为什么解密的哈希与签名中的加密哈希不匹配?
Why the decrypted hash does not match the encrypted hash in the signature?
根据我的理解,签名中由私钥加密的哈希值应该与有效负载的哈希值相匹配。我写了一个小节点程序来测试这个概念,但是即使验证通过了哈希也无法匹配。
下面是我试过的。
import crypto from 'crypto';
// generate some stub keys for the test program
const { publicKey, privateKey } = crypto.generateKeyPairSync('rsa', {
modulusLength: 2048,
publicKeyEncoding: {
type: 'spki',
format: 'pem',
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
},
});
// the payload to be signed
const payload = 'helloWorld';
// create the signature
const signatureFunction = crypto.createSign('SHA256');
signatureFunction.write(payload);
signatureFunction.end();
const signature = signatureFunction.sign(privateKey, 'base64');
// verify the signature
const verifyFunction = crypto.createVerify('SHA256');
verifyFunction.write(payload);
verifyFunction.end();
// the result is "true" which means my public key can verify the encrypted hash
console.log(verifyFunction.verify(publicKey, signature, 'base64'));
// decrypt and check what is the hash
const decryptedHash = crypto.publicDecrypt(publicKey, Buffer.from(signature, 'base64'));
console.log(`decryptedHash: ${decryptedHash.toString('base64')}`);
// manually generate the hash
const manualHash = crypto
.createHash('SHA256')
.update(payload)
.digest('base64');
console.log(`manualHash: ${manualHash}`);
下面是输出:
true
decryptedHash: MDEwDQYJYIZIAWUDBAIBBQAEIBHU3cNX4IIpaNv9ImtuHCqsAY0HalTaT2Xh3IGAaErD
manualHash: EdTdw1fggilo2/0ia24cKqwBjQdqVNpPZeHcgYBoSsM=
我的问题是为什么 decryptedHash
与 manualHash
不匹配?
好的,我设法找出原因.. 显然 decryptedHash
并不是真正的实际哈希值。我需要去 https://lapo.it/asn1js/ to convert it. I am not very well-verse in that area but I manage to find some clue by looking at this post https://crypto.stackexchange.com/questions/80768/openssl-extract-hash-algorithm-from-signature-data-pkcs1-v-1-5
decryptedHash
似乎是 DER ANS1 格式。
向我的程序添加了 3 行,我能够匹配 manualHash
const valueGotFromLapoSite = '11D4DDC357E0822968DBFD226B6E1C2AAC018D076A54DA4F65E1DC8180684AC3';
const myHash = Buffer.from(valueGotFromLapoSite, 'hex').toString('base64');
console.log(`myHash: ${myHash}`);
输出:
true
decryptedHash: MDEwDQYJYIZIAWUDBAIBBQAEIBHU3cNX4IIpaNv9ImtuHCqsAY0HalTaT2Xh3IGAaErD
manualHash: EdTdw1fggilo2/0ia24cKqwBjQdqVNpPZeHcgYBoSsM=
myHash: EdTdw1fggilo2/0ia24cKqwBjQdqVNpPZeHcgYBoSsM=
根据我的理解,签名中由私钥加密的哈希值应该与有效负载的哈希值相匹配。我写了一个小节点程序来测试这个概念,但是即使验证通过了哈希也无法匹配。
下面是我试过的。
import crypto from 'crypto';
// generate some stub keys for the test program
const { publicKey, privateKey } = crypto.generateKeyPairSync('rsa', {
modulusLength: 2048,
publicKeyEncoding: {
type: 'spki',
format: 'pem',
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
},
});
// the payload to be signed
const payload = 'helloWorld';
// create the signature
const signatureFunction = crypto.createSign('SHA256');
signatureFunction.write(payload);
signatureFunction.end();
const signature = signatureFunction.sign(privateKey, 'base64');
// verify the signature
const verifyFunction = crypto.createVerify('SHA256');
verifyFunction.write(payload);
verifyFunction.end();
// the result is "true" which means my public key can verify the encrypted hash
console.log(verifyFunction.verify(publicKey, signature, 'base64'));
// decrypt and check what is the hash
const decryptedHash = crypto.publicDecrypt(publicKey, Buffer.from(signature, 'base64'));
console.log(`decryptedHash: ${decryptedHash.toString('base64')}`);
// manually generate the hash
const manualHash = crypto
.createHash('SHA256')
.update(payload)
.digest('base64');
console.log(`manualHash: ${manualHash}`);
下面是输出:
true
decryptedHash: MDEwDQYJYIZIAWUDBAIBBQAEIBHU3cNX4IIpaNv9ImtuHCqsAY0HalTaT2Xh3IGAaErD
manualHash: EdTdw1fggilo2/0ia24cKqwBjQdqVNpPZeHcgYBoSsM=
我的问题是为什么 decryptedHash
与 manualHash
不匹配?
好的,我设法找出原因.. 显然 decryptedHash
并不是真正的实际哈希值。我需要去 https://lapo.it/asn1js/ to convert it. I am not very well-verse in that area but I manage to find some clue by looking at this post https://crypto.stackexchange.com/questions/80768/openssl-extract-hash-algorithm-from-signature-data-pkcs1-v-1-5
decryptedHash
似乎是 DER ANS1 格式。
向我的程序添加了 3 行,我能够匹配 manualHash
const valueGotFromLapoSite = '11D4DDC357E0822968DBFD226B6E1C2AAC018D076A54DA4F65E1DC8180684AC3';
const myHash = Buffer.from(valueGotFromLapoSite, 'hex').toString('base64');
console.log(`myHash: ${myHash}`);
输出:
true
decryptedHash: MDEwDQYJYIZIAWUDBAIBBQAEIBHU3cNX4IIpaNv9ImtuHCqsAY0HalTaT2Xh3IGAaErD
manualHash: EdTdw1fggilo2/0ia24cKqwBjQdqVNpPZeHcgYBoSsM=
myHash: EdTdw1fggilo2/0ia24cKqwBjQdqVNpPZeHcgYBoSsM=