第 2 章 字段级加密SDK常见架构与设计模式归纳总结
做这一行久了,你会发现字段级加密SDK的架构来来去去就那么几套。我刚开始接触时也觉得设计很玄乎,后来拆过好几个商业SDK的源码,嗯,其实核心骨架都差不多。这一章咱们就把它们扒开看看。
2.1 整体架构分层
说白了,一个能扛住生产环境的字段级加密SDK,通常分四层。每层各司其职,改一层不影响别的层——这一点在版本升级时特别重要,我吃过亏。
- 接口层(API Layer):对外暴露encrypt、decrypt、mask等统一方法。只关心入参出参,不关心底下怎么算。
- 加密策略层(Strategy Layer):根据字段元数据(如算法、密钥ID)选择具体加密方案。这里是设计模式的重灾区(后面细讲)。
- 密钥管理层(Key Management Layer):拉取、缓存、轮换密钥。记得当年线上事故就是因为密钥拉取超时没降级……
- 底层加密库(Crypto Provider):调用原生或第三方加密实现(OpenSSL、Bouncy Castle、国密SM4等)。
关键点:层与层之间通过抽象的接口交互,不要直接引用具体实现类。否则SDK版本升级时你会被“循环依赖”搞得想骂人。
2.2 核心设计模式
这里列几个我个人工程里必用的模式,不扯理论,直接说拿来干嘛。
| 模式 | 解决什么问题 | 我的踩坑案例 |
|---|---|---|
| 策略模式 | 字段A用AES-256,字段B用国密SM4,运行时根据注解/配置切换算法 | 曾经把所有if-else写死在service里,升级加一种算法改了十几个文件 |
| 装饰器模式 | 给加密结果加版本号、做缓存、做日志,不污染核心加密逻辑 | 用继承实现缓存,结果子类爆炸,换装饰器后清爽多了 |
| 工厂模式 | 根据版本号自动创建兼容旧版解密器,方便向后兼容 | 有个项目手写Map硬编码版本映射,新版本加了漏掉旧版,线上解密失败 |
| 模板方法 | 加密/解密流程固定(校验参数→获取密钥→执行算法→处理结果),子类只重写算法部分 | 以前每加一个加密算法都复制整个流程,改了流程就要改N处 |
一个小建议:设计初期就把这些模式嵌进去,别等SDK发布V2.0再重构。我在V1.0时偷懒没用策略模式,V2.0改了一个半月,还被客户投诉API不兼容。
2.3 架构选型对比
不同的业务场景,适合的架构也不太一样。我整理了一个对比表,你可以拿来当参考。
| 架构风格 | 优点 | 缺点 | 典型场景 |
|---|---|---|---|
| 单体胖SDK | 部署简单,依赖自包含 | 升级困难,二进制体积大 | 嵌入式设备、Android客户端 |
| 微服务+瘦SDK | 加密逻辑集中管理,客户端只做网络调用 | 增加网络延迟和依赖 | 高并发后端服务、多语言环境 |
| 插件式+SPI | 算法/密钥源可热插拔,兼容性极好 | 接口设计复杂,调试困难 | 多云密钥管理、合规审计 |
特别注意:单体胖SDK里千万别把Key和密文写死在一起。我曾经接手过一个项目,加密SDK自带了一个硬编码的默认密钥——测试环境用的,结果客户直接上了生产。嗯,后果你懂的。
2.4 一张图看懂架构
下面这张图表是我自己项目里截出来的简化版。你可以把它当作设计SDK时的“脚手架”。
注意看,每一层都只和下一层通过抽象接口通信。我习惯在接口层放一个版本号协商逻辑——客户端传个版本号,策略层自动选择对应的解密流程。这样升级时就不用停服了。
2.5 避坑指南
最后说几个我用真金白银换来的教训。
- 别把密钥信息硬编码在SDK里:哪怕测试环境也不行。我曾经觉得“临时用一下”,结果被合规部门查出来,补了三个月的整改报告。
- 版本兼容不是“加个if”那么简单:旧版密文格式可能没有版本号字段,解密时怎么识别?我建议第一期设计就在密文头部留2个字节做魔数+版本。
- 加密策略层要支持动态加载:否则每次加新算法都得发版。用SPI或者类似机制,让用户自己实现接口,放到classpath就行。
我的小工具:写了一个代码生成器,根据你定义的字段元数据自动生成策略层代码。虽然不算完美,但至少避免了手写重复的Factory类。感兴趣的话可以拿去改改。