我想使用 JavaScript webcrypto API 验证 CMS 签名的消息。该消息是根据 RFC 3161 的时间戳响应的一部分。
因此,我获取签名、内容(来自 encapContentInfo)和公钥,并将其传递给导入密钥并验证签名的以下函数:
function verify(signature, data, publicKey, callback) {
console.log("pubkey: " + publicKey);
console.log("data: " + data);
console.log("signature: " + signature);
crypto.subtle.importKey(
"spki",
new Uint8Array(hexToArray(publicKey)),
{
name: "RSASSA-PKCS1-v1_5",
hash: {name: "SHA-1"}
},
false,
["verify"]
)
.then(function(publicKey){
console.log(publicKey);
crypto.subtle.verify(
{
name: "RSASSA-PKCS1-v1_5",
hash: {name: "SHA-1"}
},
publicKey,
new Uint8Array(hexToArray(signature)),
new Uint8Array(hexToArray(data))
)
.then(function(isvalid){
console.log("valid: " + isvalid);
})
.catch(function(err){
throw(err);
});
})
.catch(function(err){
throw(err);
});
}
输出如下:
pubkey: 30820122300d06092a864886f70d01010105000382010f003082010a0282010100a9ac33b296da7177999d464f47aa4a40d57d58dcfd93beae68913ab75cb77fe36c4b52b3b55a53cce10f70880a81aba4ffdc1d4826fe645cbabcd1e0b4eceff702f6fb378670128eadbe39a4a9e484c1d01f95fcfcbd44ca091dcc344e0356ca8967f54f7f6acc0dd5af8c1a4f77003fe01c3b98d6611d52b3fe432962544e142cc6f99163ccb7798bb8d4aea948d0cd6f72b740915b87ca2824ac9ec958ab0e5eacb36a7a66be091e826f862849026aa911e3b1a84487f6654aad7f3be4d1d9d312b2f9fcd7c69836ae893060393a47b310a6a4b03eeea6c8659df57782fa75855007d5ffb622ff8d229edd57c0771149b7fc827780fcde0c02f82bc2977d250203010001
data: 306b020101060c2b0601040181ad21822c16013031300d0609608648016503040201050004201b14e43e38297d534d827e351c15347f9eebc973258c8b555c044de46c5a0f02021424e3f636950c119fb3ebdb289d60d7bc637f3bd9180f32303136303431393139333931395a
signature: 7a65069868d97fb0ffcd53bca6b80daa671e1b0ac1a1d262ba2fba1525d0ca8e4998d4f49cba990f9a89c52003457ca1bbb037dee8e5e64c617af0c1ea72215b648477b052165810f4f6eb7f869ac19373b2aad1a2b5a809b8b758bdad540a5cd1f33d3c80870c7ae9c6db61dd7c7f8c346ee3c7aadc16f90ed87833a4ba771cbdc930a6dfb3fd16f5ab57de212deddc4d49c11ef825a8d996ba40e0e07c7c5788000d61169fe7512c97d29f7ff4b8ce2842e5b339dae5cef1eb517457b3e8b98bc887dda952b6346bd8345e5eb2cdd976fe5688d375551bc2a20cd7aafd1bbf6a9d102ad2a8dea620ad3ed6763f0841ec020dc1ad485ed1448ae5f5d511ef8f
CryptoKey {}
valid: false
如您所见,验证失败,但我很确定签名是有效的,因为这个时间戳服务器被很多人使用。
我的实施有什么问题吗?
我尝试在 Firefox 扩展中执行此操作。
编辑:似乎需要使用 signedAttrs 字段的 DER 值,对其进行哈希处理,然后使用证书对其进行验证。