# SM4 算法 API **本文引用的文件** - [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. [结论](#结论) 10. [附录](#附录) ## 简介 本文件为 SM4 对称加密算法模块的完整 API 参考文档,覆盖以下内容: - 方法签名与参数类型(明文、密钥、IV 向量、输出类型) - 返回值类型与数据格式 - CBC 与 ECB 两种加密模式支持 - 自动填充与去填充机制 - 字节序与位运算处理细节 - 与 Base64 编解码的集成方式与数据格式转换 - 安全性考虑、性能特征与适用场景 - 扩展与自定义方法建议 ## 项目结构 该工具包通过统一入口导出多个工具模块,其中 SM4 模块位于 src/utils/TsSM4.js,并在 index.js 中集中导出。 ```mermaid graph TB A["index.js
统一导出入口"] --> B["TsSM4.js
SM4 实现"] A --> C["TsCrypto.js
基于 SM4 的加密器封装"] A --> D["TsGlobalConfig.js
全局配置含 base64Key"] E["package.json
依赖声明"] --> F["base64-js@1.5.1"] B --> F C --> B C --> D ``` 图表来源 - [index.js:1-16](file://index.js#L1-L16) - [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) - [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) ## 核心组件 - TsSM4:SM4 对称加密算法实现,支持 CBC/ECB 模式、PKCS#7 填充、Base64 文本输出。 - Crypt:字符串与字节数组、Base64 之间的编解码辅助工具。 - TsCrypto:基于 SM4 的应用层加密器,使用全局配置中的 base64Key 初始化。 章节来源 - [TsSM4.js:96-455](file://src/utils/TsSM4.js#L96-L455) - [TsCrypto.js:5-34](file://src/utils/TsCrypto.js#L5-L34) - [TsGlobalConfig.js:5-33](file://src/utils/TsGlobalConfig.js#L5-L33) ## 架构总览 SM4 模块以面向对象的方式组织,内部包含: - 常量表:S 盒、轮常数 CK、初始常数 FK - 工具类 Crypt:UTF-8 字符串与 Uint8Array 的互转、Base64 与 Uint8Array 的互转 - 主类 TsSM4:密钥展开、轮函数、填充/去填充、CBC/ECB 加解密流程 ```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 +constructor(config) +doBlockCrypt(blockData, roundKeys) Uint32Array +spawnEncryptRoundKeys() void +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 } TsSM4 --> Crypt : "使用" ``` 图表来源 - [TsSM4.js:39-94](file://src/utils/TsSM4.js#L39-L94) - [TsSM4.js:96-455](file://src/utils/TsSM4.js#L96-L455) ## 详细组件分析 ### 类:TsSM4(SM4 算法主类) - 职责 - 密钥展开与轮密钥生成 - 轮函数与线性变换 - PKCS#7 填充与去填充 - CBC/ECB 模式加解密 - 输出类型(Base64 或 UTF-8 文本) - 关键成员 - key:16 字节密钥(Uint8Array) - iv:16 字节 IV(Uint8Array),CBC 模式必需 - mode:'cbc' 或 'ecb' - cipherType:'base64' 或 'text' - encryptRoundKeys / decryptRoundKeys:32 轮密钥数组(Uint32Array) - 关键方法 - constructor(config) - 参数:config.keyBuffer(必填,16 字节)、config.iv(可选,16 字节)、config.mode('cbc'|'ecb')、config.outType('base64'|'text') - 行为:校验长度、初始化轮密钥、准备正向/逆向轮密钥 - encrypt(plaintext: String): String - 行为:UTF-8 编码 -> PKCS#7 填充 -> 分块处理 -> CBC/ECB -> 输出类型转换 - 返回:Base64 字符串或 UTF-8 文本 - decrypt(ciphertext: String): String - 行为:根据 cipherType 解码 -> 分块处理 -> CBC/ECB -> 去填充 -> UTF-8 解码 - 返回:明文字符串 - 数据流与算法要点 - 字节序:大端序(MSB 在前),按 4 字节组合为 Uint32 - 轮函数:32 轮迭代,使用 S 盒替换与线性变换 - CBC 链接:前一分组密文作为下一分组的 IV - 填充:按 16 字节对齐,填充长度为填充字节数 章节来源 - [TsSM4.js:96-156](file://src/utils/TsSM4.js#L96-L156) - [TsSM4.js:158-180](file://src/utils/TsSM4.js#L158-L180) - [TsSM4.js:189-207](file://src/utils/TsSM4.js#L189-L207) - [TsSM4.js:217-241](file://src/utils/TsSM4.js#L217-L241) - [TsSM4.js:250-277](file://src/utils/TsSM4.js#L250-L277) - [TsSM4.js:287-312](file://src/utils/TsSM4.js#L287-L312) - [TsSM4.js:322-329](file://src/utils/TsSM4.js#L322-L329) - [TsSM4.js:338-387](file://src/utils/TsSM4.js#L338-L387) - [TsSM4.js:395-452](file://src/utils/TsSM4.js#L395-L452) ### 类:Crypt(编解码工具) - 字符串与字节数组 - stringToArrayBufferInUtf8(str: String): Uint8Array - utf8ArrayBufferToString(buf: Uint8Array): String - Base64 与字节数组 - arrayBufferToBase64(buf: Uint8Array): String - base64ToArrayBuffer(str: String): Uint8Array 章节来源 - [TsSM4.js:39-94](file://src/utils/TsSM4.js#L39-L94) ### 类:TsCrypto(应用层封装) - 使用全局配置中的 base64Key 初始化 SM4(ECB 模式,输出 Base64) - 提供 encrypt/content 和 decrypt/base64 接口 章节来源 - [TsCrypto.js:5-34](file://src/utils/TsCrypto.js#L5-L34) - [TsGlobalConfig.js:5-33](file://src/utils/TsGlobalConfig.js#L5-L33) ### API 规范与使用示例 - 构造函数 - 名称:TsSM4(config) - 参数: - keyBuffer: Uint8Array(必须,16 字节) - iv?: String(可选,16 字节;CBC 模式必需) - mode?: 'cbc'|'ecb'(默认 'cbc') - outType?: 'base64'|'text'(默认 'base64') - 返回:TsSM4 实例 - 异常:当 keyBuffer 长度不为 16 或 iv 长度不为 16 时抛出错误 - 加密 - 名称:encrypt(plaintext: String): String - 输入:明文字符串(UTF-8) - 处理:填充 -> 分块 -> CBC/ECB -> 输出类型转换 - 输出:Base64 字符串或 UTF-8 文本(取决于 outType) - 解密 - 名称:decrypt(ciphertext: String): String - 输入:密文字符串(Base64 或 UTF-8,取决于 outType) - 处理:解码 -> 分块 -> CBC/ECB -> 去填充 -> UTF-8 - 输出:明文字符串 - 示例(路径) - CBC 模式加密:[TsSM4.js:338-387](file://src/utils/TsSM4.js#L338-L387) - ECB 模式加密:[TsSM4.js:368-378](file://src/utils/TsSM4.js#L368-L378) - CBC 模式解密:[TsSM4.js:395-452](file://src/utils/TsSM4.js#L395-L452) - ECB 模式解密:[TsSM4.js:434-447](file://src/utils/TsSM4.js#L434-L447) - 应用层封装使用:[TsCrypto.js:19-30](file://src/utils/TsCrypto.js#L19-L30) 章节来源 - [TsSM4.js:96-156](file://src/utils/TsSM4.js#L96-L156) - [TsSM4.js:338-452](file://src/utils/TsSM4.js#L338-L452) - [TsCrypto.js:19-30](file://src/utils/TsCrypto.js#L19-L30) ### 流程图:CBC 模式加密 ```mermaid flowchart TD Start(["开始"]) --> Encode["UTF-8 编码明文"] Encode --> Pad["PKCS#7 填充到 16 字节倍数"] Pad --> InitChain["初始化链寄存器为 IVCBC"] InitChain --> Loop{"遍历每个 16 字节块"} Loop --> |是| Xor["与上一密文块异或CBC"] Xor --> Round["32 轮加密轮函数+S 盒+线性变换"] Round --> Save["保存当前密文块"] Save --> Next["下一个明文块"] Next --> Loop Loop --> |否| OutType["根据 outType 输出Base64 或文本"] OutType --> End(["结束"]) ``` 图表来源 - [TsSM4.js:338-387](file://src/utils/TsSM4.js#L338-L387) ### 流程图:ECB 模式解密 ```mermaid flowchart TD Start(["开始"]) --> Decode["根据 outType 解码Base64 或文本"] Decode --> Blocks["按 16 字节分块"] Blocks --> DecryptLoop{"遍历每个 16 字节块"} DecryptLoop --> |是| Round["32 轮解密逆序轮密钥"] Round --> Save["保存明文块"] Save --> Next["下一个块"] Next --> DecryptLoop DecryptLoop --> |否| Depad["去填充移除 PKCS#7"] Depad --> Utf8["UTF-8 解码"] Utf8 --> End(["结束"]) ``` 图表来源 - [TsSM4.js:395-452](file://src/utils/TsSM4.js#L395-L452) ### 序列图:应用层加密调用 ```mermaid sequenceDiagram participant App as "应用" participant Crypto as "TsCrypto" participant SM4 as "TsSM4" participant Config as "TsGlobalConfig" App->>Crypto : "new TsCrypto()" Crypto->>Config : "getConfig()" Config-->>Crypto : "{base64Key}" Crypto->>Crypto : "base64Key -> Uint8Array" Crypto->>SM4 : "new TsSM4({keyBuffer, mode : 'ecb', outType : 'base64'})" App->>Crypto : "encrypt(明文)" Crypto->>SM4 : "encrypt(明文)" SM4-->>Crypto : "密文(Base64)" Crypto-->>App : "密文(Base64)" ``` 图表来源 - [TsCrypto.js:7-13](file://src/utils/TsCrypto.js#L7-L13) - [TsGlobalConfig.js:19-29](file://src/utils/TsGlobalConfig.js#L19-L29) - [TsSM4.js:96-156](file://src/utils/TsSM4.js#L96-L156) ## 依赖关系分析 - 内部依赖 - TsCrypto 依赖 TsSM4 与 TsGlobalConfig - TsSM4 依赖 Crypt 与 base64-js - 外部依赖 - base64-js@1.5.1:Base64 编解码 - umi-request@1.4.0:HTTP 请求(在 https 模块中使用) ```mermaid graph LR TsCrypto["TsCrypto.js"] --> TsSM4["TsSM4.js"] TsCrypto --> TsGlobalConfig["TsGlobalConfig.js"] TsSM4 --> Base64["base64-js@1.5.1"] Package["package.json"] --> Base64 ``` 图表来源 - [TsCrypto.js:1-3](file://src/utils/TsCrypto.js#L1-L3) - [TsSM4.js:1](file://src/utils/TsSM4.js#L1) - [package.json:19-22](file://package.json#L19-L22) 章节来源 - [TsCrypto.js:1-3](file://src/utils/TsCrypto.js#L1-L3) - [package.json:19-22](file://package.json#L19-L22) ## 性能与安全考量 - 性能特征 - 32 轮迭代,每块 16 字节,适合小批量数据快速加解密 - 使用 TypedArray 进行位运算,避免频繁装箱开销 - Base64 编解码在浏览器与 Node 环境均可用 - 安全性考虑 - CBC 模式需要随机且唯一的 IV;若 IV 固定,会降低安全性 - 密钥长度固定为 16 字节,需确保密钥熵足够 - 填充采用 PKCS#7,需确保去填充逻辑正确 - 适用场景 - 小型数据加密(如配置项、令牌、短消息) - 与 HTTP 加密传输结合使用(参考 README 中的 HttpUtil 配置) 章节来源 - [TsSM4.js:343-378](file://src/utils/TsSM4.js#L343-L378) - [TsSM4.js:408-447](file://src/utils/TsSM4.js#L408-L447) - [README.md:12-26](file://README.md#L12-L26) ## 故障排查指南 - 常见错误 - 密钥长度不为 16 字节:构造函数抛错 - IV 非空但长度不为 16 字节:CBC 模式抛错 - 输出类型与输入不匹配:解密失败或结果异常 - 排查步骤 - 确认密钥与 IV 均为 16 字节 - 确认 outType 与实际输入一致 - 检查 Base64 编码是否完整 - 核对 CBC/ECB 模式选择与业务需求一致 章节来源 - [TsSM4.js:102-105](file://src/utils/TsSM4.js#L102-L105) - [TsSM4.js:116-122](file://src/utils/TsSM4.js#L116-L122) - [TsSM4.js:345-347](file://src/utils/TsSM4.js#L345-L347) - [TsSM4.js:410-412](file://src/utils/TsSM4.js#L410-L412) ## 结论 本模块提供了完整的 SM4 对称加密能力,支持 CBC/ECB 模式与 PKCS#7 填充,具备良好的跨平台兼容性(浏览器/Node)。通过 TsCrypto 可直接用于业务场景,推荐在 CBC 模式下使用随机 IV,并严格管理密钥与输出类型,以确保安全性与一致性。 ## 附录 ### API 一览(方法签名与参数) - TsSM4(config) - config.keyBuffer: Uint8Array(16 字节) - config.iv?: String(16 字节;CBC 必需) - config.mode?: 'cbc'|'ecb' - config.outType?: 'base64'|'text' - encrypt(plaintext: String): String - decrypt(ciphertext: String): String 章节来源 - [TsSM4.js:96-156](file://src/utils/TsSM4.js#L96-L156) - [TsSM4.js:338-452](file://src/utils/TsSM4.js#L338-L452) ### 数据格式与转换 - 字节序:大端序(MSB 在前) - 填充:PKCS#7(1-16 字节) - 输出类型: - 'base64':Base64 字符串 - 'text':UTF-8 文本(浏览器/Node 环境均支持) 章节来源 - [TsSM4.js:322-329](file://src/utils/TsSM4.js#L322-L329) - [TsSM4.js:287-312](file://src/utils/TsSM4.js#L287-L312) - [TsSM4.js:381-386](file://src/utils/TsSM4.js#L381-L386) - [TsSM4.js:398-404](file://src/utils/TsSM4.js#L398-L404) ### 扩展与自定义 - 支持自定义 IV(CBC 模式) - 支持自定义输出类型(Base64 或文本) - 可在应用层封装更多模式(如 GCM/CTR),但当前实现仅支持 CBC/ECB 章节来源 - [TsSM4.js:115-141](file://src/utils/TsSM4.js#L115-L141) - [TsCrypto.js:7-13](file://src/utils/TsCrypto.js#L7-L13)