我正在使用以下示例在 Node.js 中进行签名和验证:https ://github.com/nodejs/node-v0.x-archive/issues/6904 。验证在 Node.js 中成功,但在 WebCrypto 中失败。同样,使用 WebCrypto 签名的消息无法在 Node.js 中验证。
这是我用来验证使用 WebCrypto 从 Node.js 脚本生成的签名的代码 - https://jsfiddle.net/aj49e8sj/。在 Chrome 54.0.2840.27 和 Firefox 48.0.2 中测试
// From https://github.com/nodejs/node-v0.x-archive/issues/6904
var keys = {
priv: '-----BEGIN EC PRIVATE KEY-----\n' +
'MHcCAQEEIF+jnWY1D5kbVYDNvxxo/Y+ku2uJPDwS0r/VuPZQrjjVoAoGCCqGSM49\n' +
'AwEHoUQDQgAEurOxfSxmqIRYzJVagdZfMMSjRNNhB8i3mXyIMq704m2m52FdfKZ2\n' +
'pQhByd5eyj3lgZ7m7jbchtdgyOF8Io/1ng==\n' +
'-----END EC PRIVATE KEY-----\n',
pub: '-----BEGIN PUBLIC KEY-----\n' +
'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEurOxfSxmqIRYzJVagdZfMMSjRNNh\n' +
'B8i3mXyIMq704m2m52FdfKZ2pQhByd5eyj3lgZ7m7jbchtdgyOF8Io/1ng==\n' +
'-----END PUBLIC KEY-----\n'
};
var message = (new TextEncoder('UTF-8')).encode('hello');
// Algorithm used in Node.js script is ecdsa-with-SHA1, key generated with prime256v1
var algorithm = {
name: 'ECDSA',
namedCurve: 'P-256',
hash: {
name: 'SHA-1'
}
};
// Signature from obtained via above Node.js script
var sig64 = 'MEUCIQDkAtiomagyHFi7dNfxMrzx/U0Gk/ZhmwCqaL3TimvlswIgPgeDqgZNqfR5/FZZASYsczUAhGSXjuycLhWnvk20qKc=';
// Decode base64 string into ArrayBuffer
var b64Decode = (str) => Uint8Array.from(atob(str), x => x.charCodeAt(0));
// Get base64 string from public key
const key64 = keys.pub.split('\n')
.filter(x => x.length > 0 && !x.startsWith('-----'))
.join('');
// Convert to buffers
var sig = b64Decode(sig64);
var keySpki = b64Decode(key64);
// Import and verify
// Want 'Verification result: true' but will get 'false'
var importKey = crypto.subtle.importKey('spki', keySpki, algorithm, true, ['verify'])
.then(key => crypto.subtle.verify(algorithm, key, sig, message))
.then(result => console.log('Verification result: ' + result));
与使用 SHA-256 而不是 SHA-1 的类似问题相关的问题:使用 Node.js/crypto 生成 ECDSA 签名
我检查过的事情:
- 我解码了 Node.js 密钥并验证它们与通过 WebCrypto 生成的密钥具有相同的 OID。这告诉我我正在使用正确的曲线。
- SHA-1 被明确标识为在两个位置使用的哈希。
- ECDSA 在 Node.js 和 WebCrypto 中都有明确标识。
如何成功验证从 Node.js 收到的签名,反之亦然 - 验证从 WebCrypto 生成的 Node.js 中的签名?或者标准的实现是否存在细微的差异,导致它们不兼容?
编辑:
- WebCrypto 签名(64 字节):uTaUWTfF+AjN3aPj0b5Z2d1HybUEpV/phv/P9RtfKaGXtcYnbgfO43IRg46rznG3/WnWwJ2sV6mPOEnEPR0vWw==
- Node.js 签名(71 字节):MEUCIQDkAtiomagyHFi7dNfxMrzx/U0Gk/ZhmwCqaL3TimvlswIgPgeDqgZNqfR5/FZZASYSczUAhGSXjuycLhWnvk20qKc=
已验证的 Node.js 签名是 DER 编码的,而 WebCrypto 签名不是。