Reputation: 685
The Java 8 code below results in the message "signature NOT signed by matching key" and I can't understand why. Any ideas why its not verifying?
My best guess is that it is something to do with the way the private key or certificate are being generated by openssl, but from my reseach it seems I'm using the correct commands. What I'm trying to do is load a private key, sign a message, then verify the signature against a public key contained in an x509 certificate.
The privatekey.pkcs8.key file was generated using MS windows based openssl using the following commands:
openssl.exe" genrsa -out privatekey.pem 1024
openssl pkcs8 -in privatekey.pem -inform PEM -topk8 -out privatekey.pkcs8.key -outform DER -nocrypt
The publickey.cer was also generated using MS windows based openssl, using the following commands:
openssl req -x509 -key privatekey.pem -days 365 -out publickey.cer -new
The Java code I've been using in an attempt to verify the signature is as follows:
public static void main(String[] args) throws Exception{
new TestSigs();
}
public TestSigs {
byte[] signature = generateSignatureForMessage("src/cryptoprivatekey.pkcs8.key", "Hello");
verifySignature("src/crypto/publickey.cer", signature);
}
public byte[] generateSignatureForMessage(String privateKeyPath, String message) throws Exception {
RSAPrivateKey privKey = loadPrivateRSAKeyFromFile(privateKeyPath);
Signature s = Signature.getInstance("SHA256withRSA");
s.initSign(privKey);
s.update(ByteBuffer.wrap(message.getBytes()));
byte[] signature = s.sign();
return signature;
}
private void verifySignature(String publicKeyPath, byte[] signature) throws Exception {
Certificate cert = loadCertificate(publicKeyPath);
Signature s = Signature.getInstance("SHA256withRSA");
s.initVerify(cert);
if(s.verify(signature)) {
System.out.println("signature signed by matching key");
} else {
System.out.println("signature NOT signed by matching key");
}
}
private Certificate loadCertificate(String filename) throws FileNotFoundException, CertificateException {
FileInputStream fis = new FileInputStream(filename);
BufferedInputStream bis = new BufferedInputStream(fis);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
return cf.generateCertificate(bis);
}
private RSAPrivateKey loadPrivateRSAKeyFromFile(String keyPath) throws Exception {
byte[] privKeyBytes = loadRSAKeyBytesFromFile(keyPath);
KeyFactory kFact = KeyFactory.getInstance("RSA");
KeySpec ks = new PKCS8EncodedKeySpec(privKeyBytes);
return (RSAPrivateKey)kFact.generatePrivate(ks);
}
Upvotes: 3
Views: 4741
Reputation: 9338
Your signature (no pun) of the verifySignature
method is a tell tale that your implementation can not work. For a Signature
to be checked, the processor needs to hava access to both the signed data, and the signature. Which your method does not provide :
private void verifySignature(String publicKeyPath, byte[] signature)
I suggest you modify it to be symetrical to the generateSignatureForMessage
method, that is :
sign
, or verify
)Which add up to an implementation akin to :
private void verifySignature(String publicKeyPath, byte[] signature, byte[] signedContent) throws Exception {
Certificate cert = loadCertificate(publicKeyPath);
Signature s = Signature.getInstance("SHA256withRSA");
s.initVerify(cert);
s.update(signedContent);
if(s.verify(signature)) {
System.out.println("signature signed by matching key");
} else {
System.out.println("signature NOT signed by matching key");
}
}
Upvotes: 3