JWE 加密
JWS(JSON Web Signature) 能验证令牌的真实性,但无法隐藏内容——任何人拿到 JWT 都能 Base64 解码读取载荷。当广州飞翔科技(learnto.cn)需要在开放网络中传输用户的身份证号、手机号等敏感信息时,仅靠签名是不够的。运维工程师李眉提出:"我们需要让令牌对第三方 不透明(opaque) ,即使被截获也无法读取。"
这就是 JWE(JSON Web Encryption,JSON Web 加密) 的使命。
JWE 与 JWS 的区别
| 特性 | JWS | JWE |
|---|---|---|
| 核心目标 | 验证真实性(authenticity) | 保护隐私(confidentiality) |
| 数据可读性 | 明文(Base64 编码) | 密文(不可读) |
| 生产者密钥 | 私钥签名 | 公钥加密 |
| 消费者密钥 | 公钥验证 | 私钥解密 |
飞翔科技场景 :李眉负责运维飞翔科技的会员系统。用户提交实名认证信息时,系统需要把身份证号、银行卡号等敏感数据封装成令牌,通过公网传递给第三方风控服务。李眉选择 JWE 确保即使流量被嗅探,攻击者也无法读取内容。
JWE 的紧凑序列化结构
与 JWS 的三段式不同,JWE 紧凑序列化(JWE Compact Serialization)由 五个部分 组成,用点号(.)分隔:
base64(header) .
base64(encryptedKey) .
base64(initializationVector) .
base64(ciphertext) .
base64(authenticationTag)
示例(为便于阅读已换行):
eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.
UGhIOguC7IuEvf_NPVaXsGMoLOmwvc1GyqlIKOK1nN94nHPoltGRhWhw7Zx0-kFm1NJn8LE9XShH59_i8J0PH5ZZyNfGy2xGdULU7sHNF6Gp2vPLgNZ__deLKxGHZ7PcHALUzoOegEI-8E66jX2E4zyJKx-YxzZIItRzC5hlRirb6Y5Cl_p-ko3YvkkysZIFNPccxRU7qve1WYPxqbb2Yw8kZqa2rMWI5ng8OtvzlV7elprCbuPhcCdZ6XDP0_F8rkXds2vE4X-ncOIM8hAYHHi29NX0mcKiRaD0-D-ljQTP-cFPgwCp6X-nZZd9OHBv-B3oWh2TbqmScqXMR4gp_A.
AxY8DCtDaGlsbGljb3RoZQ.
KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.
9hH0vgRfYgPnAHOd8stkvw
五个部分的含义:
| 部分 | 名称 | 说明 |
|---|---|---|
| 1 | Protected Header(受保护头部) | 包含算法信息的 JSON 对象,Base64-URL 编码 |
| 2 | Encrypted Key(加密密钥) | 用于加密内容的对称密钥(CEK)被加密后的结果 |
| 3 | Initialization Vector(初始化向量,IV) | 某些加密算法需要的随机初始值 |
| 4 | Ciphertext(密文) | 实际被加密的载荷数据 |
| 5 | Authentication Tag(认证标签) | 用于验证密文是否被篡改的附加数据 |
为什么需要 Encrypted Key? 非对称加密(如 RSA)计算开销大,不适合直接加密长数据。JWE 的解决方案是:生成一个随机的 内容加密密钥(CEK, Content Encryption Key) 用对称算法加密载荷,再用非对称算法加密这个 CEK。这样既安全又高效。
密钥管理模式
JWE 规范定义了五种 密钥管理模式(Key Management Modes) ,决定如何确定和保护 CEK:
密钥包装(Key Wrapping)
使用对称加密算法(如 AES Key Wrap)包装 CEK。发送方和接收方预先共享一个对称密钥。
密钥加密(Key Encryption)
使用非对称加密算法(如 RSAES-OAEP)直接加密 CEK。只有持有私钥的接收方能解密出 CEK。
直接密钥协商(Direct Key Agreement)
使用密钥协商算法(如 ECDH-ES)让双方共同计算出一个 CEK,无需传输加密后的密钥。
带密钥包装的密钥协商(Key Agreement with Key Wrapping)
先通过密钥协商算法生成一个对称密钥,再用该密钥包装 CEK。结合了协商和包装的优势。
直接加密(Direct Encryption)
直接使用用户提供的对称密钥作为 CEK,无需任何密钥派生或加密步骤。此时 encryptedKey 部分为空。
内容加密算法
CEK 确定后,实际加密载荷使用的是 内容加密算法(Content Encryption Algorithms) :
- AES CBC + HMAC SHA :AES 密码块链接模式(Cipher Block Chaining, CBC)配合 HMAC 进行认证。必需实现的有
A128CBC-HS256和A256CBC-HS512。 - AES GCM :AES 伽罗瓦计数器模式(Galois Counter Mode),自带认证功能,无需额外 HMAC。推荐使用
A128GCM和A256GCM。
李眉的选择 :飞翔科技的支付网关对性能和安全性都有高要求,李眉最终选用 RSAES-OAEP 加密 CEK,配合 A256GCM 加密内容,既避免了填充预言攻击,又减少了计算步骤。
JWE 头部声明
JWE 头部携带了解密所需的所有元数据。除了与 JWS 共用的 jku、jwk、kid、x5u、x5c、x5t、typ、crit 等声明外,JWE 特有的核心声明包括:
| 声明 | 含义 |
|---|---|
alg | 加密 CEK 的算法(如 RSA-OAEP、ECDH-ES、A128KW) |
enc | 使用 CEK 加密内容的算法(如 A128CBC-HS256、A256GCM) |
zip | 加密前对明文应用的压缩算法,通常为 DEF(deflate) |
示例头部:
{
"alg": "RSA-OAEP",
"enc": "A256GCM",
"kid": "feixiang-jwe-key-2024",
"typ": "JWT"
}
嵌套 JWT:先签名,再加密
JWE 本身虽然带有认证标签,能防止密文被篡改,但它不提供与 JWS 相同的真实性保证。在公钥/私钥方案中:
- JWS:私钥签名 → 公钥验证(只有私钥持有者能签发)
- JWE:公钥加密 → 私钥解密(任何持有公钥的人都能加密)
因此,当既需要 真实性 又需要 保密性 时,规范推荐采用 嵌套 JWT(Nested JWT) :先对载荷进行 JWS 签名,再将整个签名后的 JWT 作为明文进行 JWE 加密。
飞翔科技场景 :乐途医院(内部医疗项目)需要把患者的电子病历从移动端上传到云端。架构师白歌要求:
- 先用 ES256 对病历数据进行签名,确保数据来自合法的乐途医院 App;
- 再用 RSA-OAEP + A256GCM 对签名后的 JWT 进行加密,确保病历内容在传输过程中不被泄露。
李眉在 Nginx 网关层统一处理加密,后端服务只需验证内层的 JWS,实现了安全与业务逻辑的解耦。
小结
JWE 填补了 JWT 在隐私保护方面的空白。记住以下要点:
- JWS 保证 真实性 ,JWE 保证 保密性 ,两者互补而非替代。
- JWE 紧凑序列化包含五个部分:
header.encryptedKey.iv.ciphertext.authenticationTag。 - 选择合适的 密钥管理模式 和 内容加密算法 ,在安全与性能之间取得平衡。
- 对敏感数据同时需要真实性和保密性时,使用 嵌套 JWT (先签名,再加密)。
李眉在运维手册中写道:"加密不是万能的,但没有加密的公网传输是万万不能的。"