Files

352 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 加密配置
<cite>
**本文引用的文件列表**
- [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)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本指南围绕项目中的 SM4 加密配置展开,系统性说明 CBC 与 ECB 模式的配置与使用差异、base64Key 的作用与长度要求、安全性考量,以及在数据传输加密与存储加密等场景下的配置建议。同时覆盖加密模式切换、与全局配置的关系与继承机制、最佳实践(密钥管理、性能优化、安全加固)、以及测试与验证方法。文档严格基于仓库源码进行分析与总结,避免臆测。
## 项目结构
该项目采用“工具类 + 组件化”的组织方式:
- 工具层SM4 实现、通用加密封装、全局配置、本地存储、通用方法
- 业务集成层HTTP 请求工具,负责在请求前后对数据进行加解密
- 入口导出:统一通过入口文件导出各模块
```mermaid
graph TB
subgraph "工具层"
SM4["TsSM4<br/>SM4 加密实现"]
Crypto["TsCrypto<br/>基于 SM4 的加密封装"]
GlobalCfg["TsGlobalConfig<br/>全局配置"]
Storage["TsStorage<br/>本地存储"]
Common["TsCommon<br/>通用方法"]
end
subgraph "业务集成层"
HttpUtil["TsHttpUtil<br/>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 字节 IVECB 模式可省略 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 字节 IVECB 模式可省略
章节来源
- [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 字节 IVECB 可省略 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)