2

I wanted to perform RSA-SHA512 on a file in node.js. I could calculate sha512 hash of the given data file which matches with that of openssl's. However when trying to get the digital signature on the same hash, node.js signature differs from openssl signature. Below is an example code snippet:

var data = new Buffer(512);
data = fs.readFileSync('/tmp/data');
var pem = fs.readFileSync('/tmp/boot2-prvKey.pem');
var privateKey = pem.toString('ascii');

var signer = crypto.createSign("RSA-SHA256");
signer.update(data);
var sign = signer.sign(privateKey, 'hex');
console.log("SIGN " + sign + '\n');

Openssl command to sign the data:

openssl rsautl -sign -in /tmp/data -inkey /tmp/boot2-prvKey.pem -out sig

Both of the above generates different signatures.

I have couple of questions 1) I want to calculate RSA-SHA256 of a file, so I calculate sha256 hash of the entire file first and pass this hash as an input to signing function. Is that a correct approach? 2) If yes, what might have gone wrong in the code above ? If no, what would be the correct approach ?

node.js version I am using is 0.10.36 and openssl version is 1.0,1.

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
Amit Sheth
  • 23
  • 1
  • 3
  • "*I calculate sha256 hash of the entire file first and pass this hash as an input to signing function*" -- I don't a hash function used in the code you've provided. Is this not your real code, or do I misunderstand your description? – apsillers May 13 '15 at 13:41
  • Actually I have hash of my data file stored in /tmp/data, which is I am reading in the code above for signing. Sorry for the inappropriate file nomenclature. – Amit Sheth May 14 '15 at 03:37

2 Answers2

5

When you supply an input to a signature program, it might assume that the input is not yet hashed, and will hash it before signing. The problem here is that Node is (re-)hashing the input, while rsautl is using the input as-is. (Note that even if you separately re-hash the input before supplying it to rsautl, it's still won't match because rsautl does not use ASN1 encoding; see below.)

To make OpenSSL produce a SHA256 hash before making an RSA signature (like Node does), you need to use the dgst command with the -sha256 and -sign arguments:

openssl dgst -sha256 -sign /tmp/boot2-prvKey.pem -hex < /tmp/data

This will hash /tmp/data and sign the hash with RSA, which is exactly what Node's RSA-SHA256 signer does.

See Difference between openSSL rsautl and dgst for more information:

The simple answer is that dgst -sign creates a hash, ASN1 encodes it, and then signs the ASN1 encoded hash, whereas rsautl -sign just signs the input without hashing or ASN1 encoding.

The behavior of Node's sign method is like dgst -sign rather than rsautl -sign.

Node does not appear to offer a built-in rsautl-like mechanism for signing without hashing and ASN1-encoding. For this reason, you may need to sign the document directly, rather than operate on a hash of the document. If you really can't do that for some reason, you can download the Node rsautl module from NPM, which provides Node bindings for rsautl.

Community
  • 1
  • 1
apsillers
  • 112,806
  • 17
  • 235
  • 239
  • But see this from the comments: *"... actually I have hash of my data file stored in /tmp/data..."*. So it appears he already has the hash. I think he needs to apply the signature function to the hash. Or he needs to allow the OpenSSL command to do it all (like you show above). If he is signing, then signing an *unknown* hash or *unknown* document can be dangerous. I think the same applies to verification, but its not as bad as signing just a hash. It should be an atomic operation on the document, and not discrete operations on discrete parts. – jww May 14 '15 at 13:42
0

The problem is that your Openssl command just sign your data without hash function. You must first hash your data with openssl and with the same function as in your nodejs code (SHA-256) then sign the hash to obtain the final signature with your command: openssl rsautl -sign -in /tmp/data -inkey /tmp/boot2-prvKey.pem -out sig

You can see that in this command your havent specify any hash function.

To obtain a signature: data -> SHA-256 = hash -> RSA = signature

I havent enough time to test it and give you the right code, i hope it will be helpfull.

Paul
  • 1
  • 2
  • Hi Paul, Thanks for the reply. I did calculate hash of my data file. Hash is stored in /tmp/data. Hash(sha256) calculated with openssl and node.js matches perfectly, hence I skipped that part in the code, whereas only sign on the given hash differs. Hence I explicitly showed only signing part for both the cases. – Amit Sheth May 14 '15 at 03:51