TypeScript ZUC 使用手册
TypeScript ZUC 使用手册
只有对端协议明确要求 ZUC-128、EEA3 或 EIA3 时才使用本章。普通业务数据需要认证加密时使用 SM4-GCM。
ZUC 是流密码:加密和解密都是明文/密文与同一密钥流异或。相同 key 和 IV 重复使用会泄漏两条消息的关系;zucEncrypt 本身也不检测篡改。
三种长度单位
不要把 2 words 写成 2 bytes,也不要把协议中的 bitLength 改成缓冲区字节数。
密钥流、加解密、EEA3 和 EIA3
// 1. 准备参数:ZUC-128 key 和 IV 都固定为 16 字节 Hex。
const key = '00'.repeat(16);
const iv = '00'.repeat(16);
const plaintext = 'order=GMKIT-DEMO-0001&amount=88.00';
// 2. 生成密钥流:8 byte 输出 16 个 Hex 字符,2 word 输出同样的 8 byte。
const byteKeystream = zucKeystream(key, iv, 8);
const wordKeystream = zucKeystreamWords(key, iv, 2);
assert.equal(byteKeystream, '27bede74018082da');
assert.equal(wordKeystream, byteKeystream);
// 3. ZUC 加密:业务文本按 UTF-8 编码,密文外层使用 Base64。
const ciphertext = zucEncrypt(key, iv, plaintext, {
outputFormat: OutputFormat.BASE64,
});
// 4. ZUC 解密:显式按 Base64 解码,使用同一 key 和 IV 恢复文本。
const decrypted = zucDecrypt(key, iv, ciphertext, {
inputFormat: InputFormat.BASE64,
});
assert.equal(decrypted, plaintext);
// 5. EEA3 机密性运算:COUNT、BEARER、DIRECTION 与 bitLength 属于协议字段。
const count = 0x398a59b4;
const bearer = 0x15;
const direction = 1;
const messageBytes = stringToBytes(plaintext);
const bitLength = messageBytes.length * 8;
const eea3Ciphertext = eea3Encrypt(
key,
count,
bearer,
direction,
messageBytes,
bitLength,
);
// 6. EEA3 解密:流密码重复执行同一运算,恢复原始消息字节。
const eea3Decrypted = eea3Encrypt(
key,
count,
bearer,
direction,
hexToBytes(eea3Ciphertext),
bitLength,
);
assert.equal(eea3Decrypted, bytesToHex(messageBytes));
// 7. EIA3 完整性校验:相同协议字段和消息产生相同的 32-bit MAC-I。
const mac = eia3(key, count, bearer, direction, messageBytes, bitLength);
assert.equal(mac.length, 8);
assert.equal(eia3(key, count, bearer, direction, messageBytes, bitLength), mac);
// 8. 篡改断言:金额变化后 EIA3 MAC-I 必须不同。
const tampered = stringToBytes('order=GMKIT-DEMO-0001&amount=99.00');
assert.notEqual(
eia3(key, count, bearer, direction, tampered, tampered.length * 8),
mac,
);
// 9. 非法参数断言:BEARER 超出 5 bit 范围时必须抛错。
assert.throws(() => eia3(key, count, 32, direction, messageBytes, bitLength));参数
eea3Encrypt 已构造 EEA3 所需 IV 并对消息执行机密性运算。只返回 word 对齐密钥流的旧入口不进入新代码,迁移时见旧系统迁移。
普通 ZUC 流的传输字段
使用 zucEncrypt/zucDecryptBytes 时,至少保存算法版本、key 标识、IV、ciphertext 和编码。key 不能随消息传输。
普通 ZUC 加密不提供认证。若协议未定义独立完整性机制,攻击者可以翻转密文 bit 并使对应明文 bit 翻转。EIA3 是 LTE 协议的 32-bit 完整性算法,不应脱离协议字段直接当作通用业务 MAC。
EEA3/EIA3 接入检查
count、bearer、direction从同一协议上下文取得。- 发出方和接收方对 bit 顺序、末字节有效 bit 数的解释一致。
- EEA3 负责机密性,EIA3 负责完整性;只做 EEA3 不会检测篡改。
- 比较 MAC-I 时先解码为 4 字节,再使用
constantTimeEqual。 - key、COUNT 或方向字段复用规则遵循上层 3GPP 协议,不能由示例自行发明。
完整函数、ZUC 类和 ZUCState 见 TypeScript ZUC API。