I am developing Distributed digital signature that signs a document and send it through network to the Application Server.I am using socket programming in java to do it. I think
I'm pretty sure that the BC implementation uses X9.63 encoding, so these would be rather standardized encodings. You will need to add the Bouncy Castle provider to your JRE (Security.addProvider(new BouncyCastleProvider())
, see the bouncy documentation.
public static void showECKeyEncodings() {
try {
KeyPairGenerator kp = KeyPairGenerator.getInstance("ECDSA");
ECNamedCurveParameterSpec ecSpec = ECNamedCurveTable
.getParameterSpec("prime192v1");
kp.initialize(ecSpec);
KeyPair keyPair = kp.generateKeyPair();
PrivateKey privKey = keyPair.getPrivate();
byte[] encodedPrivKey = privKey.getEncoded();
System.out.println(toHex(encodedPrivKey));
PublicKey pubKey = keyPair.getPublic();
byte[] encodedPubKey = pubKey.getEncoded();
System.out.println(toHex(encodedPubKey));
KeyFactory kf = KeyFactory.getInstance("ECDSA");
PublicKey pubKey2 = kf.generatePublic(new X509EncodedKeySpec(encodedPubKey));
if (Arrays.equals(pubKey2.getEncoded(), encodedPubKey)) {
System.out.println("That worked for the public key");
}
PrivateKey privKey2 = kf.generatePrivate(new PKCS8EncodedKeySpec(encodedPrivKey));
if (Arrays.equals(privKey2.getEncoded(), encodedPrivKey)) {
System.out.println("That worked for the private key");
}
} catch (GeneralSecurityException e) {
throw new IllegalStateException(e);
}
}
Elliptic curve points are almost always encoded using the encoding specified in X9.62.
It is optional to use point compression. It is trivial to encode using point compression, but decoding a compressed point needs a bit more work, so unless you really need to save the extra bytes, I would not bother. Let me know if you need it, and I will add the details. You can recognize X9.62 encoded points with point compression by the first byte, which will be 0x02 or 0x03.
Encoding without point compression is really simple: start with a 0x04 (to indicate no compression). Then follow with first the x coordinate, then the y coordinate, both zero-padded on the left up to the size in bytes of the field:
int qLength = (q.bitLength()+7)/8;
byte[] xArr = toUnsignedByteArray(x);
byte[] yArr = toUnsignedByteArray(y);
byte[] res = new byte[1+2*qLength];
res[0] = 0x04;
System.arraycopy(xArr, 0, res, qLength - xArr.length, xArr.length);
System.arraycopy(yArr, 0, res, 2* qLength - yArr.length, nLength);
Decoding this is of course trivial.