为什么这个 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]
我将以下内容表示为 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]