DEK与CMK基本概念及其在日志审计中的重要性

从一次事故说起

我记得几年前接手过一个复盘案例。某云上数据库被删,事后查日志发现,数据加密密钥(DEK)的生成记录根本查不到——不是没有,而是跟客户主密钥(CMK)的使用记录对不上。你想想看,密钥权限链断了,审计线索直接卡死。那次之后,我养成了一个习惯:凡涉及加密操作的日志,一定同时抓DEK和CMK两条线。

什么是DEK和CMK?

说白了,CMK是你的“根密钥”,负责保护其他密钥。DEK是实际用来加密数据的密钥。我经常打一个比方:CMK是保险柜的总钥匙,DEK是里面每个小抽屉的钥匙。你拿着总钥匙才能开保险柜,但真正开小抽屉的是DEK。

  • CMK(客户主密钥):由KMS(密钥管理服务)创建,用户拥有管理权限。它从不离开KMS硬件安全模块(HSM)。
  • DEK(数据加密密钥):由KMS用CMK加密后返回给客户端(信封加密),客户端用DEK本地加密数据。

这里有个关键点:CMK的日志记录的是“谁授权生成DEK”,而DEK的日志记录的是“谁用这个DEK加密了什么”。二者缺一不可。

对比维度 CMK DEK
核心用途 保护DEK及其他密钥 直接加密数据
生命周期 通常长期存在,由用户管理 随数据操作创建,用后可选销毁
存储位置 KMS的HSM内 客户端内存/存储中(密文存储)
日志关键字段 GenerateDataKey、Encrypt、Decrypt 数据对象的完整性校验、加密上下文
我的个人习惯:在审计方案设计阶段,我会同时订阅CMK的KeyUsage事件和DEK的DataKeyCreated事件。前者查授权,后者查执行,两套日志时间戳必须落在同一窗口。

DEK与CMK的关系——信封加密

你知道为什么叫“信封加密”吗?

  1. 客户端请求KMS:"给我一个DEK"。KMS用CMK加密DEK,返回密文DEK + 明文DEK。
  2. 客户端用明文DEK加密数据,然后丢弃明文DEK,只保留密文DEK。
  3. 后续解密时,客户端把密文DEK发给KMS,KMS用CMK解密出明文DEK,再加密数据。

整个过程中,CMK的每一次调用都会被记录。我见过不少团队只查了KMS的Decrypt事件,却忽略了GenerateDataKey的日志——你想想看,如果连DEK是怎么生成的都没记录,后续的加密动作根本无法追溯。

我曾经踩过的一个坑:某次客户说“我们所有数据都加密了”,但安全扫描发现了一批未加密的备份文件。审计日志显示,生成这批备份的脚本没有调用KMS,而是直接使用了硬编码的DEK。所以,只依赖DEK的日志不够,必须关联CMK的授权日志来判断“这把DEK是否经过正规途径生成”。

日志审计为什么需要关注DEK和CMK?

一句话:加密操作的完整证据链。你想想看,如果只查CMK的Encrypt事件,你只能看到“某个用户在某个时间点调用了KMS”,但不知道这个操作到底加密了哪块数据。反过来,只查DEK的日志,你只能看到“某DEK被用来加密了某个对象”,却不知道这个DEK是谁授权产生的。

只有把两者关联起来,你才能回答三个关键问题:

  • 谁(IAM角色/用户)授权了这把DEK?
  • 什么时候(时间戳)生成和使用的?
  • 用在什么数据上(加密上下文/对象标识)?

我在一次合规审计中,正是靠这种关联方法,发现了一个隐蔽的权限滥用事件:某开发人员用自己的CMK生成了DEK,然后把这把DEK传给了生产环境的服务。因为DEK的日志里没有CMK的所有者信息,单看生产环境日志全是正常操作。但把CMK的GenerateDataKey日志拉出来一对比,就发现生产环境的DEK根本不应该由那个人的CMK产生。

知识图谱:DEK与CMK的审计关联模型

DEK与CMK的日志关联审计模型 用户/服务 CMK (主密钥) KMS (HSM) DEK (数据密钥) 加密数据对象 KMS API调用 GenerateDataKey 本地加密 日志关键字段:CMK事件(GenerateDataKey / Encrypt / Decrypt)+ DEK上下文(加密对象ID / 时间戳)

常见的坑与避坑指南

坑1:只保留DEK日志,忽略CMK的授权记录。

我曾经见过一个团队,把所有加密操作的日志都丢到同一个索引里,但只记录了DEK的ID和加密上下文。等到审计时才发现,他们根本没有办法知道这些DEK是哪个CMK产生的——因为CMK的GenerateDataKey事件已经被默认日志保留策略清理掉了。

解决办法:在日志收集阶段,将CMK的KeyUsage事件(通常保留90天以上)独立归档,并与DEK的使用日志通过请求ID或加密上下文做关联。

坑2:误以为DEK日志中的“加密上下文”就是数据标识。

实际上,很多服务只是把encryption_context当作元数据透传,并不是真正的数据对象ID。我遇到过某个对象存储服务,DEK日志里写的上下文全是“default”,根本没法定位到具体存储桶。

解决办法:要求开发团队在调用KMS时,把数据对象的唯一标识(如文件路径、数据库表名)写入encryption_context,并确保日志能拿到这个字段。

我自己的检查清单:每次审计前,我会先跑两条查询:1) 列出所有CMK的GenerateDataKey调用时间段;2) 检查这些时间段内的DEK日志中,是否至少有90%的加密操作能匹配到对应的CMK调用。如果匹配度低于80%,说明日志关联链路有问题,需要立即修复。

本章小结

DEK和CMK不是两个独立的实体,它们是一对加密链上的父子关系。日志审计想要看清这条链,就必须把CMK的授权操作和DEK的数据操作当作一个整体来追踪。说白了,你只有拿到完整的“谁→什么时候→用了什么密钥→加密了什么数据”这条线,才能在安全事件发生时拿出不含糊的证据。