Reputation: 1
I tried to calculate ECDH secret using my private EC key and a ephemeral peer key. The peer key is in raw compressed byte format (i.e 0x02 + 32 bytes). I manage to do it using bouncycastle library, thank to the "ECPoint org.bouncycastle.math.ec.ECCurve.decodePoint(byte[] arg0)" method. Unfortunately, I'm not able to find a way to perform the same operation using Java JCA. Bouncycastle is not an option because the final project will be in a Java Card.
// convert bouncycastle public key to Java public key
ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("secp256k1");
ECPoint Q = publicKeyParams.getQ();
ECPublicKeySpec pubSpec = new ECPublicKeySpec(Q, ecSpec);
PublicKey javaPublicKey = keyFactory.generatePublic(pubSpec);
give "The constructor ECPublicKeySpec(ECPoint, ECPublicKeySpec) is undefined"
Upvotes: 0
Views: 461
Reputation: 38781
Actually an X9-style compressed public key can begin with 0x02 or 0x03, depending on the parity of the omitted Y-coordinate.
You can read this with standard JCA KeyFactory
by adding a fixed prefix that turns it into the correct DER encoding; this is the same idea as Loading raw 64-byte long ECDSA public key in Java except with a different prefix due to the different curve, the inclusion of the 02/03 byte, and the different DER lengths.
// given byte[] raw containing 33 bytes: 0x02/0x03 then 32-byte X-coordinate, on secp256k1
byte[] head = Base64.getDecoder().decode("MDYwEAYHKoZIzj0CAQYFK4EEAAoDIgA=");
byte[] combine = Arrays.copyOf(head,head.length+raw.length);
System.arraycopy(raw,0, combine,head.length, raw.length);
PublicKey pub = KeyFactory.getInstance("EC").generatePublic(new X509EncodedKeySpec(combine));
Upvotes: 0