2. 字段级加密SDK的架构设计:模块划分与数据流
做字段级加密,架构设计是重中之重。我见过不少团队上来就硬编码加解密逻辑,结果后来字段一多,密钥一换,整个项目跟着重构。说白了,模块边界划不清楚,后面维护成本会翻好几倍。
这一章咱们就聊聊SDK内部到底长什么样。我习惯把架构拆成五个核心模块——密钥管理、加解密引擎、字段选择与适配、配置与策略、审计与日志。先看整体分层关系,再逐个展开细节。
2.1 密钥管理模块 —— 命脉所在
职责: 统一管理加密密钥的生命周期:获取、缓存、轮换、失效处理。
这个模块很容易被低估。你以为存个密钥就完事了?其实坑很多。比如密钥过期了,SDK该抛异常还是静默回退?我曾经遇到过这样的线上事故:密钥轮换时缓存没刷新,旧密钥被删除后新密钥还没生效,结果有一分钟所有加密操作都失败了。
| 子能力 | 说明 | 我踩过的坑 |
|---|---|---|
| 密钥获取 | 支持本地文件、KMS、Vault等多种数据源 | 连KMS超时没设短超时,接口堵死 |
| 密钥缓存 | LRU缓存+过期刷新,减少远程调用 | 缓存过期时间设得太长,轮换后还用旧密钥 |
| 密钥轮换 | 支持版本号机制,灰度切换 | 多版本同时存在,加解密版本不匹配 |
| 访问控制 | 限制密钥使用范围(如仅加密、仅解密) | 审计中发现密文被误解密 |
2.2 加解密引擎 —— 核心运算层
加解密引擎负责真正的算法执行。我建议引擎本身不做任何策略判断,它只接收“输入数据 + 密钥材料”,然后返回加密结果或解密结果。
- 算法选择: 默认推荐
AES-256-GCM(兼顾安全与性能),也可扩展国密SM4-GCM。 - 数据包格式: 非对称的 IV + 密文 + 认证标签,按预定协议组装。
- 性能优化: 使用
ThreadLocal复用 Cipher 实例,减少对象创建开销。 - 兼容性: 旧版本的数据包格式要能识别并兼容解密。
2.3 字段选择与适配模块 —— 精准打击
这个模块是SDK里最容易被忽视的部分。说白了,它解决三个问题:哪些字段要加密?字段是什么类型?嵌套对象怎么处理?
我习惯用注解 + 配置文件的混合模式。举一个实际例子:
// Java 注解声明敏感字段
@Encrypted(algorithm = "AES-GCM", keyId = "user-key-v2")
private String idCard;
@Encrypted(encryptMode = EncryptMode.SKIP_IF_NULL)
private String phone;
// 对于嵌套对象,还需要指定脱敏策略
@EncryptedFields({
@EncryptedField(path = "address.province", enable = false),
@EncryptedField(path = "address.detail", encrypt = true)
})
private Address address;
注意:你想想看,嵌套对象的处理有多麻烦?JSON里的深层字段,如果硬编码路径,改一个字段名所有加密配置都要跟着改。所以我推荐用 路径表达式(类似JSONPath) 来做字段定位,这样配置和代码完全解耦。
2.4 配置与策略模块 —— 调度大脑
这个模块不直接处理数据,但所有加密行为都由它控制。用表格看更清楚:
| 配置项 | 作用 | 示例值 |
|---|---|---|
| 字段映射表 | 指定类/字段对应的密钥和算法 | user.idCard → keyId=v2, algo=AES-GCM |
| 加密策略 | 条件判断:为空、不加密、脱敏 | encrypt_if_present |
| 回滚策略 | 升级后自动回退至旧版字段配置 | rollback_to: v1.0 |
| 密钥优先级 | 多个密钥版本同时存在时的选择规则 | latest_active |
2.5 审计与日志模块 —— 出了问题别抓瞎
加密操作一旦出问题,溯源非常重要。这个模块负责记录:
- 每条加密/解密请求的请求ID、时间戳
- 涉及的字段名、密钥版本
- 操作结果(成功/失败,失败原因)
- 性能指标:加解密耗时、缓存命中率
为什么要强调这个?有一次我排查线上慢问题,发现加密延迟突然飙高,最后查日志看到缓存未命中数暴增——原来是密钥管理模块的连接池被占满了。没有日志,这个问题根本没法定位。
2.6 数据流全局透视
上面几个模块之间是怎么配合的?打个比方:假设一个请求进来要加密用户身份证:
- 应用层调用
sdk.encrypt(user) - 字段选择模块扫描对象,发现
idCard上有@Encrypted注解,确认需要加密。 - 配置与策略模块查出算法为
AES-GCM,密钥标识user-key-v2。 - 密钥管理模块根据标识获取密钥(先查缓存,缓存不存在则从远程取)。
- 加解密引擎用该密钥对
idCard的明文进行加密,返回密文。 - 字段选择模块将密文填回对象的对应字段。
- 审计模块记录本次操作日志。
解密流程基本逆向,只是密钥管理模块要能根据数据包中的密钥版本号找到正确密钥。