user_4685247
user_4685247

Reputation: 2985

Constructing ECPublicKey from ANSI X9.62 encoded bytes

I need to validate the signature generated remotely, by ECDSA secp256k1 curve. I get 64 bytes, representing the raw bytes of r and s. And the ANSI X9.62 encoded public key ([0x04, X (32 bytes), Y (32 bytes)]). How can I verify the signature using this data?

Upvotes: 4

Views: 1742

Answers (2)

k_o_
k_o_

Reputation: 6288

This code is decoding the plain text form from the curve's point byte array and checks a signature:

// extract the key with known domain parameters
            ECGenParameterSpec ecGenParameterSpec = new ECGenParameterSpec("secp256k1");
            AlgorithmParameters algorithmParameters = AlgorithmParameters.getInstance("EC");
            algorithmParameters.init(ecGenParameterSpec);
            ECParameterSpec ecParameterSpec = algorithmParameters.getParameterSpec(ECParameterSpec.class);
            ECPoint point = ECPointUtil.decodePoint(ecParameterSpec.getCurve(), pubKey);
            KeyFactory keyFactory = KeyFactory.getInstance("EC");
            ECPublicKeySpec ecPublicKeySpec = new ECPublicKeySpec(point, ecParameterSpec);
            ECPublicKey ecPublicKey = (ECPublicKey) keyFactory.generatePublic(ecPublicKeySpec);

// verify the signature, here using SHA256
            Signature signature = Signature.getInstance("SHA256withECDSA");
            signature.initVerify(ecPublicKey);
            signature.update(data);
            boolean valid = signature.verify(receivedSignature));

ECPointUtil is coming from BouncyCastle, but it is also possible to parse it. Skip the first 04 from the encoding and then convert the next 32 bytes with BigInteger to the x and y coordinate.

Upvotes: 0

JanSLO
JanSLO

Reputation: 388

Assuming you already have x and y as BigIntegers:

// Create the W point
ECPoint w = new ECPoint(x, y);

// Create the ECField from hey integer (p)
ECField field = new ECFieldFp(new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16));

// Create the EllipticCurve with a and b
EllipticCurve curve = new EllipticCurve(field, new BigInteger("0"), new BigInteger("7"));

// Create the G point:
BigInteger gx = new BigInteger("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16);
    BigInteger gy = new BigInteger("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16);
ECPoint g = new ECPoint(gx, gy);

// Create ECParameterSpec
ECParameterSpec spec = new ECParameterSpec(curve, new ECPoint(gx, gy), new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16), 1);

// Create the KeySpec:
KeySpec keySpec = new ECPublicKeySpec(w, spec);

// Generate the key
KeyFactory keyFactory = KeyFactory.getInstance("EC");
PublicKey key = keyFactory.generatePublic(keySpec);

The constants used here are available here

Upvotes: 3

Related Questions