我最近采用了一些第三方安全软件,我试图了解如何处理我们从他们那里收到的签名消息。在此过程中,我使用 Node Crypto 库来巩固我对概念的理解。
据我了解RSA-SHA256签名算法,在签名过程中:
然后客户端将原始消息、公钥和签名发送给我们。验证签名的过程如下:
如果是这种情况,那么在下面的代码片段中:
const {
generateKeyPairSync,
publicDecrypt, privateEncrypt,
createSign, createVerify,
createHash,
} = require('crypto');
const { privateKey, publicKey } = generateKeyPairSync('rsa', {
modulusLength: 2048,
publicKeyEncoding: {
type: 'spki',
format: 'pem',
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
},
});
const messageToSign = "Yma o hyd";
const signer = createSign('RSA-SHA256');
signer.update(messageToSign);
const signature = signer.sign(privateKey);
console.log('Signed message', signature.toString('hex'));
const verifier = createVerify('RSA-SHA256');
verifier.update(messageToSign);
const isVerified = verifier.verify(publicKey, signature);
console.log('isVerified:', isVerified);
const hash = createHash('SHA256').update(messageToSign).digest();
console.log('hash in hex', hash.toString('hex'));
const hashEncryptedWithPrivateKey = privateEncrypt(
privateKey,
hash,
);
console.log('encrypted hash', hashEncryptedWithPrivateKey.toString('hex'));
const signatureDecryptedWithPublicKey = publicDecrypt(
publicKey,
signature
);
console.log('Signature decrypted with public key', signatureDecryptedWithPublicKey.toString('hex'));
我希望
signatureDecryptedWithPublicKey.toString('hex')
能够匹配 hash.toString('hex')
,但事实并非如此。
签名者所做的不仅仅是 RSA 和 SHA256 的简单组合吗?
您的考虑中没有考虑填充。
为了使
hashEncryptedWithPrivateKey
等于signature
,不是必须将hash
传递给privateEncrypt()
,而是将DigestInfo
值T
的DER编码,这适用于SHA256:0x3031300d060960864801650304020105000420 || hash
,因此:
const hashEncryptedWithPrivateKey = privateEncrypt(
privateKey,
Buffer.concat([Buffer.from('3031300d060960864801650304020105000420', 'hex'), hash])
);
同样,
const signatureDecryptedWithPublicKey = publicDecrypt(
publicKey,
signature
);
不返回
hash
而是T
。