为什么这个 decoding/encoding 进程给出了不同的缓冲区数组?

Why is this decoding/encoding process giving a different buffer array?

我将以下内容表示为 ArrayBuffer:

const encryptedMsg = await crypto.subtle.encrypt(algorithm, key, messageUTF8)

这个值的字节长度是28:

encryptedMsg
// ArrayBuffer { byteLength: 28 }

当我将其转换为 Uint8Array 时,我得到以下值:

const encryptedMsgArr = new Uint8Array(encryptedMsg)
// Uint8Array(28) [ 237, 243, 213, 127, 248, 55, 37, 237, 209, 21, … ]

我想使用标准解码器将其转换为 UTF-8 密文,然后使用标准编码器将其还原:

const encoder = new TextEncoder("utf-8");
const decoder = new TextDecoder("utf-8");

解码时:

const cypherText = decoder.decode(encryptedMsgArr)
"���\u007f�7%��\u0015\u00113\u0012\u0016�۹o׀.:+=��\u0015\u0015"

但是当我尝试将其编码回 Uint8Array 时,即使为两者指定了 utf-8 编码,它也不匹配。

事实上,上面的代码看起来甚至不像是 utf-8,而且字节长度也不匹配(现在是 46 而不是 28):

encoder.encode(cypherText)
// Uint8Array(46) [ 239, 191, 189, 239, 191, 189, 239, 191, 189, 127, … ]

我做错了什么?

目标

能够导出密文,以便稍后在其他地方解密。如果 ArrayBuffer 的 UTF-8 解码不起作用,我唯一能想到的就是将 AB 转换为整数数组的字符串化版本并导出该字符串,但我不认为这是一个非常理智的方法。

编辑

实际上,只需声明没有 utf-8 编码的编码器和解码器就可以解决这个问题,但是@ornic 提供了一个很好的 base64 encoding/decoding 函数来代替使用。

const encoder = new TextEncoder();
const decoder = new TextDecoder();

据我所知,最常见的方法是将字节解码为 ASCII 文本,而不是 UTF-8。

类似的东西(所有代码都来自我当前的项目,我在 SoF 上找到了几乎所有代码):

var bufferToBase64 = function (buffer) {
            var s = '';
            var uintArray = new Uint8Array(buffer);
            uintArray.filter(function (v) { s += String.fromCharCode(v); return false; });
            return window.btoa(s);
        };

var bytes = function (text) {
            return new Uint8Array(
               atob(text)
                  .split('')
                  .map(function (c) {
                       return c.charCodeAt(0);
                   })
            );
}

以及用法示例:

test = new Uint8Array([1, 5, 167, 12])
> Uint8Array(4) [1, 5, 167, 12]
test2 = bufferToBase64(test)
> "AQWnDA=="
test3 = bytes(test2)
> Uint8Array(4) [1, 5, 167, 12]