# 加密配置
**本文引用的文件列表**
- [TsSM4.js](file://src/utils/TsSM4.js)
- [TsCrypto.js](file://src/utils/TsCrypto.js)
- [TsGlobalConfig.js](file://src/utils/TsGlobalConfig.js)
- [TsHttpUtil.js](file://src/https/TsHttpUtil.js)
- [TsStorage.js](file://src/utils/TsStorage.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. [结论](#结论)
10. [附录](#附录)
## 简介
本指南围绕项目中的 SM4 加密配置展开,系统性说明 CBC 与 ECB 模式的配置与使用差异、base64Key 的作用与长度要求、安全性考量,以及在数据传输加密与存储加密等场景下的配置建议。同时覆盖加密模式切换、与全局配置的关系与继承机制、最佳实践(密钥管理、性能优化、安全加固)、以及测试与验证方法。文档严格基于仓库源码进行分析与总结,避免臆测。
## 项目结构
该项目采用“工具类 + 组件化”的组织方式:
- 工具层:SM4 实现、通用加密封装、全局配置、本地存储、通用方法
- 业务集成层:HTTP 请求工具,负责在请求前后对数据进行加解密
- 入口导出:统一通过入口文件导出各模块
```mermaid
graph TB
subgraph "工具层"
SM4["TsSM4
SM4 加密实现"]
Crypto["TsCrypto
基于 SM4 的加密封装"]
GlobalCfg["TsGlobalConfig
全局配置"]
Storage["TsStorage
本地存储"]
Common["TsCommon
通用方法"]
end
subgraph "业务集成层"
HttpUtil["TsHttpUtil
HTTP 请求工具"]
end
SM4 --> Crypto
GlobalCfg --> Crypto
Crypto --> HttpUtil
Storage --> HttpUtil
Common --> HttpUtil
```
图表来源
- [TsSM4.js:1-456](file://src/utils/TsSM4.js#L1-L456)
- [TsCrypto.js:1-34](file://src/utils/TsCrypto.js#L1-L34)
- [TsGlobalConfig.js:1-34](file://src/utils/TsGlobalConfig.js#L1-L34)
- [TsHttpUtil.js:1-171](file://src/https/TsHttpUtil.js#L1-L171)
- [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55)
章节来源
- [index.js:1-16](file://index.js#L1-L16)
- [package.json:1-24](file://package.json#L1-L24)
## 核心组件
- SM4 加密实现:提供 CBC/ECB 模式、PKCS#7 填充、Base64 文本输出、密钥扩展与轮函数等完整实现
- 加密封装:基于 SM4 构建默认实例,读取全局配置中的 base64Key,并默认以 ECB 模式工作
- 全局配置:提供 base64Key、前缀、HTTP 参数注入、错误回调等配置项
- HTTP 工具:在请求体加密开关开启时,对请求体进行加密;在响应标记为加密时进行解密
- 本地存储:提供开关控制是否对请求体进行加密
章节来源
- [TsSM4.js:96-453](file://src/utils/TsSM4.js#L96-L453)
- [TsCrypto.js:5-31](file://src/utils/TsCrypto.js#L5-L31)
- [TsGlobalConfig.js:5-29](file://src/utils/TsGlobalConfig.js#L5-L29)
- [TsHttpUtil.js:50-91](file://src/https/TsHttpUtil.js#L50-L91)
- [TsStorage.js:17-23](file://src/utils/TsStorage.js#L17-L23)
## 架构总览
下图展示了从请求发起到加解密处理的关键流程,以及与全局配置、本地存储的关系。
```mermaid
sequenceDiagram
participant Client as "调用方"
participant HttpUtil as "TsHttpUtil"
participant Storage as "TsStorage"
participant Crypto as "TsCrypto"
participant SM4 as "TsSM4"
participant Server as "后端服务"
Client->>HttpUtil : "post(url, data)"
HttpUtil->>Storage : "getEncryptBody()"
Storage-->>HttpUtil : "true/false"
alt "需要加密"
HttpUtil->>Crypto : "encrypt(JSON.stringify(data))"
Crypto->>SM4 : "encrypt(明文)"
SM4-->>Crypto : "密文(Base64)"
Crypto-->>HttpUtil : "密文(Base64)"
HttpUtil->>Server : "POST { encryptData : 密文 }"
else "无需加密"
HttpUtil->>Server : "POST data"
end
Server-->>HttpUtil : "响应 { code, data, encrypt? }"
alt "响应标记为加密"
HttpUtil->>Crypto : "decrypt(data)"
Crypto->>SM4 : "decrypt(密文)"
SM4-->>Crypto : "明文"
Crypto-->>HttpUtil : "明文"
HttpUtil-->>Client : "{ data, recordsTotal }"
else "未加密响应"
HttpUtil-->>Client : "{ data, recordsTotal }"
end
```
图表来源
- [TsHttpUtil.js:82-88](file://src/https/TsHttpUtil.js#L82-L88)
- [TsHttpUtil.js:119-122](file://src/https/TsHttpUtil.js#L119-L122)
- [TsCrypto.js:19-30](file://src/utils/TsCrypto.js#L19-L30)
- [TsSM4.js:338-387](file://src/utils/TsSM4.js#L338-L387)
- [TsSM4.js:395-452](file://src/utils/TsSM4.js#L395-L452)
- [TsStorage.js:17-23](file://src/utils/TsStorage.js#L17-L23)
## 详细组件分析
### SM4 加密实现(TsSM4)
- 模式支持:CBC、ECB 双模式,可通过构造参数选择
- IV 要求:CBC 模式必须提供 16 字节 IV;ECB 模式可省略 IV
- 密钥要求:必须为 16 字节(128 位),构造时会校验
- 输出类型:支持 Base64 与文本两种输出类型
- 填充策略:PKCS#7 填充,解密时自动去除
- 轮函数与密钥扩展:内置完整的 SM4 轮函数与轮密钥生成逻辑
```mermaid
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
+doBlockCrypt(blockData, roundKeys) Uint32Array
+spawnEncryptRoundKeys() void
+padding(buffer) Uint8Array
+dePadding(buffer) Uint8Array
+uint8ToUint32Block(arr, baseIndex) Uint32Array
+encrypt(plaintext) String
+decrypt(ciphertext) String
}
TsSM4 --> Crypt : "使用"
```
图表来源
- [TsSM4.js:39-94](file://src/utils/TsSM4.js#L39-L94)
- [TsSM4.js:96-453](file://src/utils/TsSM4.js#L96-L453)
章节来源
- [TsSM4.js:102-156](file://src/utils/TsSM4.js#L102-L156)
- [TsSM4.js:338-387](file://src/utils/TsSM4.js#L338-L387)
- [TsSM4.js:395-452](file://src/utils/TsSM4.js#L395-L452)
### 加密封装(TsCrypto)
- 默认使用 ECB 模式
- 从全局配置读取 base64Key 并转换为字节数组作为密钥
- 对外暴露 encrypt、decrypt 接口,内部委托给 TsSM4
章节来源
- [TsCrypto.js:7-13](file://src/utils/TsCrypto.js#L7-L13)
- [TsCrypto.js:19-30](file://src/utils/TsCrypto.js#L19-L30)
### 全局配置(TsGlobalConfig)
- 提供 base64Key、prefix、httpParams、onHttpError 等配置项
- 支持运行时 setConfig 合并默认配置
- HTTP 工具通过 getConfig 获取 prefix 与 httpParams 注入
章节来源
- [TsGlobalConfig.js:5-29](file://src/utils/TsGlobalConfig.js#L5-L29)
- [TsHttpUtil.js:100-106](file://src/https/TsHttpUtil.js#L100-L106)
- [TsHttpUtil.js:72-74](file://src/https/TsHttpUtil.js#L72-L74)
### HTTP 工具(TsHttpUtil)
- 在请求体加密开关开启时,将 data 包装为 { encryptData: 加密结果 }
- 在响应标记 encrypt 时,对 data 执行解密并解析 JSON
- 支持 GET/POST/form 等多种请求类型
章节来源
- [TsHttpUtil.js:82-88](file://src/https/TsHttpUtil.js#L82-L88)
- [TsHttpUtil.js:119-122](file://src/https/TsHttpUtil.js#L119-L122)
- [TsHttpUtil.js:142-154](file://src/https/TsHttpUtil.js#L142-L154)
- [TsHttpUtil.js:163-165](file://src/https/TsHttpUtil.js#L163-L165)
### 本地存储(TsStorage)
- 提供 getEncryptBody/saveEncryptBody 开关,用于控制请求体是否加密
- 与 HTTP 工具配合使用
章节来源
- [TsStorage.js:17-23](file://src/utils/TsStorage.js#L17-L23)
## 依赖关系分析
- TsCrypto 依赖 TsSM4 与 TsGlobalConfig
- TsHttpUtil 依赖 TsCrypto、TsStorage、TsGlobalConfig
- TsSM4 依赖 base64js(用于 Base64 编解码)
```mermaid
graph LR
base64js["base64js"] --> SM4["TsSM4"]
GlobalCfg["TsGlobalConfig"] --> Crypto["TsCrypto"]
SM4 --> Crypto
Crypto --> HttpUtil["TsHttpUtil"]
Storage["TsStorage"] --> HttpUtil
Common["TsCommon"] --> HttpUtil
```
图表来源
- [TsCrypto.js:1-3](file://src/utils/TsCrypto.js#L1-L3)
- [TsSM4.js:1](file://src/utils/TsSM4.js#L1)
- [TsHttpUtil.js:1-5](file://src/https/TsHttpUtil.js#L1-L5)
章节来源
- [package.json:19-22](file://package.json#L19-L22)
## 性能考量
- 模式选择
- ECB:每块独立加密,适合无状态、可并行处理的场景;但相同明文块会产生相同密文块,易受统计分析攻击
- CBC:引入链式传播,相同明文块不会产生相同密文块,更安全;但需 16 字节 IV,且加密过程串行
- 输出类型
- Base64 输出便于网络传输与日志记录,但会增加约 33% 的体积;文本输出取决于底层编码,通常体积更小
- 填充开销
- PKCS#7 填充会在明文末尾追加若干字节,对小数据影响较小
- 建议
- 优先使用 CBC 模式(若后端支持 IV),并在需要时启用 Base64 输出
- 对大体量数据,考虑分块或压缩后再加密,减少网络往返
## 故障排查指南
- 常见错误与定位
- “密钥长度不为 16 字节”:检查 base64Key 是否正确,确保解码后为 16 字节
- “IV 错误”:CBC 模式必须提供 16 字节 IV;确认传入的 iv 长度与编码
- “输出类型不匹配”:若后端返回非 Base64 内容,需将 cipherType 设置为文本
- “解密失败”:确认使用的密钥与模式一致,且数据未被篡改
- 定位步骤
- 确认全局配置中 base64Key 是否正确设置
- 检查请求体加密开关是否按预期开启
- 核对响应是否标记为加密,以及解密流程是否执行
- 使用最小化复现:仅传递一段固定明文,观察加解密结果一致性
章节来源
- [TsSM4.js:103-105](file://src/utils/TsSM4.js#L103-L105)
- [TsSM4.js:118-121](file://src/utils/TsSM4.js#L118-L121)
- [TsSM4.js:345-347](file://src/utils/TsSM4.js#L345-L347)
- [TsSM4.js:410-412](file://src/utils/TsSM4.js#L410-L412)
- [TsCrypto.js:8-12](file://src/utils/TsCrypto.js#L8-L12)
- [TsHttpUtil.js:82-88](file://src/https/TsHttpUtil.js#L82-L88)
- [TsHttpUtil.js:119-122](file://src/https/TsHttpUtil.js#L119-L122)
## 结论
本项目以 TsSM4 为核心,通过 TsCrypto 封装默认 ECB 模式与 base64Key,结合 TsHttpUtil 的请求体加密与响应解密能力,形成一套可配置、可扩展的加密方案。实际部署中应优先采用 CBC 模式并妥善管理 IV 与密钥,确保输出类型与后端一致,并通过全局配置集中管理密钥与前缀等参数。
## 附录
### 加密配置选项与说明
- base64Key
- 作用:作为 SM4 密钥的 Base64 字符串,构造时会被解码为 16 字节密钥
- 长度要求:解码后必须为 16 字节(128 位)
- 安全性:应由后端生成并下发,避免硬编码泄露;定期轮换
- 模式选择
- CBC:需提供 16 字节 IV;更安全,推荐用于大多数场景
- ECB:无需 IV;简单但安全性较低,仅在特定场景使用
- 输出类型
- Base64:便于网络传输与日志记录
- 文本:体积更小,但需确保后端一致
- IV 要求
- CBC 模式必须提供 16 字节 IV;ECB 模式可省略
章节来源
- [TsSM4.js:102-156](file://src/utils/TsSM4.js#L102-L156)
- [TsSM4.js:338-387](file://src/utils/TsSM4.js#L338-L387)
- [TsSM4.js:395-452](file://src/utils/TsSM4.js#L395-L452)
- [TsCrypto.js:8-12](file://src/utils/TsCrypto.js#L8-L12)
### 不同场景下的配置建议
- 数据传输加密(HTTP 请求体)
- 开启请求体加密开关
- 使用 CBC 模式并提供 16 字节 IV(若后端支持)
- 输出类型建议 Base64
- 存储加密(本地或数据库)
- 若明文为字符串,建议使用 ECB 模式简化处理
- 若存在重复明文块,建议使用 CBC 模式并随机 IV
- 输出类型根据存储介质选择(Base64 更通用)
章节来源
- [TsHttpUtil.js:82-88](file://src/https/TsHttpUtil.js#L82-L88)
- [TsStorage.js:17-23](file://src/utils/TsStorage.js#L17-L23)
### 加密模式切换与注意事项
- 切换方法
- 通过 TsCrypto 构造参数或直接创建 TsSM4 实例指定 mode 与 iv/cipherType
- 注意事项
- CBC 必须提供 16 字节 IV;ECB 可省略 IV
- 输出类型需与后端保持一致
- 切换模式后需同步后端解密逻辑
章节来源
- [TsCrypto.js:7-13](file://src/utils/TsCrypto.js#L7-L13)
- [TsSM4.js:128-141](file://src/utils/TsSM4.js#L128-L141)
- [TsSM4.js:343-378](file://src/utils/TsSM4.js#L343-L378)
- [TsSM4.js:408-447](file://src/utils/TsSM4.js#L408-L447)
### 最佳实践
- 密钥管理
- 使用强随机生成的 16 字节密钥,避免硬编码
- 通过安全渠道下发 base64Key,定期轮换
- 性能优化
- 对小数据优先使用 ECB;对大数据优先使用 CBC
- 合理选择输出类型,平衡体积与兼容性
- 安全加固
- CBC 模式务必使用随机 IV
- 对响应数据进行完整性校验(如 HMAC)
- 限制日志中输出密文,必要时仅输出摘要
### 加密配置与全局配置的关系与继承机制
- TsCrypto 默认从全局配置读取 base64Key,并以 ECB 模式初始化
- TsHttpUtil 通过 GlobalConfig.getConfig 获取 prefix 与 httpParams,用于请求拼接与参数注入
- setConfig 可合并默认配置,实现运行时动态调整
章节来源
- [TsCrypto.js:8-12](file://src/utils/TsCrypto.js#L8-L12)
- [TsGlobalConfig.js:19-29](file://src/utils/TsGlobalConfig.js#L19-L29)
- [TsHttpUtil.js:100-106](file://src/https/TsHttpUtil.js#L100-L106)
- [TsHttpUtil.js:72-74](file://src/https/TsHttpUtil.js#L72-L74)
### 测试方法与验证步骤
- 单元测试(建议)
- 使用固定明文与密钥,验证加解密一致性
- 分别测试 ECB 与 CBC 模式,确保 IV 正确性
- 验证 Base64 与文本输出类型的互操作
- 端到端测试(建议)
- 通过 HTTP 工具发起请求,开启请求体加密,验证响应解密
- 模拟后端响应标记为加密,验证解密流程
- 日志与监控
- 记录关键配置项(模式、输出类型、IV 是否提供)
- 对异常进行捕获与上报
章节来源
- [README.md:12-26](file://README.md#L12-L26)
- [TsHttpUtil.js:82-88](file://src/https/TsHttpUtil.js#L82-L88)
- [TsHttpUtil.js:119-122](file://src/https/TsHttpUtil.js#L119-L122)