I been stuck with this matter for a while. I have followed How can I get a PublicKey object from EC public key bytes? method. It's working on his example but not on mine. Not sure where went wrong. The sample works on node.js but when using the publickey, msg and signature from ECC elliptic it just always returning false.
byte[] pubKey = Hex.decode("04f491ccd1913757e10c2fe965ac764dd6af2f8bbfa47f4dddff0fe7736601701464d9fa02e6eada870ac626825e28d99bdf2d3a2742ba6dc99a56c663e875852a");
byte[] message = Hex.decode("613839633666323863616238633538623533313466626365636364326363633166646537643937383663373863373134313432646230343361313530323937657c416c6920416873616e7c43562d4d3957515253544d7c4d616c657c4d59537c323032312d30352d30355431303a33303a32392b30383a30307c3235383530303030317c39343735362d347c313234303538313030303030303130347c4b75616c61204c756d70757220486f73706974616c7c3031");
byte[] signature = Hex.decode("304502202f70fe9a8173a13daef97e8d59c9cd9aec3851c0f0568e5b5d61ddb752d1cb9e022100d9eccdcdd4b4a448bd36f3a9dafde08b55b8176f6b21bb6e1cc7d35a929dc1bf");
private static boolean isValidSignature(byte[] pubKey, byte[] message,byte[] signature) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, SignatureException, InvalidKeySpecException {
Signature ecdsaVerify = Signature.getInstance("SHA256withECDSA", new BouncyCastleProvider());
ecdsaVerify.initVerify(getPublicKeyFromBytes(pubKey));
ecdsaVerify.update(message);
System.out.println(getPublicKeyFromBytes(pubKey));
System.out.println(message);
System.out.println(signature);
return ecdsaVerify.verify(signature);
}
private static PublicKey getPublicKeyFromBytes(byte[] pubKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("P-256");
KeyFactory kf = KeyFactory.getInstance("ECDSA", new BouncyCastleProvider());
ECNamedCurveSpec params = new ECNamedCurveSpec("P-256", spec.getCurve(), spec.getG(), spec.getN());
ECPoint point = ECPointUtil.decodePoint(params.getCurve(), pubKey);
ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(point, params);
ECPublicKey pk = (ECPublicKey) kf.generatePublic(pubKeySpec);
return pk;
}
Appreciate if someone could help. warm regards.
Below is created on node:
console.log("Create D. Signature: ");
let elliptic = require('elliptic');
let sha3 = require('js-sha3');
let ec = new elliptic.ec('p256');
let key = ec.keyFromPrivate("our private key");
let msgHash = sha3.sha3_256('scv1|Ali Ahsan|CV-M9WQRSTM|Male|MYS|2021-05- 05T10:30:29+08:00|258500001|94756-4|1240581000000104|Kuala Lumpur Hospital|01');
console.log("msgHash: "+msgHash);
let signature = key.sign(msgHash); signature=signature.toDER(); signature=Buffer.from(signature).toString('hex'); console.log("signature: "+signature);
let pubPoint = key.getPublic('hex'); console.log('public key: '+pubPoint);
/*
console.log("Verify D. Signature:");
const qrContent = 'a89c6f28cab8c58b5314fbceccd2ccc1fde7d9786c78c714142db043a150297e|Ali Ahsan|CV-M9WQRSTM|Male|MYS|2021-05-05T10:30:29+08:00|258500001|94756-4|1240581000000104|Kuala Lumpur Hospital|01|304502202f70fe9a8173a13daef97e8d59c9cd9aec3851c0f0568e5b5d61ddb752d1cb9e022100d9eccdcdd4b4a448bd36f3a9dafde08b55b8176f6b21bb6e1cc7d35a929dc1bf'
const pub = '4f491ccd1913757e10c2fe965ac764dd6af2f8bbfa47f4dddff0fe7736601701464d9fa02e6eada870ac626825e28d99bdf2d3a2742ba6dc99a56c663e875852a'
const EC = require('elliptic').ec;
let ec = new EC('p256');
const key = ec.keyFromPublic(pub,'hex');
const sigIndex = qrContent.lastIndexOf('|');
const data = qrContent.slice(0, sigIndex);
const sig = qrContent.slice(sigIndex + 1, qrContent.length);
console.log(data);
console.log(sig);
console.log(key.verify(data, sig);*/
Based on the nodejs code you added you are doing SHA-3-256 (not SHA-256 which is a SHA-2 algorithm), so your Java code needs to match that. However, your posted nodejs signing code uses a different value for the data than used by either the nodejs or java verify code, which will never work. Even fixing those, your posted values still don't verify for me. However, the following slightly simplified and corrected versions of your code (with a different, arbitrary key) DO work as expected:
so you must still have something wrong that you aren't showing in your post. Compare what I did that works with what you did that doesn't.
I notice you now mention Android. I don't have Android myself but to my understanding it has a port of bouncycastle (spongycastle) not the real thing. It is conceivable that's the problem, although I would expect something so widely used not to have problems like this. But you might check against desktop Java with real bouncycastle (at least 1.55).