I am trying to use SECP-256K1 (Bitcoin's ECC curve) to do a SHA256withECDSA signature on some data with the code posted below. The codes do not always work properly and can be rather erratic and unstable at times.
I would like help stabilizing the code below.
Code for generating ECC keypair on Signer's end:
AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC");
parameters.init(new ECGenParameterSpec("secp256k1"));
ECParameterSpec ecParameterSpec = parameters.getParameterSpec(ECParameterSpec.class);
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
keyGen.initialize(ecParameterSpec);
KeyPair ecKeyPair = keyGen.generateKeyPair();
ECPublicKey deviceEcPub = (ECPublicKey) ecKeyPair.getPublic();
ECPrivateKey deviceEcPriv = (ECPrivateKey) ecKeyPair.getPrivate();
Convert the ECC public key into 04<Public X Axis><Public Y Axis>
format as per Bitcoin specifications of public keys:
int cursor = 0;
byte[] devicePubKey = new byte[65];
devicePubKey[cursor] = (byte) 0x04;
cursor++;
System.arraycopy(deviceEcPub.getW().getAffineX().toByteArray(), 0, devicePubKey, cursor, 32);
cursor += 32;
System.arraycopy(deviceEcPub.getW().getAffineY().toByteArray(), 0, devicePubKey, cursor, 32);
Sign some data on the Signer's end:
Signature sig = Signature.getInstance("SHA256withECDSA");
sig.initSign(deviceEcPriv);
sig.update(data, 0, data.length);
byte[] signature = sig.sign();
Verifier's end receive the 04<Public X Axis><Public Y Axis>
encoded public key and converts from a X,Y coordinates into an actual ECC Public Key for use:
byte[] x = new byte[32];
byte[] y = new byte[32];
// Skips the first byte containing the 0x04 byte and copies the rest
System.arraycopy(devicePubKey, 1, x, 0, 32);
System.arraycopy(devicePubKey, 33, y, 0, 32);
Verifier uses the X and Y coordinates and reconstructs the ECPublicKey:
AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC");
parameters.init(new ECGenParameterSpec("secp256k1"));
ECParameterSpec ecParameterSpec = parameters.getParameterSpec(ECParameterSpec.class);
ECPublicKeySpec ecPublicKeySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(x), new BigInteger(y)), ecParameterSpec);
ECPublicKey publicKey = (ECPublicKey) KeyFactory.getInstance("EC").generatePublic(ecPublicKeySpec);
Executes the verification by the Verifier on the data and signature supplied:
Signature sig = Signature.getInstance("SHA256withECDSA");
sig.initVerify(publicKey);
sig.update(data, offset, length);
return sig.verify(signature);
The result of verification is sometimes True
and sometimes False
with seemingly random looking occurrences.
I would like advise on the above code to ensure that it doesn't have erratic behaviours.