# 加密配置 **本文引用的文件列表** - [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)