
一个密钥加密所有数据,够吗
最简单的加密:用一把主密钥 KEK 直接加密所有业务数据。问题也很直接------这把密钥一旦泄露,全军覆没;而且每次加解密都要调用 HSM,高并发下性能扛不住。
更合理的做法,是像寄信一样:把信(数据)装进信封,用信封钥匙(DEK)锁上;信封钥匙本身再装进一个铁箱,用铁箱钥匙(KEK,由 HSM 保管)锁上。这就是信封加密(Envelope Encryption)。
二层密钥体系:DEK + KEK
业务数据 ──DEK加密──▶ 密文数据
DEK ──KEK加密──▶ 密文DEK(和数据一起存)
KEK ──HSM保管──▶ 永不明文导出
- DEK(数据密钥):只用来加密业务数据本身,可以每条数据一把,用完即弃或定期轮换;
- KEK(主密钥) :由 KSP / HSM 管理,只用来加密 DEK,自身永不明文导出硬件;
- 存储时,密文数据 + 密文 DEK 一起落库。
攻击者即使拖走整库,拿到的也只是"密文数据 + 被 KEK 锁住的密文 DEK"------没有 HSM 里的 KEK,解不开任何东西。
为什么它比单密钥更稳
- 缩小爆炸半径:DEK 泄露只影响部分数据,KEK 始终在 HSM 内;
- 性能更好:高频的数据加解密用 DEK(软件/本地即可),只有偶尔的 DEK 加解密才碰 HSM;
- 轮换灵活:换 DEK 不用重新加密全量数据,换 KEK 不影响历史密文结构;
- 合规清晰:密钥分层对应"数据密钥 / 主密钥"的密评要求。
Java 调用 KSP 实战
KSP 提供 Java SDK 与 RESTful API。下面用 RESTful 风格演示"加密一个字段"的闭环(伪代码,密钥名与端点以实际产品为准):
java
// 1. 向 KSP 申请一把数据密钥 DEK(明文仅在本次调用返回,建议立即用掉)
HttpClient client = HttpClient.newHttpClient();
String createDek = """
{ "action":"key/create", "type":"SYMMETRIC",
"alg":"SM4", "length":128, "exportable":true }
""";
HttpResponse<String> r1 = client.send(
post("https://ksp-host/api/v1/key", createDek),
BodyHandlers.ofString());
// r1 返回 { dataKey: "<base64 明文DEK>", keyId: "dek-xxxx" }
// 2. 用 DEK 加密业务字段(本地 SM4)
byte[] dek = Base64.getDecoder().decode(r1.dataKey);
byte[] cipher = Sm4Util.cbcEncrypt(dek, "13800001234".getBytes(StandardCharsets.UTF_8));
// 3. 把 DEK 交给 KSP 用 KEK 加密后归档,本地只留密文 DEK
String wrap = """
{ "action":"key/wrap", "keyId":"dek-xxxx" }
""";
HttpResponse<String> r2 = client.send(
post("https://ksp-host/api/v1/key/wrap", wrap),
BodyHandlers.ofString());
// r2 返回 { wrappedDek: "<被KEK加密的密文DEK>" }
// 4. 落库:密文数据 + 密文DEK + keyId
jdbc.update("INSERT INTO user(phone_cipher, dek_wrapped, dek_id) VALUES(?,?,?)",
Base64.getEncoder().encodeToString(cipher), r2.wrappedDek, "dek-xxxx");
解密时反向:用 keyId 向 KSP 申请 unwrap 拿回 DEK,再用 DEK 解 phone_cipher。整个过程业务明文密钥从不落库,KEK 从不离开 HSM。
字段级加密的典型场景
- 身份证号、手机号、银行卡号等 PII 字段;
- 电力营销系统敏感字段端到端加密(KSP + SM2 UKey,浏览器端加密,服务端不落地明文);
- 汽车研发 PLM 三维模型文件"谁上传、谁能解密"的细粒度授权。
小结
信封加密把"一把钥匙守所有数据"变成"每封信有自己的钥匙,所有钥匙锁进 HSM 铁箱"。它既扛得住拖库,又扛得住高并发,还是密评里"密钥分层管理"的标准答法。
下一篇换个威胁模型:不是拖库,而是勒索病毒把文件全加密了------KSP 的 RDM 怎么拦。