Skip to content

安全说明 ​

这一页讲本库替你做了什么,以及哪些事必须你自己做。

库替你把住的 ​

随机数只来自宿主 CSPRNG ​

SM2 的签名随机数 k、SM9 的 r、密钥生成用的私钥 d —— 全部取自 globalThis.crypto.getRandomValues(Node 下退到 webcrypto)。 本库不内置 RNG,也不会在任何路径上把随机性降级成 Math.random()。

生成私钥用拒绝采样 ​

椭圆曲线私钥按 64 位字切分从 256 位候选里重抽直到小于曲线阶,而不是取模 —— 取模会让分布偏斜。

公钥必须落在曲线上 ​

sm2.encrypt 会先验证公钥满足 y² ≡ x³ + ax + b (mod p) 且坐标在素域内, 否则抛 InvalidPublicKeyError。这挡掉的是"无效曲线点 / 错误子群"这类攻击面。 sm2.verify 遇到不在曲线上的公钥直接返回 false。

密钥流复用会被拒绝 ​

ZUC 的 zucEncrypt 记住用过的 (key, iv, counter),第二次出现同一个组合就抛 InvalidKeyError。同一密钥流异或两条明文即泄露两者的异或值 —— 这是静默失败里代价最高的 一种,所以宁可抛错。记录表有 4096 条上限(FIFO 淘汰),不会无限增长。

需要自己管理计数器的场景可以 configureReuseGuard({ enabled: false }) 关掉 —— 但那就把责任接过去了。

确认值用常数时间比较 ​

SM2 / SM9 密钥交换里的确认值 S_A / S_B 校验是逐字节常数时间比较, 不因提前返回而泄露信息。

需要你自己决定的 ​

SM2 公钥派生缓存(默认开启) ​

sign 每次都需要公钥算 Z 值,而公钥只依赖私钥。默认开启的进程内缓存(容量 32)让 sign 从 252 µs 降到 142 µs,代价是私钥的 hex 形态与其派生结果会驻留在进程内存里。

如果你的威胁模型不接受这个,关掉它:

ts
import { sm2 } from 'sm-crypto-wasm';

sm2.configurePublicKeyCache({ enabled: false });   // 回到每次都重算的无状态行为
sm2.clearPublicKeyCache();                          // 清掉已缓存的条目

ECB 和"无认证的加密" ​

  • ECB 泄露结构:相同明文块产出相同密文块。只在测试或兼容旧数据时用。
  • CTR / OFB / ECB 没有完整性:密文被改动你不会得到错误,只会得到错误的明文。 需要机密性 + 完整性时用 GCM。

IV / nonce 的生成与唯一性 ​

  • GCM 的 IV 在同一密钥下绝不可重复,否则可恢复认证密钥。本库不会替你生成 IV —— 显式传入,并保证唯一性(常用做法:96 位随机数或严格递增的计数器)。
  • CBC 的 IV 需要不可预测。
  • ZUC 的 (key, iv, counter) 同上(库会在加密路径上拦一道)。

密钥的存储与生命周期 ​

本库只做算法,不做密钥管理:私钥以 PEM / hex 字符串进出,不落盘、不写日志是库的设计 约束,但把它写进 localStorage、日志或错误上报是你的代码的事。

不在范围 ​

  • 国密机 / HSM / PKCS#11 句柄;
  • X.509 / PKCS#7 / CMS 协议封装(本库只到"算法 + 密钥编解码"这一层);
  • 抗侧信道的极端要求:WASM 的常数时间性质不受本库完全控制(例如底层查表访问模式), 高价值目标请评估后再采用。

建议的默认组合 ​

需求选择
摘要SM3
对称加密 + 完整性SM4-GCM
对称加密,只要机密性SM4-CTR(IV 唯一)或 SM4-CBC(IV 不可预测)
数字签名SM2 + SM3withSM2
公钥加密SM2(C1C3C2)
标识密码 / 无证书体系SM9
移动通信协议栈ZUC(EEA3 + EIA3)

以 Apache-2.0 许可发布