# SM4 算法模块 (TsSM4)
**本文档引用的文件**
- [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)
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构概览](#架构概览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考虑](#性能考虑)
8. [故障排除指南](#故障排除指南)
9. [结论](#结论)
## 简介
SM4 算法模块是基于中国国家密码标准的对称加密算法实现,采用 128 位分组长度和 128 位密钥长度。该模块提供了完整的 SM4 加密解密功能,支持 CBC 和 ECB 两种工作模式,并实现了 PKCS7 自动填充算法。模块设计遵循现代 JavaScript 最佳实践,使用 ES6 类语法和 TypedArray 数据结构,确保高性能和内存效率。
本模块在企业级应用中用于数据加密、安全通信和敏感信息保护,特别适用于需要符合中国国家标准的加密需求场景。
## 项目结构
该项目采用模块化组织方式,主要包含以下核心文件:
```mermaid
graph TB
subgraph "核心模块"
SM4[TsSM4.js
主加密模块]
Crypto[TsCrypto.js
加密服务封装]
Global[TsGlobalConfig.js
全局配置]
end
subgraph "工具模块"
Common[TsCommon.js
通用工具]
Storage[TsStorage.js
存储工具]
HttpUtil[TsHttpUtil.js
HTTP工具]
end
subgraph "入口文件"
Index[index.js
模块导出]
Package[package.json
依赖管理]
end
SM4 --> Crypto
Crypto --> Global
Index --> SM4
Index --> Crypto
Index --> Common
Index --> Storage
Index --> HttpUtil
Package --> SM4
Package --> Crypto
```
**图表来源**
- [TsSM4.js:1-456](file://src/utils/TsSM4.js#L1-L456)
- [TsCrypto.js:1-34](file://src/utils/TsCrypto.js#L1-L34)
- [index.js:1-16](file://index.js#L1-L16)
**章节来源**
- [TsSM4.js:1-456](file://src/utils/TsSM4.js#L1-L456)
- [index.js:1-16](file://index.js#L1-L16)
## 核心组件
### 主要类结构
TsSM4 模块包含两个核心类:Crypt 工具类和 TsSM4 加密类。
```mermaid
classDiagram
class Crypt {
+stringToArrayBufferInUtf8(str) Uint8Array
+utf8ArrayBufferToString(buffer) String
+arrayBufferToBase64(buffer) String
+base64ToArrayBuffer(base64) Uint8Array
}
class TsSM4 {
-Uint8Array key
-Uint8Array iv
-String mode
-String cipherType
-Uint32Array encryptRoundKeys
-Uint32Array decryptRoundKeys
+constructor(config)
+doBlockCrypt(blockData, roundKeys) Uint32Array
+spawnEncryptRoundKeys() Uint32Array
+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
}
class TsCrypto {
-SM4 sm4
+constructor()
+encrypt(content) String
+decrypt(base64) String
}
TsSM4 --> Crypt : "使用"
TsCrypto --> TsSM4 : "封装"
```
**图表来源**
- [TsSM4.js:39-453](file://src/utils/TsSM4.js#L39-L453)
- [TsCrypto.js:5-31](file://src/utils/TsCrypto.js#L5-L31)
### 关键常量定义
模块定义了 SM4 算法的核心常量:
- **Sbox 替换表**: 16×16 的 S 盒替换表,用于字节替换操作
- **CK 常量数组**: 32 个轮常量,用于密钥扩展
- **FK 固定常量**: 4 个固定常量,用于初始密钥处理
**章节来源**
- [TsSM4.js:5-37](file://src/utils/TsSM4.js#L5-L37)
## 架构概览
### 整体架构设计
```mermaid
graph TB
subgraph "应用层"
App[业务应用]
Config[配置管理]
end
subgraph "加密服务层"
CryptoService[TsCrypto]
SM4Engine[TsSM4]
end
subgraph "数据转换层"
Base64[Base64 编码]
UTF8[UTF-8 编码]
ByteArray[字节数组]
end
subgraph "底层实现"
SBox[S 盒表]
RoundKeys[轮密钥]
Transform[变换函数]
end
App --> CryptoService
Config --> CryptoService
CryptoService --> SM4Engine
SM4Engine --> Base64
SM4Engine --> UTF8
SM4Engine --> ByteArray
SM4Engine --> SBox
SM4Engine --> RoundKeys
SM4Engine --> Transform
```
**图表来源**
- [TsSM4.js:96-156](file://src/utils/TsSM4.js#L96-L156)
- [TsCrypto.js:5-31](file://src/utils/TsCrypto.js#L5-L31)
### 数据流处理
```mermaid
sequenceDiagram
participant Client as 应用客户端
participant Crypto as TsCrypto
participant SM4 as TsSM4
participant Crypt as Crypt工具
Client->>Crypto : encrypt(明文)
Crypto->>SM4 : encrypt(明文)
SM4->>Crypt : stringToArrayBufferInUtf8(明文)
Crypt-->>SM4 : UTF-8 字节数组
SM4->>SM4 : padding(填充)
SM4->>SM4 : CBC/ECB 模式处理
SM4->>Crypt : arrayBufferToBase64(密文)
Crypt-->>SM4 : Base64 字符串
SM4-->>Crypto : 密文字符串
Crypto-->>Client : 密文字符串
```
**图表来源**
- [TsSM4.js:338-387](file://src/utils/TsSM4.js#L338-L387)
- [TsCrypto.js:19-21](file://src/utils/TsCrypto.js#L19-L21)
## 详细组件分析
### SM4 核心算法实现
#### 密钥扩展算法
密钥扩展是 SM4 算法的核心步骤,负责从原始密钥生成 32 个轮密钥。
```mermaid
flowchart TD
Start([开始密钥扩展]) --> ExtractMK["提取 MK 密钥
mk[0..3] = key[0..15]"]
ExtractMK --> InitK["初始化 K 数组
k[0..3] = mk ⊕ FK"]
InitK --> Loop{"循环 i = 0..31"}
Loop --> CalcK["计算 k[i+4] = k[i] ⊕ T(k[i+1] ⊕ k[i+2] ⊕ k[i+3] ⊕ CK[i])"]
CalcK --> SaveKey["保存轮密钥
encryptRoundKeys[i] = k[i+4]"]
SaveKey --> Loop
Loop --> |完成| ReverseKeys["反转密钥顺序
decryptRoundKeys = reverse(encryptRoundKeys)"]
ReverseKeys --> End([结束])
```
**图表来源**
- [TsSM4.js:189-207](file://src/utils/TsSM4.js#L189-L207)
#### 轮函数实现
每个 SM4 轮包含多个变换操作:
```mermaid
flowchart TD
BlockIn[16字节明文块] --> SplitBlock["分割为4个32位字
block[0..3]"]
SplitBlock --> RoundLoop{"i = 0..31"}
RoundLoop --> XOROp["x[i+4] = x[i] ⊕ T(x[i+1] ⊕ x[i+2] ⊕ x[i+3] ⊕ RK[i])"]
XOROp --> RoundLoop
RoundLoop --> |完成| FinalBlock["组合最终块
y[0..3] = x[32..35]"]
FinalBlock --> BlockOut[16字节密文块]
```
**图表来源**
- [TsSM4.js:166-180](file://src/utils/TsSM4.js#L166-L180)
#### 变换函数详解
##### τ 变换 (字节替换)
τ 变换使用 S 盒进行非线性替换:
- 输入: 32位值
- 处理: 将每个字节通过 S 盒查找替换
- 输出: 32位值
##### L 线性变换
L 变换实现位移和异或操作:
- L1: b ⊕ (b <<< 2) ⊕ (b <<< 10) ⊕ (b <<< 18) ⊕ (b <<< 24)
- L2: b ⊕ (b <<< 13) ⊕ (b <<< 23)
##### T 组合变换
T 变换结合 τ 和 L 变换:
- T1: L1(τ(z))
- T2: L2(τ(z))
**章节来源**
- [TsSM4.js:250-277](file://src/utils/TsSM4.js#L250-L277)
### 工作模式实现
#### CBC 模式
CBC (Cipher Block Chaining) 模式提供链式加密:
```mermaid
sequenceDiagram
participant P as 明文块
participant IV as 初始化向量
participant XOR as 异或运算
participant ENC as 加密器
participant C as 密文块
P1->>XOR : 明文1 ⊕ IV
XOR->>ENC : (明文1 ⊕ IV)
ENC-->>C : 密文1
C->>XOR : 密文1 ⊕ 明文2
XOR->>ENC : (密文1 ⊕ 明文2) ⊕ IV
ENC-->>C : 密文2
Note over IV,C : 每次使用前一个密文作为链输入
```
**图表来源**
- [TsSM4.js:343-378](file://src/utils/TsSM4.js#L343-L378)
#### ECB 模式
ECB (Electronic Codebook) 模式提供独立块加密:
```mermaid
flowchart TD
Plain1[明文块1] --> Encrypt1[独立加密]
Plain2[明文块2] --> Encrypt2[独立加密]
Plain3[明文块3] --> Encrypt3[独立加密]
Encrypt1 --> Cipher1[密文块1]
Encrypt2 --> Cipher2[密文块2]
Encrypt3 --> Cipher3[密文块3]
Note1[相同明文块产生相同密文块]
Note2[无链式依赖]
```
**图表来源**
- [TsSM4.js:368-378](file://src/utils/TsSM4.js#L368-L378)
### PKCS7 填充算法
PKCS7 是一种标准的块填充方案:
```mermaid
flowchart TD
Start([开始填充]) --> CheckNull{"输入为空?"}
CheckNull --> |是| ReturnNull[返回 null]
CheckNull --> |否| CalcPad["计算填充长度
padLen = 16 - (len % 16)"]
CalcPad --> CreateBuffer["创建新缓冲区
长度 = 原长度 + padLen"]
CreateBuffer --> CopyData["复制原数据到新缓冲区"]
CopyData --> FillPad["填充 padLen 个字节
每个字节值为 padLen"]
FillPad --> ReturnBuffer[返回填充后的缓冲区]
ReturnNull --> End([结束])
ReturnBuffer --> End
```
**图表来源**
- [TsSM4.js:287-296](file://src/utils/TsSM4.js#L287-L296)
**章节来源**
- [TsSM4.js:287-312](file://src/utils/TsSM4.js#L287-L312)
### 数据类型转换
#### 字节数组与 32 位整数转换
```mermaid
flowchart TD
Uint8Array[Uint8Array] --> SplitBytes["按字节分割
每4字节组成一个32位整数"]
SplitBytes --> ShiftLeft["左移操作
高位字节 << 24, 16, 8, 0"]
ShiftLeft --> ORCombine["按位或组合
形成32位整数"]
ORCombine --> Uint32Array[Uint32Array]
Uint32Array --> SplitBits["按位拆分
32位整数拆分为4个字节"]
SplitBits --> ShiftRight["右移操作
高位字节 >> 24, 16, 8, 0"]
ShiftRight --> ANDMask["按位与掩码
& 0xFF"]
ANDMask --> Uint8Array[Uint8Array]
```
**图表来源**
- [TsSM4.js:322-329](file://src/utils/TsSM4.js#L322-L329)
**章节来源**
- [TsSM4.js:322-329](file://src/utils/TsSM4.js#L322-L329)
## 依赖关系分析
### 外部依赖
```mermaid
graph TB
subgraph "外部库"
Base64[base64-js@1.5.1
Base64 编解码]
UmiRequest[umi-request@1.4.0
HTTP 请求]
end
subgraph "内部模块"
SM4[TsSM4.js
SM4 加密算法]
Crypto[TsCrypto.js
加密服务封装]
Global[TsGlobalConfig.js
全局配置]
Common[TsCommon.js
通用工具]
Storage[TsStorage.js
存储工具]
HttpUtil[TsHttpUtil.js
HTTP 工具]
end
SM4 --> Base64
Crypto --> Base64
Crypto --> Global
HttpUtil --> UmiRequest
```
**图表来源**
- [package.json:19-22](file://package.json#L19-L22)
- [TsSM4.js](file://src/utils/TsSM4.js#L1)
- [TsCrypto.js](file://src/utils/TsCrypto.js#L1)
### 内部模块依赖
```mermaid
graph LR
SM4[TsSM4] --> Crypt[Crypt 工具类]
Crypto[TsCrypto] --> SM4
Crypto --> Global[全局配置]
HttpUtil[TsHttpUtil] --> SM4
HttpUtil --> Crypto
```
**图表来源**
- [TsSM4.js:1-94](file://src/utils/TsSM4.js#L1-L94)
- [TsCrypto.js:1-3](file://src/utils/TsCrypto.js#L1-L3)
- [index.js:1-16](file://index.js#L1-L16)
**章节来源**
- [package.json:19-22](file://package.json#L19-L22)
- [index.js:1-16](file://index.js#L1-L16)
## 性能考虑
### 内存使用分析
#### 数据结构内存占用
| 数据结构 | 大小 | 用途 |
|---------|------|------|
| Uint8Array | 1 字节/元素 | 原始字节数据 |
| Uint32Array | 4 字节/元素 | 32位整数运算 |
| Sbox 表 | 256 字节 | 字节替换表 |
| 轮密钥数组 | 128 字节 | 32个轮密钥 |
| 中间变量 | ~144 字节 | 临时计算结果 |
#### 内存优化策略
1. **TypedArray 使用**: 优先使用 TypedArray 减少内存开销
2. **就地计算**: 尽可能重用数组避免额外分配
3. **批量处理**: 一次处理多个块提高缓存利用率
### 性能特征
#### 时间复杂度
- **密钥扩展**: O(1) - 固定 32 次迭代
- **单块加密**: O(1) - 固定 32 轮运算
- **整体加密**: O(n) - n 为块数量
#### 空间复杂度
- **内存使用**: O(n) - n 为输入数据大小
- **额外开销**: O(1) - 固定大小的中间变量
### 并发处理
模块当前不支持并发操作,建议:
1. 为每个并发任务创建独立的 TsSM4 实例
2. 避免在多线程环境中共享同一实例
3. 考虑使用 Web Workers 处理大量数据
## 故障排除指南
### 常见错误及解决方案
#### 密钥长度错误
**问题**: 密钥长度不是 16 字节
**解决**: 确保密钥为 16 字节长度
**位置**: [TsSM4.js:103-105](file://src/utils/TsSM4.js#L103-L105)
#### IV 参数错误
**问题**: CBC 模式下 IV 长度不正确
**解决**: 确保 IV 为 16 字节长度
**位置**: [TsSM4.js:119-121](file://src/utils/TsSM4.js#L119-L121)
#### 填充数据错误
**问题**: 去填充时数据格式不正确
**解决**: 确保使用相同的填充算法进行加解密
**位置**: [TsSM4.js:309-311](file://src/utils/TsSM4.js#L309-L311)
### 调试技巧
1. **启用详细日志**: 在开发环境中输出中间计算结果
2. **单元测试**: 为关键函数编写测试用例
3. **边界测试**: 测试空数据、单块数据、多块数据等场景
**章节来源**
- [TsSM4.js:103-121](file://src/utils/TsSM4.js#L103-L121)
- [TsSM4.js:309-311](file://src/utils/TsSM4.js#L309-L311)
## 结论
SM4 算法模块提供了完整、高效的中国国家标准加密实现。模块具有以下特点:
### 技术优势
1. **标准兼容**: 完全符合 SM4 算法规范
2. **性能优秀**: 使用 TypedArray 和优化算法
3. **接口友好**: 提供简洁的加密解密接口
4. **模式完整**: 支持 CBC 和 ECB 两种工作模式
### 应用场景
- 企业数据加密
- 网络通信安全
- 敏感信息保护
- 符合国家标准的系统集成
### 发展建议
1. **添加更多模式**: 考虑支持 OFB、CFB 等模式
2. **性能优化**: 实现 SIMD 指令集优化
3. **安全性增强**: 添加完整性校验机制
4. **文档完善**: 提供更详细的使用示例
该模块为企业级应用提供了可靠的加密解决方案,满足了中国国家标准的要求,同时保持了良好的性能和易用性。