13 KiB
13 KiB
SM4 算法 API
**本文引用的文件** - [TsSM4.js](file://src/utils/TsSM4.js) - [TsCrypto.js](file://src/utils/TsCrypto.js) - [TsGlobalConfig.js](file://src/utils/TsGlobalConfig.js) - [index.js](file://index.js) - [package.json](file://package.json) - [README.md](file://README.md)目录
简介
本文件为 SM4 对称加密算法模块的完整 API 参考文档,覆盖以下内容:
- 方法签名与参数类型(明文、密钥、IV 向量、输出类型)
- 返回值类型与数据格式
- CBC 与 ECB 两种加密模式支持
- 自动填充与去填充机制
- 字节序与位运算处理细节
- 与 Base64 编解码的集成方式与数据格式转换
- 安全性考虑、性能特征与适用场景
- 扩展与自定义方法建议
项目结构
该工具包通过统一入口导出多个工具模块,其中 SM4 模块位于 src/utils/TsSM4.js,并在 index.js 中集中导出。
graph TB
A["index.js<br/>统一导出入口"] --> B["TsSM4.js<br/>SM4 实现"]
A --> C["TsCrypto.js<br/>基于 SM4 的加密器封装"]
A --> D["TsGlobalConfig.js<br/>全局配置含 base64Key"]
E["package.json<br/>依赖声明"] --> F["base64-js@1.5.1"]
B --> F
C --> B
C --> D
图表来源
章节来源
核心组件
- TsSM4:SM4 对称加密算法实现,支持 CBC/ECB 模式、PKCS#7 填充、Base64 文本输出。
- Crypt:字符串与字节数组、Base64 之间的编解码辅助工具。
- TsCrypto:基于 SM4 的应用层加密器,使用全局配置中的 base64Key 初始化。
章节来源
架构总览
SM4 模块以面向对象的方式组织,内部包含:
- 常量表:S 盒、轮常数 CK、初始常数 FK
- 工具类 Crypt:UTF-8 字符串与 Uint8Array 的互转、Base64 与 Uint8Array 的互转
- 主类 TsSM4:密钥展开、轮函数、填充/去填充、CBC/ECB 加解密流程
classDiagram
class Crypt {
+stringToArrayBufferInUtf8(str) Uint8Array
+utf8ArrayBufferToString(buf) String
+arrayBufferToBase64(buf) String
+base64ToArrayBuffer(str) Uint8Array
}
class TsSM4 {
+Uint8Array key
+Uint8Array iv
+String mode
+String cipherType
+Uint32Array encryptRoundKeys
+Uint32Array decryptRoundKeys
+constructor(config)
+doBlockCrypt(blockData, roundKeys) Uint32Array
+spawnEncryptRoundKeys() void
+rotateLeft(x, y) Number
+linearTransform1(b) Number
+linearTransform2(b) Number
+tauTransform(a) Number
+tTransform1(z) Number
+tTransform2(z) Number
+padding(originalBuffer) Uint8Array
+dePadding(paddedBuffer) Uint8Array
+uint8ToUint32Block(uint8Array, baseIndex) Uint32Array
+encrypt(plaintext) String
+decrypt(ciphertext) String
}
TsSM4 --> Crypt : "使用"
图表来源
详细组件分析
类:TsSM4(SM4 算法主类)
-
职责
- 密钥展开与轮密钥生成
- 轮函数与线性变换
- PKCS#7 填充与去填充
- CBC/ECB 模式加解密
- 输出类型(Base64 或 UTF-8 文本)
-
关键成员
- key:16 字节密钥(Uint8Array)
- iv:16 字节 IV(Uint8Array),CBC 模式必需
- mode:'cbc' 或 'ecb'
- cipherType:'base64' 或 'text'
- encryptRoundKeys / decryptRoundKeys:32 轮密钥数组(Uint32Array)
-
关键方法
- constructor(config)
- 参数:config.keyBuffer(必填,16 字节)、config.iv(可选,16 字节)、config.mode('cbc'|'ecb')、config.outType('base64'|'text')
- 行为:校验长度、初始化轮密钥、准备正向/逆向轮密钥
- encrypt(plaintext: String): String
- 行为:UTF-8 编码 -> PKCS#7 填充 -> 分块处理 -> CBC/ECB -> 输出类型转换
- 返回:Base64 字符串或 UTF-8 文本
- decrypt(ciphertext: String): String
- 行为:根据 cipherType 解码 -> 分块处理 -> CBC/ECB -> 去填充 -> UTF-8 解码
- 返回:明文字符串
- constructor(config)
-
数据流与算法要点
- 字节序:大端序(MSB 在前),按 4 字节组合为 Uint32
- 轮函数:32 轮迭代,使用 S 盒替换与线性变换
- CBC 链接:前一分组密文作为下一分组的 IV
- 填充:按 16 字节对齐,填充长度为填充字节数
章节来源
- TsSM4.js:96-156
- TsSM4.js:158-180
- TsSM4.js:189-207
- TsSM4.js:217-241
- TsSM4.js:250-277
- TsSM4.js:287-312
- TsSM4.js:322-329
- TsSM4.js:338-387
- TsSM4.js:395-452
类:Crypt(编解码工具)
- 字符串与字节数组
- stringToArrayBufferInUtf8(str: String): Uint8Array
- utf8ArrayBufferToString(buf: Uint8Array): String
- Base64 与字节数组
- arrayBufferToBase64(buf: Uint8Array): String
- base64ToArrayBuffer(str: String): Uint8Array
章节来源
类:TsCrypto(应用层封装)
- 使用全局配置中的 base64Key 初始化 SM4(ECB 模式,输出 Base64)
- 提供 encrypt/content 和 decrypt/base64 接口
章节来源
API 规范与使用示例
-
构造函数
- 名称:TsSM4(config)
- 参数:
- keyBuffer: Uint8Array(必须,16 字节)
- iv?: String(可选,16 字节;CBC 模式必需)
- mode?: 'cbc'|'ecb'(默认 'cbc')
- outType?: 'base64'|'text'(默认 'base64')
- 返回:TsSM4 实例
- 异常:当 keyBuffer 长度不为 16 或 iv 长度不为 16 时抛出错误
-
加密
- 名称:encrypt(plaintext: String): String
- 输入:明文字符串(UTF-8)
- 处理:填充 -> 分块 -> CBC/ECB -> 输出类型转换
- 输出:Base64 字符串或 UTF-8 文本(取决于 outType)
-
解密
- 名称:decrypt(ciphertext: String): String
- 输入:密文字符串(Base64 或 UTF-8,取决于 outType)
- 处理:解码 -> 分块 -> CBC/ECB -> 去填充 -> UTF-8
- 输出:明文字符串
-
示例(路径)
- CBC 模式加密:TsSM4.js:338-387
- ECB 模式加密:TsSM4.js:368-378
- CBC 模式解密:TsSM4.js:395-452
- ECB 模式解密:TsSM4.js:434-447
- 应用层封装使用:TsCrypto.js:19-30
章节来源
流程图:CBC 模式加密
flowchart TD
Start(["开始"]) --> Encode["UTF-8 编码明文"]
Encode --> Pad["PKCS#7 填充到 16 字节倍数"]
Pad --> InitChain["初始化链寄存器为 IVCBC"]
InitChain --> Loop{"遍历每个 16 字节块"}
Loop --> |是| Xor["与上一密文块异或CBC"]
Xor --> Round["32 轮加密轮函数+S 盒+线性变换"]
Round --> Save["保存当前密文块"]
Save --> Next["下一个明文块"]
Next --> Loop
Loop --> |否| OutType["根据 outType 输出Base64 或文本"]
OutType --> End(["结束"])
图表来源
流程图:ECB 模式解密
flowchart TD
Start(["开始"]) --> Decode["根据 outType 解码Base64 或文本"]
Decode --> Blocks["按 16 字节分块"]
Blocks --> DecryptLoop{"遍历每个 16 字节块"}
DecryptLoop --> |是| Round["32 轮解密逆序轮密钥"]
Round --> Save["保存明文块"]
Save --> Next["下一个块"]
Next --> DecryptLoop
DecryptLoop --> |否| Depad["去填充移除 PKCS#7"]
Depad --> Utf8["UTF-8 解码"]
Utf8 --> End(["结束"])
图表来源
序列图:应用层加密调用
sequenceDiagram
participant App as "应用"
participant Crypto as "TsCrypto"
participant SM4 as "TsSM4"
participant Config as "TsGlobalConfig"
App->>Crypto : "new TsCrypto()"
Crypto->>Config : "getConfig()"
Config-->>Crypto : "{base64Key}"
Crypto->>Crypto : "base64Key -> Uint8Array"
Crypto->>SM4 : "new TsSM4({keyBuffer, mode : 'ecb', outType : 'base64'})"
App->>Crypto : "encrypt(明文)"
Crypto->>SM4 : "encrypt(明文)"
SM4-->>Crypto : "密文(Base64)"
Crypto-->>App : "密文(Base64)"
图表来源
依赖关系分析
- 内部依赖
- TsCrypto 依赖 TsSM4 与 TsGlobalConfig
- TsSM4 依赖 Crypt 与 base64-js
- 外部依赖
- base64-js@1.5.1:Base64 编解码
- umi-request@1.4.0:HTTP 请求(在 https 模块中使用)
graph LR
TsCrypto["TsCrypto.js"] --> TsSM4["TsSM4.js"]
TsCrypto --> TsGlobalConfig["TsGlobalConfig.js"]
TsSM4 --> Base64["base64-js@1.5.1"]
Package["package.json"] --> Base64
图表来源
章节来源
性能与安全考量
- 性能特征
- 32 轮迭代,每块 16 字节,适合小批量数据快速加解密
- 使用 TypedArray 进行位运算,避免频繁装箱开销
- Base64 编解码在浏览器与 Node 环境均可用
- 安全性考虑
- CBC 模式需要随机且唯一的 IV;若 IV 固定,会降低安全性
- 密钥长度固定为 16 字节,需确保密钥熵足够
- 填充采用 PKCS#7,需确保去填充逻辑正确
- 适用场景
- 小型数据加密(如配置项、令牌、短消息)
- 与 HTTP 加密传输结合使用(参考 README 中的 HttpUtil 配置)
章节来源
故障排查指南
- 常见错误
- 密钥长度不为 16 字节:构造函数抛错
- IV 非空但长度不为 16 字节:CBC 模式抛错
- 输出类型与输入不匹配:解密失败或结果异常
- 排查步骤
- 确认密钥与 IV 均为 16 字节
- 确认 outType 与实际输入一致
- 检查 Base64 编码是否完整
- 核对 CBC/ECB 模式选择与业务需求一致
章节来源
结论
本模块提供了完整的 SM4 对称加密能力,支持 CBC/ECB 模式与 PKCS#7 填充,具备良好的跨平台兼容性(浏览器/Node)。通过 TsCrypto 可直接用于业务场景,推荐在 CBC 模式下使用随机 IV,并严格管理密钥与输出类型,以确保安全性与一致性。
附录
API 一览(方法签名与参数)
- TsSM4(config)
- config.keyBuffer: Uint8Array(16 字节)
- config.iv?: String(16 字节;CBC 必需)
- config.mode?: 'cbc'|'ecb'
- config.outType?: 'base64'|'text'
- encrypt(plaintext: String): String
- decrypt(ciphertext: String): String
章节来源
数据格式与转换
- 字节序:大端序(MSB 在前)
- 填充:PKCS#7(1-16 字节)
- 输出类型:
- 'base64':Base64 字符串
- 'text':UTF-8 文本(浏览器/Node 环境均支持)
章节来源
扩展与自定义
- 支持自定义 IV(CBC 模式)
- 支持自定义输出类型(Base64 或文本)
- 可在应用层封装更多模式(如 GCM/CTR),但当前实现仅支持 CBC/ECB
章节来源