Files
npm-tool/.qoder/repowiki/zh/content/核心模块/SM4 算法模块 (TsSM4).md

13 KiB
Raw Permalink Blame History

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 数据结构,确保高性能和内存效率。

本模块在企业级应用中用于数据加密、安全通信和敏感信息保护,特别适用于需要符合中国国家标准的加密需求场景。

项目结构

该项目采用模块化组织方式,主要包含以下核心文件:

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 模块包含两个核心类Crypt 工具类和 TsSM4 加密类。

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 : "封装"

图表来源

关键常量定义

模块定义了 SM4 算法的核心常量:

  • Sbox 替换表: 16×16 的 S 盒替换表,用于字节替换操作
  • CK 常量数组: 32 个轮常量,用于密钥扩展
  • FK 固定常量: 4 个固定常量,用于初始密钥处理

章节来源

架构概览

整体架构设计

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

图表来源

数据流处理

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 : 密文字符串

图表来源

详细组件分析

SM4 核心算法实现

密钥扩展算法

密钥扩展是 SM4 算法的核心步骤,负责从原始密钥生成 32 个轮密钥。

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([结束])

图表来源

轮函数实现

每个 SM4 轮包含多个变换操作:

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字节密文块]

图表来源

变换函数详解

τ 变换 (字节替换)

τ 变换使用 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))

章节来源

工作模式实现

CBC 模式

CBC (Cipher Block Chaining) 模式提供链式加密:

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 : 每次使用前一个密文作为链输入

图表来源

ECB 模式

ECB (Electronic Codebook) 模式提供独立块加密:

flowchart TD
Plain1[明文块1] --> Encrypt1[独立加密]
Plain2[明文块2] --> Encrypt2[独立加密]
Plain3[明文块3] --> Encrypt3[独立加密]
Encrypt1 --> Cipher1[密文块1]
Encrypt2 --> Cipher2[密文块2]
Encrypt3 --> Cipher3[密文块3]
Note1[相同明文块产生相同密文块]
Note2[无链式依赖]

图表来源

PKCS7 填充算法

PKCS7 是一种标准的块填充方案:

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

图表来源

章节来源

数据类型转换

字节数组与 32 位整数转换

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]

图表来源

章节来源

依赖关系分析

外部依赖

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

图表来源

内部模块依赖

graph LR
SM4[TsSM4] --> Crypt[Crypt 工具类]
Crypto[TsCrypto] --> SM4
Crypto --> Global[全局配置]
HttpUtil[TsHttpUtil] --> SM4
HttpUtil --> Crypto

图表来源

章节来源

性能考虑

内存使用分析

数据结构内存占用

数据结构 大小 用途
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

IV 参数错误

问题: CBC 模式下 IV 长度不正确 解决: 确保 IV 为 16 字节长度 位置: TsSM4.js:119-121

填充数据错误

问题: 去填充时数据格式不正确 解决: 确保使用相同的填充算法进行加解密 位置: TsSM4.js:309-311

调试技巧

  1. 启用详细日志: 在开发环境中输出中间计算结果
  2. 单元测试: 为关键函数编写测试用例
  3. 边界测试: 测试空数据、单块数据、多块数据等场景

章节来源

结论

SM4 算法模块提供了完整、高效的中国国家标准加密实现。模块具有以下特点:

技术优势

  1. 标准兼容: 完全符合 SM4 算法规范
  2. 性能优秀: 使用 TypedArray 和优化算法
  3. 接口友好: 提供简洁的加密解密接口
  4. 模式完整: 支持 CBC 和 ECB 两种工作模式

应用场景

  • 企业数据加密
  • 网络通信安全
  • 敏感信息保护
  • 符合国家标准的系统集成

发展建议

  1. 添加更多模式: 考虑支持 OFB、CFB 等模式
  2. 性能优化: 实现 SIMD 指令集优化
  3. 安全性增强: 添加完整性校验机制
  4. 文档完善: 提供更详细的使用示例

该模块为企业级应用提供了可靠的加密解决方案,满足了中国国家标准的要求,同时保持了良好的性能和易用性。