跳到主要内容
ecdsa.com
WebCrypto crypto.subtleWebCrypto

错误信息

OperationError: The operation failed for an operation-specific reason

WebCrypto crypto.subtle — browsers & Node

含义

这是 WebCrypto 有意含糊的兜底错误:密码原语本身失败了。对于使用 AES-GCM 的 decrypt(),它表示认证标签未通过验证——密钥错误、IV 错误、附加数据错误,或者密文被修改。规范有意让消息保持笼统,以免实现泄露密码学检查失败的原因。对于 sign() 和 deriveBits(),同一个名称涵盖原语内部的各种失败,因此堆栈跟踪中是哪个操作出错,比消息文本更重要。

原因

修复方法

  1. 1.

    IV 与密文一起传输,两端对称解码

    把 IV 放在密文前面,解密时再拆开,这样两端始终一致;所有地方都使用同一种 base64 变体。

    js
    // encrypt
    const iv = crypto.getRandomValues(new Uint8Array(12));
    const ct = await crypto.subtle.encrypt({ name: "AES-GCM", iv }, key, data);
    const packed = new Uint8Array([...iv, ...new Uint8Array(ct)]);
    
    // decrypt
    const buf = packedFromWire;
    const pt = await crypto.subtle.decrypt(
      { name: "AES-GCM", iv: buf.slice(0, 12) }, key, buf.slice(12),
    );
  2. 2.

    把它当作完整性判定,而不是数据损坏

    decrypt 抛出 OperationError 时,正确的响应是认定“这段密文在这个密钥下未通过认证”,并拒绝它。不要通过调整填充来重试,也不要退回到无认证的模式;检查失败正是这项安全特性在起作用。

  3. 3.

    对比两端的密钥指纹

    导出两端的密钥并分别计算哈希;如果摘要不同,问题一步就能查明。

    js
    const raw = await crypto.subtle.exportKey("raw", key);
    const fp = await crypto.subtle.digest("SHA-256", raw);
    console.log(Buffer.from(fp).toString("hex").slice(0, 16)); // compare on both sides

相关错误

浏览完整的签名错误库