# 加密模块 (TsCrypto) **本文引用的文件列表** - [TsCrypto.js](file://src/utils/TsCrypto.js) - [TsSM4.js](file://src/utils/TsSM4.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. [附录](#附录) ## 简介 本文件为加密模块(TsCrypto)的全面技术文档,聚焦于基于 SM4 算法的加密与解密实现,覆盖 CBC 与 ECB 模式支持与配置、Base64 编解码机制、自动填充与去填充算法,以及与全局配置系统、存储系统和 HTTP 请求模块的集成方式。文档同时提供完整的 API 接口说明、使用示例、性能与安全最佳实践,并解释加密开关控制、token 加密传输等典型应用场景。 ## 项目结构 该工具包采用按功能模块划分的组织方式: - utils:通用工具与加密核心实现 - TsCrypto.js:对外暴露的加密模块入口,封装 SM4 并与全局配置联动 - TsSM4.js:SM4 算法实现,含填充/去填充、CBC/ECB 模式、Base64 文本编解码 - TsGlobalConfig.js:全局配置读取与设置 - TsStorage.js:本地存储与加密开关、token 的持久化 - TsCommon.js:通用工具函数(如 JSON 解析、URL 参数解析等) - https:HTTP 请求封装与加密开关集成 - TsHttpUtil.js:统一请求处理、参数预处理、加解密与响应解密 - index.js:导出模块集合 - package.json:依赖声明(base64-js、umi-request) ```mermaid graph TB subgraph "工具包(utils)" Crypto["TsCrypto.js"] SM4["TsSM4.js"] GConf["TsGlobalConfig.js"] Store["TsStorage.js"] Common["TsCommon.js"] end subgraph "HTTP(https)" HttpUtil["TsHttpUtil.js"] end Index["index.js"] Package["package.json"] Crypto --> SM4 Crypto --> GConf HttpUtil --> Crypto HttpUtil --> Store HttpUtil --> GConf HttpUtil --> Common Index --> Crypto Index --> SM4 Index --> GConf Index --> Store Index --> HttpUtil Package --> SM4 Package --> HttpUtil ``` 图表来源 - [TsCrypto.js:1-34](file://src/utils/TsCrypto.js#L1-L34) - [TsSM4.js:1-456](file://src/utils/TsSM4.js#L1-L456) - [TsGlobalConfig.js:1-34](file://src/utils/TsGlobalConfig.js#L1-L34) - [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55) - [TsHttpUtil.js:1-171](file://src/https/TsHttpUtil.js#L1-L171) - [index.js:1-16](file://index.js#L1-L16) - [package.json:1-24](file://package.json#L1-L24) 章节来源 - [index.js:1-16](file://index.js#L1-L16) - [package.json:1-24](file://package.json#L1-L24) ## 核心组件 - TsCrypto:对外加密模块,负责初始化 SM4 实例(默认 ECB 模式、Base64 输出),并提供 encrypt/decrypt 方法。 - TsSM4:SM4 算法核心,支持 CBC/ECB 模式、Base64/text 输出、自动 PKCS#7 填充与去填充、UTF-8 字符串编解码。 - TsGlobalConfig:全局配置读取与合并,提供 base64Key、prefix、httpParams、onHttpError 等。 - TsStorage:本地存储封装,提供用户 token、加密开关等键值存取。 - TsHttpUtil:HTTP 请求封装,集成加密开关、请求体加密、响应体解密、token 注入等。 章节来源 - [TsCrypto.js:5-34](file://src/utils/TsCrypto.js#L5-L34) - [TsSM4.js:96-456](file://src/utils/TsSM4.js#L96-L456) - [TsGlobalConfig.js:1-34](file://src/utils/TsGlobalConfig.js#L1-L34) - [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55) - [TsHttpUtil.js:1-171](file://src/https/TsHttpUtil.js#L1-L171) ## 架构总览 加密模块在工具包中的位置与交互如下: - TsCrypto 初始化时从全局配置读取 base64Key,转换为字节后注入 SM4;默认模式为 ECB,输出为 Base64。 - TsHttpUtil 在发送请求前根据存储的加密开关决定是否对请求体进行加密;收到响应后若标记为加密,则进行解密并尝试 JSON 解析。 - TsStorage 提供加密开关与 token 的持久化,便于跨页面/会话保持状态。 - TsGlobalConfig 提供全局配置(如前缀、附加参数、错误回调)以影响 HTTP 请求行为。 ```mermaid sequenceDiagram participant Client as "调用方" participant HttpUtil as "TsHttpUtil" participant Store as "TsStorage" participant Crypto as "TsCrypto" participant SM4 as "TsSM4" participant Server as "后端服务" Client->>HttpUtil : "post(url, data)" HttpUtil->>Store : "getEncryptBody()" alt "加密开关开启" HttpUtil->>Crypto : "encrypt(JSON.stringify(data))" Crypto->>SM4 : "encrypt(UTF-8字节)" SM4-->>Crypto : "Base64密文" Crypto-->>HttpUtil : "Base64密文" HttpUtil->>Server : "POST { encryptData : Base64密文 }" else "加密开关关闭" HttpUtil->>Server : "POST data" end Server-->>HttpUtil : "响应 { code, data, encrypt? }" alt "响应标记为加密" HttpUtil->>Crypto : "decrypt(data)" Crypto->>SM4 : "decrypt(Base64密文)" SM4-->>Crypto : "明文字节数组" Crypto-->>HttpUtil : "明文字符串" HttpUtil->>HttpUtil : "parseJSON(可选)" end HttpUtil-->>Client : "{ data, recordsTotal }" ``` 图表来源 - [TsHttpUtil.js:81-123](file://src/https/TsHttpUtil.js#L81-L123) - [TsCrypto.js:19-30](file://src/utils/TsCrypto.js#L19-L30) - [TsSM4.js:338-452](file://src/utils/TsSM4.js#L338-L452) ## 详细组件分析 ### TsCrypto 组件分析 - 角色定位:对外加密模块,封装 SM4 并与全局配置联动。 - 关键点: - 构造函数中从全局配置读取 base64Key,转换为字节数组后传入 SM4。 - 默认模式为 ECB,输出类型为 Base64。 - 对外提供 encrypt/content 与 decrypt/base64 两个方法,分别委托给 SM4 的对应逻辑。 - 适用场景:作为 HTTP 请求层的加密前置,或独立用于数据加密/解密。 ```mermaid classDiagram class TsCrypto { +constructor() +encrypt(content) String +decrypt(base64) String } class TsSM4 { +constructor(config) +encrypt(plaintext) String +decrypt(ciphertext) String -padding(buffer) Uint8Array -dePadding(buffer) Uint8Array -uint8ToUint32Block(arr, idx) Uint32Array -doBlockCrypt(block, roundKeys) Uint32Array -spawnEncryptRoundKeys() void -tTransform1(z) Uint32 -tTransform2(z) Uint32 -linearTransform1(x) Uint32 -linearTransform2(x) Uint32 -rotateLeft(x,y) Uint32 } class GlobalConfig { +getConfig() Object +setConfig(obj) void } TsCrypto --> TsSM4 : "组合" TsCrypto --> GlobalConfig : "读取配置" ``` 图表来源 - [TsCrypto.js:5-34](file://src/utils/TsCrypto.js#L5-L34) - [TsSM4.js:96-456](file://src/utils/TsSM4.js#L96-L456) - [TsGlobalConfig.js:19-33](file://src/utils/TsGlobalConfig.js#L19-L33) 章节来源 - [TsCrypto.js:5-34](file://src/utils/TsCrypto.js#L5-L34) ### TsSM4 组件分析 - 角色定位:SM4 算法实现,支持 CBC/ECB 模式、Base64/text 输出、UTF-8 编解码、PKCS#7 填充/去填充。 - 关键点: - 支持 CBC/ECB 模式选择,默认 CBC;CBC 需要 16 字节 IV,否则抛错。 - 输出类型支持 Base64 与 text;输入统一为 UTF-8 字节流。 - 填充/去填充:按 16 字节块进行 PKCS#7 填充与去填充。 - 字符串编解码:通过 Crypt 工具类在 UTF-8 与 Base64 之间转换。 - 性能与复杂度: - 每块 16 字节,循环 32 轮;时间复杂度 O(n),空间复杂度 O(n)。 - 填充/去填充为线性处理,开销较小。 - 安全性: - CBC 模式下 IV 必须为 16 字节,且建议随机生成;当前实现未内置 IV 生成,需确保传入合法 IV。 - ECB 模式不推荐用于长文本或重复明文场景,易暴露模式特征。 ```mermaid flowchart TD Start(["开始"]) --> ToUtf8["UTF-8 编码为字节数组"] ToUtf8 --> Pad["PKCS#7 填充到 16 字节倍数"] Pad --> Mode{"模式选择"} Mode --> |CBC| CbcLoop["逐块 CBC 循环
链式 XOR + 轮函数"] Mode --> |ECB| EcbLoop["逐块 ECB 循环
直接轮函数"] CbcLoop --> OutSel{"输出类型"} EcbLoop --> OutSel OutSel --> |Base64| ToBase64["Base64 编码"] OutSel --> |text| ToText["UTF-8 解码"] ToBase64 --> End(["结束"]) ToText --> End ``` 图表来源 - [TsSM4.js:287-312](file://src/utils/TsSM4.js#L287-L312) - [TsSM4.js:338-387](file://src/utils/TsSM4.js#L338-L387) - [TsSM4.js:408-452](file://src/utils/TsSM4.js#L408-L452) 章节来源 - [TsSM4.js:96-456](file://src/utils/TsSM4.js#L96-L456) ### TsGlobalConfig 组件分析 - 角色定位:全局配置中心,提供默认配置与运行时合并。 - 关键点: - 默认 base64Key、prefix、httpParams、onHttpError 等。 - getConfig 返回 window.httpConfig 或默认配置;setConfig 合并传入对象。 - 与加密模块的关系: - TsCrypto 通过 getConfig().base64Key 读取密钥;TsHttpUtil 通过 getConfig().prefix/httpParams/onHttpError 影响请求行为。 章节来源 - [TsGlobalConfig.js:1-34](file://src/utils/TsGlobalConfig.js#L1-L34) - [TsCrypto.js:8-12](file://src/utils/TsCrypto.js#L8-L12) - [TsHttpUtil.js:100-106](file://src/https/TsHttpUtil.js#L100-L106) ### TsStorage 组件分析 - 角色定位:本地存储封装,提供 token 与加密开关的持久化。 - 关键点: - save/get:统一 JSON 序列化/反序列化。 - saveUserToken/getUserToken:token 的便捷存取。 - saveEncryptBody/getEncryptBody:加密开关的持久化,影响 HTTP 请求是否加密请求体。 章节来源 - [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55) - [TsHttpUtil.js:82-86](file://src/https/TsHttpUtil.js#L82-L86) ### TsHttpUtil 组件分析 - 角色定位:HTTP 请求封装,集成加密开关、请求体加密、响应体解密、token 注入。 - 关键点: - dealParamsBody:对 GET 参数与 POST 数据进行预处理;当加密开关开启时,将 data 包装为 { encryptData: TsCrypto.encrypt(JSON.stringify(data)) }。 - req:发起请求,自动拼接 prefix、注入 token、处理响应;若响应标记为加密,则调用 TsCrypto.decrypt 并尝试 JSON 解析。 - 错误处理:根据状态码映射错误信息,或调用全局 onHttpError 回调。 - 与加密模块的协作: - 使用 TsCrypto.encrypt/decrypt 完成请求体与响应体的加解密。 - 通过 TsStorage 控制加密开关,通过 TsGlobalConfig 控制前缀与附加参数。 章节来源 - [TsHttpUtil.js:50-91](file://src/https/TsHttpUtil.js#L50-L91) - [TsHttpUtil.js:99-134](file://src/https/TsHttpUtil.js#L99-L134) ## 依赖关系分析 - TsCrypto 依赖 TsSM4 与 TsGlobalConfig。 - TsHttpUtil 依赖 TsCrypto、TsStorage、TsGlobalConfig、TsCommon。 - TsSM4 依赖 base64-js(用于 Base64 编解码)。 - index.js 将各模块统一导出,供外部使用。 - package.json 声明 base64-js 与 umi-request 依赖。 ```mermaid graph LR TsCrypto["TsCrypto.js"] --> TsSM4["TsSM4.js"] TsCrypto --> TsGlobalConfig["TsGlobalConfig.js"] TsHttpUtil["TsHttpUtil.js"] --> TsCrypto TsHttpUtil --> TsStorage["TsStorage.js"] TsHttpUtil --> TsGlobalConfig TsHttpUtil --> TsCommon["TsCommon.js"] TsSM4 --> Base64["base64-js(依赖)"] index_js["index.js"] --> TsCrypto index_js --> TsSM4 index_js --> TsGlobalConfig index_js --> TsStorage index_js --> TsHttpUtil package_json["package.json"] --> Base64 package_json --> UmiReq["umi-request(依赖)"] ``` 图表来源 - [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) - [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) - [package.json:19-22](file://package.json#L19-L22) ## 性能考量 - 时间复杂度:SM4 每块 16 字节,32 轮,整体 O(n);填充/去填充为线性处理,开销较小。 - 内存占用:主要为输入/输出字节数组与中间块数组,空间复杂度 O(n)。 - Base64 编解码:在浏览器与 Node 环境均可用 base64-js,性能稳定。 - CBC/ECB 选择:CBC 增加链式处理,但无额外显著性能损耗;ECB 更简单但安全性较低。 - 建议: - 对大文本分块处理(当前实现按块处理,已具备良好扩展性)。 - 在浏览器端避免频繁重复加密,必要时缓存结果。 - 使用 CBC 模式并确保 IV 正确(当前实现要求 16 字节 IV,否则抛错)。 ## 故障排查指南 - “iv 错误”异常 - 现象:CBC 模式下抛出 iv 错误。 - 原因:未正确传入 16 字节 IV 或未传入 IV。 - 处理:确保传入长度为 16 的 IV,或切换至 ECB 模式。 - 参考路径:[TsSM4.js:345-347](file://src/utils/TsSM4.js#L345-L347)、[TsSM4.js:410-412](file://src/utils/TsSM4.js#L410-L412) - “密钥长度不为 16 字节” - 现象:构造 SM4 实例时抛出密钥长度错误。 - 原因:base64Key 解码后不是 16 字节。 - 处理:确认 base64Key 来自后端并符合规范。 - 参考路径:[TsSM4.js:103-105](file://src/utils/TsSM4.js#L103-L105) - “响应未解密” - 现象:响应未按预期解密。 - 原因:响应未标记为加密或密钥不一致。 - 处理:确认后端响应标记 encrypt 且密钥一致。 - 参考路径:[TsHttpUtil.js:119-122](file://src/https/TsHttpUtil.js#L119-L122) - “加密开关无效” - 现象:请求未加密。 - 原因:加密开关未启用或未持久化。 - 处理:调用 saveEncryptBody(true) 并确认存储生效。 - 参考路径:[TsStorage.js:17-23](file://src/utils/TsStorage.js#L17-L23)、[TsHttpUtil.js:82-86](file://src/https/TsHttpUtil.js#L82-L86) 章节来源 - [TsSM4.js:103-105](file://src/utils/TsSM4.js#L103-L105) - [TsSM4.js:345-347](file://src/utils/TsSM4.js#L345-L347) - [TsSM4.js:410-412](file://src/utils/TsSM4.js#L410-L412) - [TsHttpUtil.js:119-122](file://src/https/TsHttpUtil.js#L119-L122) - [TsStorage.js:17-23](file://src/utils/TsStorage.js#L17-L23) ## 结论 本加密模块以 TsCrypto 为核心,结合 TsSM4 的 SM4 算法实现,提供了 CBC/ECB 模式、Base64 编解码、PKCS#7 填充与去填充、UTF-8 字符串编解码能力,并与全局配置系统、存储系统、HTTP 请求模块形成完整闭环。通过加密开关与 token 注入,满足了请求体加密与安全传输的常见需求。建议在生产环境中优先使用 CBC 模式并妥善管理 IV 与密钥,遵循最小暴露原则与安全最佳实践。 ## 附录 ### API 接口文档 - TsCrypto.encrypt(content) - 功能:对明文字符串进行加密,返回 Base64 字符串。 - 输入:明文字符串。 - 输出:Base64 密文字符串。 - 参考路径:[TsCrypto.js:19-21](file://src/utils/TsCrypto.js#L19-L21)、[TsSM4.js:338-387](file://src/utils/TsSM4.js#L338-L387) - TsCrypto.decrypt(base64) - 功能:对 Base64 密文进行解密,返回明文字符串。 - 输入:Base64 密文字符串。 - 输出:明文字符串。 - 参考路径:[TsCrypto.js:28-30](file://src/utils/TsCrypto.js#L28-L30)、[TsSM4.js:395-452](file://src/utils/TsSM4.js#L395-L452) - TsSM4.encrypt(plaintext) - 功能:支持 CBC/ECB 模式、Base64/text 输出、UTF-8 编解码与 PKCS#7 填充。 - 输入:明文字符串。 - 输出:Base64 或 UTF-8 字符串(取决于 cipherType)。 - 参考路径:[TsSM4.js:338-387](file://src/utils/TsSM4.js#L338-L387) - TsSM4.decrypt(ciphertext) - 功能:支持 CBC/ECB 模式、Base64/text 输入、UTF-8 编解码与 PKCS#7 去填充。 - 输入:Base64 或 UTF-8 密文字符串。 - 输出:明文字符串。 - 参考路径:[TsSM4.js:395-452](file://src/utils/TsSM4.js#L395-L452) - TsGlobalConfig.getConfig()/setConfig(obj) - 功能:读取/设置全局配置,包括 base64Key、prefix、httpParams、onHttpError。 - 参考路径:[TsGlobalConfig.js:19-33](file://src/utils/TsGlobalConfig.js#L19-L33) - TsStorage.saveEncryptBody(bool)/getEncryptBody() - 功能:设置/获取加密开关,影响 HTTP 请求是否加密请求体。 - 参考路径:[TsStorage.js:17-23](file://src/utils/TsStorage.js#L17-L23) - TsHttpUtil.post/get/form(req) - 功能:统一发起 HTTP 请求,自动处理加密开关、请求体加密、响应体解密、token 注入。 - 参考路径:[TsHttpUtil.js:152-165](file://src/https/TsHttpUtil.js#L152-L165) ### 使用示例 - 启用请求体加密 - 设置加密开关:调用 saveEncryptBody(true)。 - 发送请求:post(url, data) 自动将 data 包装为 { encryptData: TsCrypto.encrypt(JSON.stringify(data)) }。 - 参考路径:[TsStorage.js:17-23](file://src/utils/TsStorage.js#L17-L23)、[TsHttpUtil.js:82-86](file://src/https/TsHttpUtil.js#L82-L86) - 响应体解密 - 若后端响应标记为加密,则自动调用 TsCrypto.decrypt 并尝试 JSON 解析。 - 参考路径:[TsHttpUtil.js:119-122](file://src/https/TsHttpUtil.js#L119-L122) - 自定义密钥与前缀 - 通过 setConfig({ base64Key, prefix }) 配置密钥与请求前缀。 - 参考路径:[TsGlobalConfig.js:27-29](file://src/utils/TsGlobalConfig.js#L27-L29)、[TsHttpUtil.js:100-106](file://src/https/TsHttpUtil.js#L100-L106) ### 安全最佳实践 - CBC 模式 - 使用 16 字节 IV,建议随机生成并随消息传输或在协议中约定。 - 避免重复使用相同的 IV 与密钥组合。 - ECB 模式 - 不适用于长文本或存在重复明文的场景,易泄露模式特征。 - 密钥管理 - base64Key 应来自可信后端,定期轮换;避免硬编码在前端。 - 响应校验 - 对响应进行完整性校验(如 HMAC),防止篡改。 - 日志与调试 - 生产环境避免打印密文与敏感信息;仅在开发环境启用严格日志级别。