4. 数据加密密钥(DEK)与密钥加密密钥(KEK)归纳总结
到现在为止,我们已经聊了信封加密的核心流程。说实话,很多刚接触云上加密的同学,最容易绕晕的地方就是那两个缩写——DEK 和 KEK。我自己刚开始也搞混过,到底哪个是用来加密数据的,哪个是用来保护密钥本身的?
今天这一章,我们就彻底把这两个角色掰扯清楚。我习惯用一句话来区分它们:DEK 是干活的那个,KEK 是管人的那个。你想想看,DEK 直接面对你的业务数据,而 KEK 只负责保护 DEK,不碰数据本身。
4.1 DEK:数据加密密钥
DEK,全称 Data Encryption Key。它就是那个真正用来加密和解密你业务数据的密钥。不管你用 AES-256 还是 SM4,最终计算的时候都得拿 DEK 上。
DEK 有几个关键特性:
- 生命周期短:通常一次一换,或者几天一换。我见过一些项目把 DEK 用半年不换,差点出大事。
- 对称密钥:加密和解密用同一把密钥。算法常见的是 AES-256、SM4。
- 永远不能明文落盘:这是底线。DEK 只在内存里使用,用完就销毁。
4.2 KEK:密钥加密密钥
KEK,全称 Key Encryption Key。它的职责很单一——保护 DEK。说白了,KEK 就是用来给 DEK 裹一层保护壳的钥匙。
我举个例子。你在数据库里存了 100 个文件的 DEK,每个都是明文?那如果数据库被拖库,你所有的加密数据相当于白加密。但如果每个 DEK 都用 KEK 加密后再存储,黑客拿到数据库也只是一堆密文,他解不开。
核心区别一句话:
DEK 加密你的数据,KEK 加密你的 DEK。
KEK 的特点包括:
- 生命周期长:可以几个月甚至几年保持不变。但要配合轮换策略。
- 存储在 KMS 或 HSM 内部:永远不暴露到业务服务器上。调用 KMS 的 API 时,传进去的是密文 DEK,KMS 用 KEK 解密后返回。
- 主密钥角色:在信封加密里,KEK 就是那层信封的封口。
4.3 两者关系对比
我用一张表格帮你理清它们的差异。这个表格我自己做项目时经常拿出来给团队讲,清晰得很。
| 对比维度 | DEK(数据加密密钥) | KEK(密钥加密密钥) |
|---|---|---|
| 加密对象 | 业务数据(文件、数据库记录等) | DEK 本身 |
| 存储位置 | 加密后存储在数据库或本地磁盘 | KMS / HSM 内部,不可导出明文 |
| 生命周期 | 短(一次一换或按天轮换) | 长(按季度或按年轮换) |
| 访问频率 | 高(每次读写数据都要用) | 低(只在信封打开/关闭时用) |
| 密钥生成 |
可由客户端或 KMS 生成 | 必须在 KMS 或 HSM 内生成 |
| 泄露后果 | 对应数据全被解密 | 所有用该 KEK 保护的 DEK 都危险 |
4.4 流程中的具体分工
现在我们把它们放到实际的加解密流程里看看。我挑一个典型场景:上传文件到云存储。
加密流程:
- 从 KMS 请求生成一个 DEK(明文)。KMS 内部会生成随机 AES-256 密钥。
- 用这个明文 DEK 加密文件内容。得到密文文件。
- 再次调用 KMS,用 KEK 加密 DEK。得到加密后的 DEK(也叫 wrapped DEK)。
- 把密文文件和 wrapped DEK 一起上传到云存储。
- 立即从内存中清除明文 DEK。
解密流程:
- 从云存储拉取密文文件和 wrapped DEK。
- 将 wrapped DEK 发送给 KMS,请求用 KEK 解密。
- KMS 验证权限后,返回明文 DEK(只在网络连接中加密传输)。
- 用明文 DEK 解密文件内容。
- 解密完成后,立即清空明文 DEK。
4.5 密钥轮换策略
轮换是个大话题。我这里只针对 DEK 和 KEK 的不同轮换逻辑给点建议。
DEK 轮换:
- 每次加密新数据时,都生成新的 DEK。这是最安全的方式。
- 对于已存数据,可以按时间(比如 7 天)重新加密。
- 我的做法:在文件元数据里加一个 "keyVersion" 字段,方便追踪。
KEK 轮换:
- KEK 轮换成本高,因为所有 DEK 都需要重新加密保护。
- 建议在以下情况触发轮换:怀疑密钥泄露、合规审计到期、人员离职。
- 我用过的一个方案:创建新版本的 KEK,然后逐步把旧 DEK 切换到新 KEK 下。
4.6 核心知识体系
为了帮你一次性记住这张关系网,我画了一张 SVG 图。你看完就明白了。
从这张图里你能看到,DEK 和 KEK 分属不同的安全层级。DEK 在应用层直接干活,但它的安全由 KEK 在底层兜底。这个分层设计,说白了就是把核心秘密藏起来,让暴露在外面的密钥即使被偷,也只是一堆无用乱码。
4.7 避坑指南
最后我列几个常见的坑,都是我或者团队里的人亲身经历过:
我建议的存放方式: 在数据库里存 wrapped DEK 的时候,顺便存一个 KEK 版本号。这样以后轮换 KEK,你能知道哪些 DEK 是用旧 KEK 保护的,好做批量重加密。
- 别把明文 DEK 写日志:我曾经在 debug 阶段把 DEK 打印到日志里,上线前忘了删。好在只是测试环境。但养成习惯很重要。
- DEK 和 KEK 不能共用同一把:如果 DEK 和 KEK 是一样的,那信封加密就失去意义了。相当于你把家里钥匙放在门口的脚垫下面。
- KEK 的权限要最小化:不是谁都能调 KMS 的 Decrypt 接口。我在一个项目里看到运维同学给所有应用配了同一个 KEK 的完全访问权限…后来改成了按应用隔离。
- 定期检测密钥是否过期:很多云 KMS 支持密钥过期时间。我习惯在 KEK 过期前 30 天开始轮换,留足缓冲。