gus2000
gus2000

Reputation: 1

Java JCA ECDH Create public key from raw encoded X Point

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

Answers (1)

dave_thompson_085
dave_thompson_085

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

Related Questions