TypeScript 数据、编码与错误
TypeScript 数据、编码与错误
密码 API 处理的是字节。字符串只是输入或传输层表示;在写算法调用前,先为每个字段确定“文本还是二进制”和“Hex 还是 Base64”。
何时使用哪种类型
stringToBytes 与 bytesToString 只用于 UTF-8 文本。任意二进制经过 bytesToString 后可能出现替换字符,不能再无损还原;这类数据直接保留为 Uint8Array。
编码、解码和失败比较
下面的文件由文档测试直接执行。它同时覆盖不可打印字节、UTF-8、显式编码、非法输入和认证值比较。
// 1. 准备二进制:该字节序列包含 NUL、非 ASCII 字节和字母 A。
const binary = Uint8Array.of(0x00, 0xff, 0x80, 0x41);
// 2. 编码二进制:协议字段分别输出为小写 Hex 和 RFC 4648 Base64。
const hex = encodeOutput(binary, OutputFormat.HEX);
const base64 = encodeOutput(binary, OutputFormat.BASE64);
assert.equal(hex, '00ff8041');
assert.equal(base64, 'AP+AQQ==');
// 3. 显式解码:接收方按协议声明的格式恢复相同字节。
assert.equal(constantTimeEqual(decodeInput(hex, InputFormat.HEX), binary), true);
assert.equal(constantTimeEqual(decodeInput(base64, InputFormat.BASE64), binary), true);
// 4. UTF-8 往返:文本转换与任意二进制转换分开处理。
const plaintext = '订单 GMKIT-DEMO-0001';
assert.equal(bytesToString(stringToBytes(plaintext)), plaintext);
assert.equal(bytesToHex(hexToBytes(hex)), hex);
assert.equal(bytesToBase64(base64ToBytes(base64)), base64);
// 5. Hex 边界:奇数长度会在高位补 0;非 Hex 字符必须被拒绝。
assert.equal(bytesToHex(hexToBytes('abc')), '0abc');
assert.throws(() => decodeInput('00xz', InputFormat.HEX));
// 6. 比较失败断言:长度相同但内容不同的认证值必须返回 false。
const tampered = Uint8Array.from(binary);
tampered[3] ^= 0x01;
assert.equal(constantTimeEqual(binary, tampered), false);0.10.1 的 Hex 边界
hexToBytes('abc')按0abc处理,这是已发布兼容行为。- 非 Hex 字符会抛出
Error。 bytesToHex始终输出小写、不带0x。- 跨系统协议应要求偶数长度;不要利用奇数长度补零行为定义新格式。
显式编码
主手册要求协议字段同时固定值和编码;接收端按照 schema 指定的格式解码,不根据内容猜测。例如:
{
"ciphertext": "W2...",
"encoding": "base64"
}随机源
configureRNG('strict') 的作用是:系统和调用方都没有提供 CSPRNG 时抛错。它不会创建随机源,也不会证明宿主随机源质量。
自定义随机源属于高级能力,普通 Node.js 和现代浏览器不需要注入。
false 与异常的边界
JavaScript/JIT 不保证严格恒时;constantTimeEqual 只避免相同长度数据按首个不同字节提前返回。
完整参数见 TypeScript 通用 API。