14 KiB
14 KiB
加密配置
**本文引用的文件列表** - [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)目录
简介
本指南围绕项目中的 SM4 加密配置展开,系统性说明 CBC 与 ECB 模式的配置与使用差异、base64Key 的作用与长度要求、安全性考量,以及在数据传输加密与存储加密等场景下的配置建议。同时覆盖加密模式切换、与全局配置的关系与继承机制、最佳实践(密钥管理、性能优化、安全加固)、以及测试与验证方法。文档严格基于仓库源码进行分析与总结,避免臆测。
项目结构
该项目采用“工具类 + 组件化”的组织方式:
- 工具层:SM4 实现、通用加密封装、全局配置、本地存储、通用方法
- 业务集成层:HTTP 请求工具,负责在请求前后对数据进行加解密
- 入口导出:统一通过入口文件导出各模块
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
图表来源
章节来源
核心组件
- SM4 加密实现:提供 CBC/ECB 模式、PKCS#7 填充、Base64 文本输出、密钥扩展与轮函数等完整实现
- 加密封装:基于 SM4 构建默认实例,读取全局配置中的 base64Key,并默认以 ECB 模式工作
- 全局配置:提供 base64Key、前缀、HTTP 参数注入、错误回调等配置项
- HTTP 工具:在请求体加密开关开启时,对请求体进行加密;在响应标记为加密时进行解密
- 本地存储:提供开关控制是否对请求体进行加密
章节来源
架构总览
下图展示了从请求发起到加解密处理的关键流程,以及与全局配置、本地存储的关系。
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
- TsHttpUtil.js:119-122
- TsCrypto.js:19-30
- TsSM4.js:338-387
- TsSM4.js:395-452
- TsStorage.js:17-23
详细组件分析
SM4 加密实现(TsSM4)
- 模式支持:CBC、ECB 双模式,可通过构造参数选择
- IV 要求:CBC 模式必须提供 16 字节 IV;ECB 模式可省略 IV
- 密钥要求:必须为 16 字节(128 位),构造时会校验
- 输出类型:支持 Base64 与文本两种输出类型
- 填充策略:PKCS#7 填充,解密时自动去除
- 轮函数与密钥扩展:内置完整的 SM4 轮函数与轮密钥生成逻辑
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 : "使用"
图表来源
章节来源
加密封装(TsCrypto)
- 默认使用 ECB 模式
- 从全局配置读取 base64Key 并转换为字节数组作为密钥
- 对外暴露 encrypt、decrypt 接口,内部委托给 TsSM4
章节来源
全局配置(TsGlobalConfig)
- 提供 base64Key、prefix、httpParams、onHttpError 等配置项
- 支持运行时 setConfig 合并默认配置
- HTTP 工具通过 getConfig 获取 prefix 与 httpParams 注入
章节来源
HTTP 工具(TsHttpUtil)
- 在请求体加密开关开启时,将 data 包装为 { encryptData: 加密结果 }
- 在响应标记 encrypt 时,对 data 执行解密并解析 JSON
- 支持 GET/POST/form 等多种请求类型
章节来源
本地存储(TsStorage)
- 提供 getEncryptBody/saveEncryptBody 开关,用于控制请求体是否加密
- 与 HTTP 工具配合使用
章节来源
依赖关系分析
- TsCrypto 依赖 TsSM4 与 TsGlobalConfig
- TsHttpUtil 依赖 TsCrypto、TsStorage、TsGlobalConfig
- TsSM4 依赖 base64js(用于 Base64 编解码)
graph LR
base64js["base64js"] --> SM4["TsSM4"]
GlobalCfg["TsGlobalConfig"] --> Crypto["TsCrypto"]
SM4 --> Crypto
Crypto --> HttpUtil["TsHttpUtil"]
Storage["TsStorage"] --> HttpUtil
Common["TsCommon"] --> HttpUtil
图表来源
章节来源
性能考量
- 模式选择
- 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
- TsSM4.js:118-121
- TsSM4.js:345-347
- TsSM4.js:410-412
- TsCrypto.js:8-12
- TsHttpUtil.js:82-88
- TsHttpUtil.js:119-122
结论
本项目以 TsSM4 为核心,通过 TsCrypto 封装默认 ECB 模式与 base64Key,结合 TsHttpUtil 的请求体加密与响应解密能力,形成一套可配置、可扩展的加密方案。实际部署中应优先采用 CBC 模式并妥善管理 IV 与密钥,确保输出类型与后端一致,并通过全局配置集中管理密钥与前缀等参数。
附录
加密配置选项与说明
- base64Key
- 作用:作为 SM4 密钥的 Base64 字符串,构造时会被解码为 16 字节密钥
- 长度要求:解码后必须为 16 字节(128 位)
- 安全性:应由后端生成并下发,避免硬编码泄露;定期轮换
- 模式选择
- CBC:需提供 16 字节 IV;更安全,推荐用于大多数场景
- ECB:无需 IV;简单但安全性较低,仅在特定场景使用
- 输出类型
- Base64:便于网络传输与日志记录
- 文本:体积更小,但需确保后端一致
- IV 要求
- CBC 模式必须提供 16 字节 IV;ECB 模式可省略
章节来源
不同场景下的配置建议
- 数据传输加密(HTTP 请求体)
- 开启请求体加密开关
- 使用 CBC 模式并提供 16 字节 IV(若后端支持)
- 输出类型建议 Base64
- 存储加密(本地或数据库)
- 若明文为字符串,建议使用 ECB 模式简化处理
- 若存在重复明文块,建议使用 CBC 模式并随机 IV
- 输出类型根据存储介质选择(Base64 更通用)
章节来源
加密模式切换与注意事项
- 切换方法
- 通过 TsCrypto 构造参数或直接创建 TsSM4 实例指定 mode 与 iv/cipherType
- 注意事项
- CBC 必须提供 16 字节 IV;ECB 可省略 IV
- 输出类型需与后端保持一致
- 切换模式后需同步后端解密逻辑
章节来源
最佳实践
- 密钥管理
- 使用强随机生成的 16 字节密钥,避免硬编码
- 通过安全渠道下发 base64Key,定期轮换
- 性能优化
- 对小数据优先使用 ECB;对大数据优先使用 CBC
- 合理选择输出类型,平衡体积与兼容性
- 安全加固
- CBC 模式务必使用随机 IV
- 对响应数据进行完整性校验(如 HMAC)
- 限制日志中输出密文,必要时仅输出摘要
加密配置与全局配置的关系与继承机制
- TsCrypto 默认从全局配置读取 base64Key,并以 ECB 模式初始化
- TsHttpUtil 通过 GlobalConfig.getConfig 获取 prefix 与 httpParams,用于请求拼接与参数注入
- setConfig 可合并默认配置,实现运行时动态调整
章节来源
测试方法与验证步骤
- 单元测试(建议)
- 使用固定明文与密钥,验证加解密一致性
- 分别测试 ECB 与 CBC 模式,确保 IV 正确性
- 验证 Base64 与文本输出类型的互操作
- 端到端测试(建议)
- 通过 HTTP 工具发起请求,开启请求体加密,验证响应解密
- 模拟后端响应标记为加密,验证解密流程
- 日志与监控
- 记录关键配置项(模式、输出类型、IV 是否提供)
- 对异常进行捕获与上报
章节来源