敏感数据怎么防拖库?信封加密(DEK+KEK 二层密钥)架构设计与 Java 实战

一个密钥加密所有数据,够吗

最简单的加密:用一把主密钥 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,解不开任何东西。

为什么它比单密钥更稳

  1. 缩小爆炸半径:DEK 泄露只影响部分数据,KEK 始终在 HSM 内;
  2. 性能更好:高频的数据加解密用 DEK(软件/本地即可),只有偶尔的 DEK 加解密才碰 HSM;
  3. 轮换灵活:换 DEK 不用重新加密全量数据,换 KEK 不影响历史密文结构;
  4. 合规清晰:密钥分层对应"数据密钥 / 主密钥"的密评要求。

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 怎么拦。

相关推荐
青 春 记 忆3 小时前
零基础入门python30:Flask个人账本从空目录运行与阶段验收
python·flask·后端开发
l1258653 小时前
# LangGraph Memory机制深度解析:短期记忆与长期记忆的工程实践
前端·人工智能·python·langchain·bootstrap
丘山一郎4 小时前
Spring 中的IOC控制反转 和DI依赖注入
java·后端·spring
码视野4 小时前
基于 Spring Boot + Vue3 的【大学英语四六级 (CET-4/6) 作文智能评分与句式润色系统】设计与实现(含PRD/三端高保真源码/大屏)
java·前端·人工智能·spring boot·后端·vue3
MetaLite4 小时前
Spring-AOP自调用为什么失效-AopContext真能解决吗
java·后端·spring
大模型码小白4 小时前
AI 对话流性能调优:万级消息的虚拟滚动落地
java·大数据·前端·javascript·人工智能·算法·机器学习
m0_547486664 小时前
《JavaScript核心原理 》全套PPT课件2026
开发语言·javascript·ecmascript
许彰午4 小时前
14-字段级SM4加密与SM2签名
java·低代码·架构
MC皮蛋侠客5 小时前
Tauri 2.x 系列(五):调用系统 API——官方插件、Rust crate 与原生能力
开发语言·后端·rust
金銀銅鐵5 小时前
斐波那契数列的个位数出现的周期是多少?
python·数学