1

I base my work on this answer

I'm trying to verify a file using a public key. Here is my code:

var hash = crypto.createHash("sha256");
hash.setEncoding("hex");
var fd = fs.createReadStream("path/to/my/file");
fd.on("end", function() {
    hash.end();
    var fileHash = hash.read();    
    const publicKey = fs.readFileSync('keys/public_key.pem');
    const verifier = crypto.createVerify('RSA-SHA256');
    const testSignature = verifier.verify(publicKey, fileSignature, 'base64');
    console.log("testSignature: \n" + testSignature);
    if (testSignature === fileHash)
        console.log("ok");
    else
        console.log("not ok");
});
fd.pipe(hash);

I don't know if this code is correct, but testSignature is equal to "false" when i printed it in the console. Why ?

testSignature:
false

The encrypted hash (the fileSignature variable) is correct. The base64 string is the same as I expect.

Any idea about what is wrong in my code ? Thanks

EDIT

Here is the code that generates the signature:

var hash = crypto.createHash("sha256");
hash.setEncoding("hex");
var fd = fs.createReadStream("path/to/file");
fd.on("end", function() {
    hash.end();
    var fileHash = hash.read();
    var privateKey = fs.readFileSync('keys/private_key.pem');
    var signer = crypto.createSign('RSA-SHA256');
    signer.update(fileHash);
    fileSignature = signer.sign(privateKey, 'base64');
});
fd.pipe(hash);
iAmoric
  • 1,787
  • 3
  • 31
  • 64
  • Where do you use `openssl` here? (what's the tag for?) – Yan Foto May 09 '19 at 15:40
  • I just reused the tags from the question I've mentioned – iAmoric May 09 '19 at 16:06
  • Actually I used openssl to create the keys. I've updated the tags – iAmoric May 09 '19 at 16:23
  • What node version are you using? – Heraldo May 09 '19 at 17:29
  • md5 and sha256 are different and incompatible hash algorithms. From what I can glean from the very poor documentation, you should pass the file contents (not the hash of the file contents) to the `verify.update()` method and it will do the hashing internal to the class. When the file is finished then you call the `verify.verify()` method. – President James K. Polk May 09 '19 at 17:48
  • @Heraldo v10.15.3 – iAmoric May 09 '19 at 18:02
  • @JamesKPolk it's not what it's done in the answer i've mentionned. But I've changed the hash to `sha256` to try, same problem -> `false` – iAmoric May 09 '19 at 18:07
  • @iAmoric: I cannot test it myself so I cannot confirm. For reasons I can't fathom, the documentation says very little of substance. However, it would be a strange API to have an `update()` method that expects a hash of data rather than the data itself. Also, in any question like this, we must also see the code that generates the signature. – President James K. Polk May 09 '19 at 19:07
  • @JamesKPolk I've edited my question by adding the code that generates the signature – iAmoric May 09 '19 at 19:42
  • 1
    These edits change things a lot, and render my previous comments obsolete. One thing to be alert for is lack of symmetry in crypto operations. Notice how you call `update()` in the signature generation, but not in the signature verification? That's a clue that you're doing something wrong. `fileHash` is not used at all. – President James K. Polk May 09 '19 at 19:47
  • Yes I noticed it too, but my code is totally based on it : https://stackoverflow.com/a/34024428/6240756 where there is no update call in the veriffication and it seems to work correctly – iAmoric May 09 '19 at 19:53
  • That answer looks completely wrong to me. There are many completely wrong answers on stackoverflow that are accepted and highly rated. I'm not a javascript expert so you should definitely not take my word for it, but you should also not blindly accept an answer just because it is both accepted and highly rated. – President James K. Polk May 09 '19 at 20:11
  • I'm not saying that and I agree with you, according to the doc there should be a `verify.update()` but I don't understant what content i need to provide to this function. Also in my code the fileHash is compared with testSignature. Both should be equal – iAmoric May 09 '19 at 20:16
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/193115/discussion-between-iamoric-and-james-k-polk). – iAmoric May 09 '19 at 20:19

1 Answers1

2

Assuming path/to/my/file is the file of which contents you need to verify, you have to provide its contents to verifier.update(). Try the following:

const input = fs.readFileSync('path/to/my/file'); // load data contents
const publicKey = fs.readFileSync('keys/public_key.pem').toString(); // load the signature, as a string!
const verifier = crypto.createVerify('RSA-SHA256');
verifier.update(input); // provide data contents to the verifier
const testSignature = verifier.verify(publicKey, fileSignature, 'base64');
console.log("testSignature: \n" + testSignature);

Also, make sure that fileSignature is a string value and not a Buffer. For some reason, which I am still trying to figure why, if you pass a Buffer object to verifier.verify it will not work:

const fileSignatureBuffer = fs.readFileSync('signature.sha256');
const fileSignatureString = fileSignatureBuffer.toString();
// load public key, create the verifier, provide data contents to verifier, etc.
const testSignature = verifier.verify(publicKey, fileSignatureBuffer); // false
const testSignature = verifier.verify(publicKey, fileSignatureString, 'base64'); // true

EDIT: If you are using a hash as input to the signing step, then you have to pass the same hash in the verify step. Then code would look as follows:

const publicKey = fs.readFileSync('keys/public_key.pem').toString(); // load the signature, as a string!
const verifier = crypto.createVerify('RSA-SHA256');
verifier.update(fileSignature); // provide the file signature to the verifier
const testSignature = verifier.verify(publicKey, fileSignature, 'base64');
console.log("testSignature: \n" + testSignature);
Heraldo
  • 407
  • 2
  • 11
  • I just tied it but i still have `false` as result . `fileSignature` is a string, not a buffer – iAmoric May 09 '19 at 19:48
  • 1
    I see that you are signing the file hash, not the input file content itself, so you have to provide the hash to `verify.update()` instead of the input file content. – Heraldo May 09 '19 at 20:12