字段级加密概念与原理
什么是字段级加密
说白了,字段级加密就是在数据库表的某个或某几个列上单独做加密,而不是把整张表甚至整个库打包成一个加密容器。我最初接触这个术语时,第一反应是“这不就是个列级别的加密吗?”——嗯,本质上确实如此,但它的设计边界比这要精细得多。
我们想想看:传统数据库加密方案,比如 TDE(透明数据加密),它加密的是磁盘上的整个数据文件。磁盘被拿走、文件被复制,数据是安全的。但一旦数据库跑起来,查询进来,TDE 自动解密——这时候内存里的数据就是明文的。如果你的应用需要严格控制不同用户看到不同字段,TDE 就帮不上忙了。
字段级加密的核心特点:
- 精细粒度:只加密敏感字段,比如身份证号、手机号、银行卡号。普通字段保持明文,不影响查询性能。
- 保留格式(可选):加密后数据仍能保持原格式,比如身份证号还是 18 位数字字符,方便存量系统兼容。
- 端到端保护:数据在应用层加密后才写入数据库。即使数据库被脱库,攻击者拿到的也是密文。查询时也只在应用层解密。
- 权限分离:DBA 没有密钥,无法读取敏感数据。这解决了 DBA“超级管理员”能看所有数据的老大难问题。
我的个人习惯:在开始做字段级加密之前,先梳理清楚哪些字段是真的敏感。不是所有数据都需要加密——姓名、性别、邮箱,很多场景下加密反而增加复杂度。我只对法律合规明确要求的字段(如 GDPR 中的个人识别信息、PCI-DSS 中的卡号)下刀。
加密算法选择:AES 还是 SM4
算法选择是个绕不开的决策点。我经历过一个项目,在 AES-256 和 SM4 之间反复权衡了两周。核心考量其实就是三个维度:安全性、性能、合规。
| 维度 | AES-256-GCM | SM4 |
|---|---|---|
| 算法标准 | NIST 标准,国际通用 | 中国国家密码管理局标准 |
| 分组 / 模式 | 128 位分组,GCM 模式(带认证) | 128 位分组,常用 CBC/CTR/GCM 模式 |
| 密钥长度 | 128 / 192 / 256 bit | 128 bit |
| 性能(软件实现) | 硬件加速(AES-NI)下极快 | 无专用指令,略慢于 AES |
| 国内合规 | 部分场景(如等保三级)要求使用国密 | 等保 / 密评 优先推荐 |
| 生态支持 | 所有语言、所有平台 | 主流语言均有实现,但部分小众框架欠缺 |
我曾经踩过的坑:在早期项目中选用了 AES-128-ECB 模式,因为实现简单。结果被安全审计报告打回来——ECB 模式下,相同明文块会产生相同密文块,图像类数据直接能看出轮廓。后来全部改成了 AES-256-GCM。所以我的建议是:优先选带认证加密的 AEAD 模式(如 GCM),既能加密又能防篡改。
密钥管理基础
算法选定后,真正的硬骨头才出现——密钥怎么管?我见过太多团队把密钥硬编码在配置里,或者跟数据库连在同一台机器上。这些做法基本等于没加密。
密钥管理三原则:
- 密钥与数据分离:加密密钥不能和密文数据存放在同一存储介质上。比如数据库服务器只存密文,KMS 或硬件安全模块(HSM)独立部署。
- 密钥分级:不直接用“最终加密密钥”加密所有字段。通常设计三级结构:
- 主密钥(Master Key):最顶层,负责保护下级密钥,通常存储在 KMS / HSM 中。
- 字段密钥(Field Key):每个字段或每组字段独立一个密钥,用主密钥加密后存储。
- 数据密钥(Data Key):实际加密数据的短期密钥,定期轮换。
- 密钥轮换:定期更换密钥。旧数据可以用旧密钥解密,新写入数据使用新密钥。
下面是三级密钥结构的示意图——也是我个人非常推荐的一种落地方式:
关于轮换的实际经验:我以前做金融项目时,监管要求数据密钥每 90 天轮换一次。但全量重加密(用新密钥重新加密所有历史数据)对在线系统冲击太大。我们实际采用了双密钥策略:保留旧密钥用于读取历史数据,新密钥只用于新写入。这样避免了在线重加密,代价是密钥存储量翻倍。好在字段级加密的密钥数本来就不多,这个代价完全可以接受。
字段级加密的几种落地模式
在端侧(应用层)执行加密,还是让数据库代理帮你搞定?这取决于你的架构和管控力度。
| 模式 | 加密位置 | 优点 | 缺点 |
|---|---|---|---|
| 应用层 SDK | 业务代码中调用 SDK 加密 | 灵活、可控、可保留格式 | 需要改造代码、逻辑散落 |
| 数据库代理 | 中间件拦截 SQL 语句 | 业务无感知、集中管控 | 代理成为性能瓶颈、兼容性风险 |
| 存储过程 / UDF | 数据库内部函数加解密 | 部署简单 | 密钥容易被 DBA 读取、不支持跨库 |
我做技术选型时的原则:如果团队有足够的工程能力,推荐应用层 SDK 模式。虽然“改代码”听起来麻烦,但你在代码中能精确控制什么时候加解密、怎么处理异常。代理模式虽然“零侵入”,但出了问题很难排——我见过代理因为一条复杂 JOIN 语句的性能抖动,拖垮整个业务链的例子。
小结与思考
字段级加密的本质,就是在“数据可用”和“数据安全”之间找一个平衡点。它不像全库加密那样一刀切,也不像不给权限控制那样裸奔。算法选对了、密钥管好了、加密模式落地合理了,你就已经解决掉了 80% 的数据泄露风险。
你会遇到问题,比如:加了索引的字段怎么加密?密文上能建索引吗?嗯,这些我会在后面的章节用专门的篇幅跟你聊。这里先画个问号,记下来就好。