# 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. **文档完善**: 提供更详细的使用示例 该模块为企业级应用提供了可靠的加密解决方案,满足了中国国家标准的要求,同时保持了良好的性能和易用性。