My task is to verify a digital signature signed using ED25519. The signature that was generated using typescript Crypto and I need to verify in Java. I am using BouncyCastle to verify and here is my code.
byte[] decodedSign = Base64.getDecoder().decode("<signature>");
byte[] message = Base64.getDecoder().decode("<encoded message String">);
byte[] publicKeyBytes = Base64.getDecoder().decode("<public key>");
Ed25519PublicKeyParameters publicKey = new Ed25519PublicKeyParameters(publicKeyBytes, 0);
// Verify
Signer verifier = new Ed25519Signer();
verifier.init(false, publicKey);
verifier.update(message, 0, message.length);
boolean verified = verifier.verifySignature(decodedSign);
System.out.println("Verification: " + verified); // Verification: false
What I have is encoded message, encoded signature and encoded public key. I decoded all of these and used above code to verify the signature. I always get verified false. Please help if I am missing something or use different approach or this is not a right approach.
I tried the above code snippet and keep getting 'false'. I should get 'true'.
Update - Here is typescript to create key pair
const { privateKey, publicKey } = crypto.generateKeyPairSync("ed25519");
const signingKey = privateKey.export({ type: "pkcs8", format: "der"}).toString("hex");
const verifyKey = publicKey.export({ type: "spki", format: "der" }).toString("hex");
Signature -
const signature = crypto.sign(null, Buffer.from(JSON.stringify(jsondata)), privateKey);
Typescript dumps the encoded json data and the signature into one file and public key into another file.
The "spki" format in your posted code is not a 'raw' or 'bare' publickey, and whatever you referenced in a comment but didn't show is apparently wrong also.
Here is a correct way (using Bouncy LWAPI) plus 4 alternatives using JCA (with either the Bouncy provider, or the standard Oracle/OpenJDK provider in Java 15 up). I don't have/use typescript but your 'typescript' is really just nodejs. I output all the data from it in base64: classic base64 for data signature, and spki-format key, base64url for raw key because that's what JWK natively uses and Java can handle it just as easily. You could use hex or any other bit-preserving encoding as long as you are consistent.
Note that using
new Ed25519PublicKeyParameters(spki)throws an exception telling you it is the wrong length, which if you know what you are doing is enough to identify the problem. Using the(spki,0)ctor instead suppresses the exception but the result is still completely and totally wrong; this is like putting masking tape over the light on your dashboard that indicates your brakes have failed -- it doesn't make anything better, it just prevents you from recognizing you are in danger.