Reputation: 2985
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
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
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