crypto.subtle.sign()未执行签名?请求排查问题
/* 获取"message"文本框内容,编码为签名操作可用格式 */ function getMessageEncoding() { const messageBox = 'hello world!'; let message = messageBox.value; let enc = new TextEncoder(); return enc.encode(message); } async function main() { let encoded = getMessageEncoding(); window.crypto.subtle.sign( { name: "ECDSA", hash: { name: "SHA-384" }, }, {"alg":"ES256","crv":"P-256","d":"KRiXxoIFHmBQJdoCsqB8Bc9_f2Z-QCdRgoydMKdoL04","ext":true,"key_ops":["sign"],"kty":"EC","x":"FKwqyGd4i2NAl8RUXCCBRCAIbcpeGyfyXwgA_AWHb8Y","y":"njxhw5O6zGVkBlcPDKYj0E-6VO1giHTUkJWBhgKNqd8"}, encoded, ).then(signature => { console.log(signature); alert('test'); }); alert(signature); } main();
(注:上述私钥为测试用,非生产环境密钥)
运行以上代码后无任何反应,预期将签名输出到JavaScript控制台,以下是具体排查思路:
DOM元素获取错误:
getMessageEncoding函数中messageBox被赋值为字符串'hello world!',字符串没有value属性,执行messageBox.value会直接抛出错误,导致后续代码无法执行。修复时如果是要获取输入框内容,需改为document.getElementById('message')这类方式获取DOM元素;如果直接用固定字符串,直接用message = 'hello world!'即可。异步变量作用域错误:
main函数中最后一行alert(signature)的signature是在then回调内部定义的变量,外部无法访问,且这行代码会在sign异步操作完成前执行,此时signature未定义,会抛出错误。需删除该行,或把逻辑移到then回调内。密钥格式错误:
window.crypto.subtle.sign的第二个参数要求传入CryptoKey对象,而代码直接传入了JWK格式的普通对象,无法被识别。需先用crypto.subtle.importKey方法将JWK导入为CryptoKey,示例:const jwk = {"alg":"ES256","crv":"P-256","d":"KRiXxoIFHmBQJdoCsqB8Bc9_f2Z-QCdRgoydMKdoL04","ext":true,"key_ops":["sign"],"kty":"EC","x":"FKwqyGd4i2NAl8RUXCCBRCAIbcpeGyfyXwgA_AWHb8Y","y":"njxhw5O6zGVkBlcPDKYj0E-6VO1giHTUkJWBhgKNqd8"}; const privateKey = await crypto.subtle.importKey( 'jwk', jwk, { name: 'ECDSA', hash: 'SHA-256' }, true, ['sign'] );算法参数不匹配:签名时指定的哈希算法是
SHA-384,但JWK的alg是ES256(对应SHA-256),算法参数与密钥的算法不兼容,会导致签名操作失败。需将签名配置中的hash改为{ name: "SHA-256" },保持与密钥算法一致。缺少错误捕获:代码未对异步操作的错误进行捕获,即使执行出错也无法在控制台看到错误信息。建议利用
async/await配合try/catch处理错误,或在then后添加catch回调:async function main() { try { let encoded = getMessageEncoding(); const jwk = {"alg":"ES256","crv":"P-256","d":"KRiXxoIFHmBQJdoCsqB8Bc9_f2Z-QCdRgoydMKdoL04","ext":true,"key_ops":["sign"],"kty":"EC","x":"FKwqyGd4i2NAl8RUXCCBRCAIbcpeGyfyXwgA_AWHb8Y","y":"njxhw5O6zGVkBlcPDKYj0E-6VO1giHTUkJWBhgKNqd8"}; const privateKey = await crypto.subtle.importKey( 'jwk', jwk, { name: 'ECDSA', hash: 'SHA-256' }, true, ['sign'] ); const signature = await window.crypto.subtle.sign( { name: "ECDSA", hash: { name: "SHA-256" } }, privateKey, encoded ); console.log(signature); alert('test'); } catch (err) { console.error('签名失败:', err); } }
内容的提问来源于stack exchange,提问作者neubert

