使用WebCrypto API生成密钥对并签名时哈希缺失错误的解决方法
解决WebCrypto API ECDSA签名时"algorithm.hash is required"错误
问题出在调用sign方法时直接使用privateKey.algorithm作为算法参数——WebCrypto返回的ECDSA密钥算法对象里并不包含哈希算法配置,而ECDSA签名必须明确指定哈希算法才能完成数据摘要计算。
修正步骤
明确签名时的算法配置
不要直接传递privateKey.algorithm,手动构造包含hash字段的算法对象,且哈希算法要和密钥生成时的配置保持一致。修正后的代码
先保留密钥生成函数(建议明确指定哈希算法,保持前后逻辑统一):const generateKeyPair = async function() { return crypto.subtle.generateKey( { name: "ECDSA", namedCurve: "P-384", hash: "SHA-512" // 提前指定哈希算法,与签名时保持一致 }, true, ["sign", "verify"] ); }然后修改签名函数,手动构造符合要求的算法参数:
const sign = async function(privateKey: CryptoKey, buffer: BufferSource) { const signAlgorithm = { name: privateKey.algorithm.name, namedCurve: privateKey.algorithm.namedCurve, hash: "SHA-512" // 必须与密钥生成时的哈希算法一致 }; return crypto.subtle.sign(signAlgorithm, privateKey, buffer); }
补充验签实现(匹配核心需求)
如果需要完成公钥验签的逻辑,同样要手动指定哈希算法:
const verify = async function(publicKey: CryptoKey, buffer: BufferSource, signature: ArrayBuffer) { const verifyAlgorithm = { name: publicKey.algorithm.name, namedCurve: publicKey.algorithm.namedCurve, hash: "SHA-512" }; return crypto.subtle.verify(verifyAlgorithm, publicKey, signature, buffer); }
测试用例验证
修正后的签名函数可以通过原有测试,也可以扩展验证完整的签名-验签流程:
import { describe, it, expect } from "vitest"; import { generateKeyPair, sign, verify } from "../../src"; describe("sign and verify", () => { it('signs data and verifies signature correctly', async () => { const { privateKey, publicKey } = await generateKeyPair(); const data = { foo: 'bar' }; const stringifiedData = JSON.stringify(data); const buffer = Buffer.from(stringifiedData); const signature = await sign(privateKey, buffer); await expect(signature).toBeTruthy(); const isValid = await verify(publicKey, buffer, signature); expect(isValid).toBe(true); }); });
关键原因说明
WebCrypto的ECDSA密钥对象不会存储哈希算法配置,即使你在generateKey时指定了hash字段,返回的CryptoKey.algorithm也只包含name和namedCurve两个属性。因此调用sign/verify时必须手动补充hash参数,否则会触发ERR_MISSING_OPTION错误。
内容的提问来源于stack exchange,提问作者baitendbidz
相关产品推荐
相关产品推荐

