我正在尝试加密文件并将其上传到云端,然后使用 Node.js v21.6.2 在本地解密。不幸的是,我在解密时遇到问题。我能够生成密钥并加密,但在 iv 上解密失败,据称它不是 ArrayBuffer,但应该是。有没有更好的方法来确保 iv 是缓冲区,以便我可以正确解密文件?我注意到加密的数据对象未定义,我不确定这是否是问题所在。有人对我做错了什么有任何想法吗?这是我收到的错误:
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();
我尝试在解密中使用 iv、iv.buffer 和 iv.buffer.slice,但收到一条错误消息,提示 iv 不是 ArrayBuffer、Buffer、TypedArray 或 DataView 的实例
你的问题不是IV(这是your
decrypt
函数的第三个参数),而是——正如错误消息所说——第三个参数到SubtleCrypto.decrypt
,它应该是密文,但实际上是 undefined
。
这是因为你的线路
const { key, iv, encrypted } = await aesEncrypt(data);
aesEncrypt
返回一个包含 key iv ciphertext
但不包含 encrypted
的对象,因此这会将 key
和 iv
设置为返回对象中的成员(这是正确的),但不会将 encrypted
设置为任何内容,丢弃成员 ciphertext
的值。更改此代码和以下代码以提取并使用 ciphertext
并且它可以工作 - 并且只需简单的 iv
。