Reputation: 2176
I've been working on a digital signature node.js app then I faced strange behaviour which I couldn't figure out.
first I generated public/private key pair as described here
then I implemented the following script
const crypto = require('crypto');
const fs = require('fs');
const privateKey = fs.readFileSync('./private_key.pem');
const publicKey = fs.readFileSync('./public_key.pem');
const hashAlg = 'sha256'
const data = Buffer.from('test signature'.repeat(100), 'utf8');
let bytes = []
// sign
const sign = crypto.createSign(hashAlg);
sign.update(data);
const signature = sign.sign(privateKey);
fs.writeFileSync(`./signature.${hashAlg}`, publicKey);
const verifier = crypto.createVerify(hashAlg);
verifier.update(data);
const result = verifier.verify(publicKey, signature);
for(let i=0; i < publicKey.length ; i++){
try{
const verifier2 = crypto.createVerify('RSA-SHA256');
verifier2.update(data);
const invalidPublicKey = Buffer.from(publicKey);
invalidPublicKey[i] = invalidPublicKey[i]+1;
const result2 = verifier2.verify(invalidPublicKey, signature);
if(result2) {
bytes.push(i);
};
} catch (e) {
// error to be handled
}
}
if(bytes.length){
console.log('****************');
console.log(`key length: ${publicKey.length}`); // 451
console.log('Bytes to be changed, and the verify would be valid');
console.log(bytes.join(',')); // 49, 450
console.log('****************');
}
How can different public key validate signature, Am I missing something here?
Upvotes: 1
Views: 137
Reputation: 39010
So given you apparently used OpenSSL rsa -pubout
from an RSA-2048 keypair, if this was on Unix:
the character at offset 49 in the PEM file encodes parts of the bytes at offsets 16 and 17 (specifically the bottom 4 bits of offset 16 and top 2 bits of offset 17). Those are the 2-byte NULL representing the parameters part of the AlgorithmIdentifier in the X.509 SubjectPublicKeyInfo format. For RSA there are no algorithm parameters (which is why the encoding uses NULL) and while this field should still be decoded perhaps nodejs doesn't bother to do so, knowing it's not needed and will be ignored.
the character at offset 450 in the PEM file is the newline terminating the footer line. Although required by the format definition, it isn't necessary to actually parse this to extract the contents of the file, namely the public key blob, and perhaps nodejs doesn't.
Upvotes: 2