5
votes

I am trying to use the Node.js crypto module to verify a signature for some data. I am using Node.js 0.8.0.

The data in a file has been hashed using the MD5 algorithm and signed using a private RSA key, and the signature saved to a separate file. This has all been done using Java libraries.

If I use openssl to verify the signature this is successful, using:

openssl dgst -verify mykey.pem -signature example.sig hello.txt

It responds with Verified OK. If I change a single character of hello.txt it does not verify. I can add a -MD5 parameter to the above command and it still works, but I presume this is the default, but if I say -MD4 or -SHA it does not verify. This is all good.

If I then try to use the Node crypto module, which wraps openssl, I cannot get this verification to work.

My example code is:

var crypto = require("crypto");
var fs = require("fs");

var data = fs.readFileSync("./hello.txt");
var pubkey = fs.readFileSync("./mykey.pem", "utf8");
var signature = fs.readFileSync("./example.sig");

var verifier = crypto.createVerify ('RSA-MD5');
verifier.update (data);
var success = verifier.verify (pubkey, signature);
console.log(success);

This allways outputs false. I have tried:

  • reading the data as 'utf8' and 'ascii' encoded, as it is a text file.
  • reading the key as 'ascii' encoded (I have reason to think the key is fine as I was getting some exceptions when I was loading an incorrectly encoded key at one point)
  • using MD5 instead of RSA-MD5 as the digest algorithm
  • loading a base64 encoded signature rather than binary, and putting the 'base64' parameter on the verify function.

Am I misinterpreting that my code is performing the same operation as the openssl command line I show here? Any suggestions for how to resolve this?

Update: I have also tried using a self-signed trusted certificate rather than just a key. I have confirmed that openssl verifies the certificate, and yet the node crypto library does not verify the file.

1
Are you sure it's RSA and not DSA? (Although does not seem like DSA has MD5 variant, but I'm not sure.) Check inside mykey.pem. And do read your key as 'ascii'; it has no significance, but is the Right Way.Andrey Tarantsov

1 Answers

7
votes

I finally found that it was a signature format problem - verify has a third parameter, which defaults to 'binary' when I had the 'hex' format.

The final solution moved to using the SHA1 hash and now runs on node 0.10 which has a slightly different stream API, but the relevant line that has changed is:

result = verifier.verify(publicKey, signature, 'hex');