490 lines
13 KiB
Markdown
490 lines
13 KiB
Markdown
# SM4 算法模块 (TsSM4)
|
||
|
||
<cite>
|
||
**本文档引用的文件**
|
||
- [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)
|
||
</cite>
|
||
|
||
## 目录
|
||
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<br/>主加密模块]
|
||
Crypto[TsCrypto.js<br/>加密服务封装]
|
||
Global[TsGlobalConfig.js<br/>全局配置]
|
||
end
|
||
subgraph "工具模块"
|
||
Common[TsCommon.js<br/>通用工具]
|
||
Storage[TsStorage.js<br/>存储工具]
|
||
HttpUtil[TsHttpUtil.js<br/>HTTP工具]
|
||
end
|
||
subgraph "入口文件"
|
||
Index[index.js<br/>模块导出]
|
||
Package[package.json<br/>依赖管理]
|
||
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 密钥<br/>mk[0..3] = key[0..15]"]
|
||
ExtractMK --> InitK["初始化 K 数组<br/>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["保存轮密钥<br/>encryptRoundKeys[i] = k[i+4]"]
|
||
SaveKey --> Loop
|
||
Loop --> |完成| ReverseKeys["反转密钥顺序<br/>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位字<br/>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["组合最终块<br/>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["计算填充长度<br/>padLen = 16 - (len % 16)"]
|
||
CalcPad --> CreateBuffer["创建新缓冲区<br/>长度 = 原长度 + padLen"]
|
||
CreateBuffer --> CopyData["复制原数据到新缓冲区"]
|
||
CopyData --> FillPad["填充 padLen 个字节<br/>每个字节值为 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["按字节分割<br/>每4字节组成一个32位整数"]
|
||
SplitBytes --> ShiftLeft["左移操作<br/>高位字节 << 24, 16, 8, 0"]
|
||
ShiftLeft --> ORCombine["按位或组合<br/>形成32位整数"]
|
||
ORCombine --> Uint32Array[Uint32Array]
|
||
Uint32Array --> SplitBits["按位拆分<br/>32位整数拆分为4个字节"]
|
||
SplitBits --> ShiftRight["右移操作<br/>高位字节 >> 24, 16, 8, 0"]
|
||
ShiftRight --> ANDMask["按位与掩码<br/>& 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<br/>Base64 编解码]
|
||
UmiRequest[umi-request@1.4.0<br/>HTTP 请求]
|
||
end
|
||
subgraph "内部模块"
|
||
SM4[TsSM4.js<br/>SM4 加密算法]
|
||
Crypto[TsCrypto.js<br/>加密服务封装]
|
||
Global[TsGlobalConfig.js<br/>全局配置]
|
||
Common[TsCommon.js<br/>通用工具]
|
||
Storage[TsStorage.js<br/>存储工具]
|
||
HttpUtil[TsHttpUtil.js<br/>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. **文档完善**: 提供更详细的使用示例
|
||
|
||
该模块为企业级应用提供了可靠的加密解决方案,满足了中国国家标准的要求,同时保持了良好的性能和易用性。 |