You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js v21.6.2中crypto.subtle解密失败问题求助

解决Node.js AES-CBC解密时的参数错误问题

问题描述

在Node.js v21.6.2中实现文件加密上传云端并本地解密功能,密钥生成和加密环节正常,但解密时出现两个问题:

  1. 提示iv并非ArrayBuffer类型(实际应为该类型)
  2. 加密数据对象为undefined

尝试直接传入iv、iv.buffer、iv.buffer.slice作为参数,仍收到以下错误:

node:internal/webidl:181
  const err = new TypeError(message);
              ^

TypeError: Failed to execute 'decrypt' on 'SubtleCrypto': 3rd argument is not instance of ArrayBuffer, Buffer, TypedArray, or DataView.
    at codedTypeError (node:internal/webidl:181:15)
    at makeException (node:internal/webidl:190:10)
    at converters.BufferSource (node:internal/crypto/webidl:206:11)
    at SubtleCrypto.decrypt (node:internal/crypto/webcrypto:961:28)
    at decrypt (/Users/me/code/encryptiontest/aes/aes.js:31:43)
    at testEncryptionDecryption (/Users/me/code/encryptiontest/aes/aes.js:52:29) {
  code: 'ERR_INVALID_ARG_TYPE'
}

原代码

const { subtle } = globalThis.crypto;

async function generateAesKey(length = 256) {
    const key = await subtle.generateKey({
        name: 'AES-CBC',
        length,
    }, true, ['encrypt', 'decrypt']);

    return key;
}

async function aesEncrypt(plaintext) {
    const ec = new TextEncoder();
    const key = await generateAesKey();
    const iv = crypto.getRandomValues(new Uint8Array(16));

    const ciphertext = await crypto.subtle.encrypt({
        name: 'AES-CBC',
        iv,
    }, key, ec.encode(plaintext));

    return {
        key,
        iv,
        ciphertext,
    };
}

async function decrypt(ciphertext, key, iv) {
    const dec = new TextDecoder();
    const plaintext = await crypto.subtle.decrypt({
        name: 'AES-CBC',
        iv,
    }, key, ciphertext);

    return dec.decode(plaintext);
}

// takes Uint8Array and returns ArrayBuffer
function typedArrayToBuffer(array) {
    return array.buffer.slice(array.byteOffset, array.byteLength + array.byteOffset);
}


async function testEncryptionDecryption() {
    const data = "Hello, world!";
    console.log("ENCRYPTING DATA");
    const { key, iv, encrypted } = await aesEncrypt(data);
    console.log(iv);
    console.log("DECRYPTING DATA");
    console.log(typeof iv.buffer);
    const decrypted = await decrypt(encrypted, key, typedArrayToBuffer(iv));
    console.log("Original:", data);
    console.log("Decrypted:", decrypted);
}

testEncryptionDecryption();

错误分析与修复方案

1. 核心错误:加密数据变量名不匹配

aesEncrypt函数返回的加密数据字段是ciphertext,但测试函数中解构赋值时误用了encrypted,导致传入decrypt的第一个参数是undefined——这才是错误提示中"3rd argument is not instance..."的根本原因(undefined不属于任何缓冲区类型)。

2. iv类型无需额外转换

Web Crypto API的decrypt方法接受的iv可以是Uint8Array、ArrayBuffer、DataView等BufferSource类型,你生成的iv本身就是Uint8Array,完全符合要求,不需要额外通过typedArrayToBuffer转换。

修正后的代码

const { subtle } = globalThis.crypto;

async function generateAesKey(length = 256) {
    const key = await subtle.generateKey({
        name: 'AES-CBC',
        length,
    }, true, ['encrypt', 'decrypt']);

    return key;
}

async function aesEncrypt(plaintext) {
    const ec = new TextEncoder();
    const key = await generateAesKey();
    const iv = crypto.getRandomValues(new Uint8Array(16));

    const ciphertext = await crypto.subtle.encrypt({
        name: 'AES-CBC',
        iv,
    }, key, ec.encode(plaintext));

    return {
        key,
        iv,
        ciphertext,
    };
}

async function decrypt(ciphertext, key, iv) {
    const dec = new TextDecoder();
    const plaintext = await crypto.subtle.decrypt({
        name: 'AES-CBC',
        iv,
    }, key, ciphertext);

    return dec.decode(plaintext);
}

async function testEncryptionDecryption() {
    const data = "Hello, world!";
    console.log("ENCRYPTING DATA");
    // 解构时使用正确的字段名ciphertext
    const { key, iv, ciphertext } = await aesEncrypt(data);
    console.log(iv);
    console.log("DECRYPTING DATA");
    // 直接传入原始iv,无需转换
    const decrypted = await decrypt(ciphertext, key, iv);
    console.log("Original:", data);
    console.log("Decrypted:", decrypted);
}

testEncryptionDecryption();

内容的提问来源于stack exchange,提问作者Mike

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 00:40:30