欢迎光临
我们一直在努力

Key Wrap 认识(一)— 专门为了密钥安全传输设计的标准

文章目录

  • 0.前言
  • 1\\. 什么是Key Wrap
    • 1.1 什么是 Key Wrap
    • 1.2 为什么需要 Key Wrap?
    • 1.3 Key Wrap 的工作原理
    • 1.4 对比RFC 3394与RFC 5649两个标准
  • 2\\. 通过实验理解Key Wrap
    • 2.1 查询openssl 支持key wrap算法列表
    • 2.2 准备测试数据
      • 2.2.1 准备一个 16 字节 AES 密钥(作为待包装的密钥)
      • 2.2.2 准备一个 32 字节 KEK(AES-256)
    • 2.3 Key Wrap(RFC 3394)
      • 2.3.1 Wrap
      • 2.3.2 Unwrap
    • 2.4 使用Key Wrap with Padding(RFC 5649)
      • 2.4.1 Key Wrap之case1(与RFC 3394对比)
        • 2.4.1.1 Wrap
        • 2.4.1.2 Unwrap
      • 2.4.2 Key Wrap之case2(加密非8bytes倍数数据)
        • 2.4.2.1 Wrap
        • 2.4.2.2 UnWrap

0.前言

最近在阅读HSM安全存储相关材料时,遇到key wrap/ Unwrap的概念。 这个概念之前的偶尔听过,但一直一来只是大概了解其为了包装密钥。 概念出处?设计目的是什么?与我们熟悉的加密的有什么不同或关联?有哪些特性呢? 这些问题一直萦绕在脑海中,挥之不去。希望通过层层分析,拨开心中迷雾。 如果你和我一样,接下来的旅程也许会有一些启发。如若如此,则倍感荣幸。

1. 什么是Key Wrap

1.1 什么是 Key Wrap

Key Wrap(密钥包装)是一种专门用于保护密码密钥的机制。它使用一个密钥加密密钥(KEK)对另一个密钥进行包装,生成可安全存储、传输或导入导出的 Wrapped Key。与普通数据加密不同,Key Wrap 不仅提供密钥的机密性,还提供完整性保护和安全恢复能力,因此被广泛应用于 HSM、PKCS#11、TEE、云 KMS 等密钥管理系统中。目前最常用的标准是 RFC 3394(AES-KW)和 RFC 5649(AES-KWP),并由 NIST SP 800-38F 统一纳入密钥包装推荐规范。

1.2 为什么需要 Key Wrap?

假设系统中已经有一个 AES-256 主密钥(KEK),现在需要把一个 AES-128 会话密钥导出到另一台设备。 如果直接传输

AES-128 Key
│
▼
网络传输

任何人截获数据,都可以获得这个密钥。 如果使用普通 AES-CBC 加密:

AES-128 Key
│
▼
AES-CBC 加密
│
▼
Ciphertext

虽然提供了保密性,但仍然存在一些问题:

  • 密钥是否被篡改?
  • 解密出来的数据是否仍然是合法密钥?
  • 是否能够安全地导入到 HSM 或 TEE 中? 因此需要一种专门针对密钥管理设计的算法,这就是 Key Wrap。

1.3 Key Wrap 的工作原理

Key Wrap 使用一个 KEK(Key Encryption Key) 去保护另一个密钥。

KEK(Wrap Key)
│
▼
Key Wrap Algorithm
│
▼
Target Key(待包装密钥)
│
▼
Wrapped Key Blob

接收方使用同一个 KEK 执行 Unwrap

Wrapped Key Blob
│
▼
Key Unwrap
│
▼
Original Key

整个过程中:

  • 原始密钥不会明文传输;
  • Wrapped Key 可以安全存储或传输;
  • 解包时会进行完整性校验。

1.4 对比RFC 3394与RFC 5649两个标准

在这里插入图片描述

对比项RFC 3394(AES-KW)RFC 5649(AES-KWP)说明
发布时间 2002 2009 RFC5649 是 RFC3394 的扩展版本
标准名称 AES Key Wrap Algorithm AES Key Wrap with Padding Algorithm KWP = Key Wrap with Padding
设计目标 包装(Wrap)密码密钥 包装(Wrap)密码密钥 相同
底层算法 AES AES 相同
KEK(Key Encryption Key) 使用 KEK 包装其他密钥 使用 KEK 包装其他密钥 相同
主要用途 密钥存储、导入导出、密钥传输 密钥存储、导入导出、密钥传输 相同
提供机密性(Confidentiality) ✔ ✔ 相同
提供完整性保护(Integrity) ✔ ✔ 相同
支持 Unwrap 恢复 ✔ ✔ 相同
AES 核心运算 相同的 AES Key Wrap 核心算法 复用 RFC3394 的核心算法 相同
数据长度要求 必须是 8 字节整数倍 支持任意长度 不同
Padding 不支持 支持自动 Padding 不同
初始值(IV/AIV) 默认 IV:A6A6A6A6A6A6A6A6 AIV:A65959A6 || MLI 不同
是否包含长度信息 否 是,包含 MLI(Message Length Indicator) 不同
是否适用于非 8 字节整数倍数据 ✘ ✔ 不同
输出结果是否与 RFC3394 相同 —— 否,即使输入数据长度是 16/32 字节也不同 不同
解包时完整性校验 校验默认 IV 是否恢复正确 校验 AIV(常量 + MLI)是否恢复正确 不同
OpenSSL Cipher id-aes128-wrapid-aes192-wrapid-aes256-wrap id-aes128-wrap-padid-aes192-wrap-padid-aes256-wrap-pad 不同
PKCS#11 Mechanism CKM_AES_KEY_WRAP CKM_AES_KEY_WRAP_PAD 不同
典型应用 AES-128、AES-192、AES-256、3DES 等固定长度密钥 任意长度密钥材料、ECC 密钥材料、密钥派生结果等 不同
  • 可以更加简化去理解
如果待包装对象推荐 Mechanism对应标准
AES-128(16B)、AES-256(32B)等固定长度密钥 AES_KEY_WRAP RFC 3394
长度可能不是 8 字节整数倍的密钥材料 AES_KEY_WRAP_PAD RFC 5649

2. 通过实验理解Key Wrap

2.1 查询openssl 支持key wrap算法列表

openssl list -cipher-algorithms | grep WRAP
{ 2.16.840.1.101.3.4.1.5, AES-128-WRAP, AES128-WRAP, id-aes128-wrap } @ default
{ 1.2.840.113549.1.9.16.3.6, DES3-WRAP, id-smime-alg-CMS3DESwrap } @ default
{ 2.16.840.1.101.3.4.1.45, AES-256-WRAP, AES256-WRAP, id-aes256-wrap } @ default
{ 2.16.840.1.101.3.4.1.8, AES-128-WRAP-PAD, AES128-WRAP-PAD, id-aes128-wrap-pad } @ default
{ 2.16.840.1.101.3.4.1.48, AES-256-WRAP-PAD, AES256-WRAP-PAD, id-aes256-wrap-pad } @ default
{ 2.16.840.1.101.3.4.1.25, AES-192-WRAP, AES192-WRAP, id-aes192-wrap } @ default
{ 2.16.840.1.101.3.4.1.28, AES-192-WRAP-PAD, AES192-WRAP-PAD, id-aes192-wrap-pad } @ default
{ AES-256-WRAP-INV, AES256-WRAP-INV } @ default
{ AES-192-WRAP-INV, AES192-WRAP-INV } @ default
{ AES-128-WRAP-INV, AES128-WRAP-INV } @ default
{ AES-256-WRAP-PAD-INV, AES256-WRAP-PAD-INV } @ default
{ AES-192-WRAP-PAD-INV, AES192-WRAP-PAD-INV } @ default
{ AES-128-WRAP-PAD-INV, AES128-WRAP-PAD-INV } @ default
****

  • 内容实际上可以分为 四类
    • 本文主要关注前两类,分别对应的标准是RFC 3394,RFC 5649
类别对应标准用途
AES-xxx-WRAP RFC 3394 AES Key Wrap,不支持任意长度
AES-xxx-WRAP-PAD RFC 5649 AES Key Wrap with Padding,支持任意长度
DES3-WRAP CMS(S/MIME) 3DES Key Wrap,用于CMS
xxx-INV OpenSSL内部算法 反向(Unwrap)实现,不建议用户直接使用

2.2 准备测试数据

2.2.1 准备一个 16 字节 AES 密钥(作为待包装的密钥)

  • 16byte密钥生成

printf '\\x00\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88\\x99\\xaa\\xbb\\xcc\\xdd\\xee\\xff' > key.bin

  • 查看key.bin内容

xxd key.bin
00000000: 0011 2233 4455 6677 8899 aabb ccdd eeff .."3DUfw……..

2.2.2 准备一个 32 字节 KEK(AES-256)

  • 32byte KEK准备

printf '\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f' > kek.bin

  • 查看kek.bin

xxd kek.bin
00000000: 0001 0203 0405 0607 0809 0a0b 0c0d 0e0f …………….
00000010: 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f …………….

2.3 Key Wrap(RFC 3394)

2.3.1 Wrap

  • 注意,需要输入iv

openssl enc \\
-id-aes256-wrap \\
-e \\
-K 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F \\
-iv A6A6A6A6A6A6A6A6 \\
-in key.bin \\
-out wrapped_01.bin

参数说明
-id-aes256-wrap AES-256 Key Wrap(RFC 3394)
-e Encrypt(Wrap)
-K KEK(十六进制)
-iv iv(十六进制)
-in 待包装密钥
-out Wrapped Key
  • 查看Wrap结果

xxd wrapped_01.bin
00000000: 64e8 c3f9 ce0f 5ba2 63e9 7779 0581 8a2a d…..[.c.wy…*
00000010: 93c8 191e 7d6e 8ae7

  • 与 RFC 3394 test例子对比 origin_url=%3A%2Fe81d81fde2954729a45494e3d54151cd&pos_id=img-0aWxo5u6-1784501027539) 在这里插入图片描述 在这里插入图片描述

2.3.2 Unwrap

  • Unwrap过程, 恢复密钥

openssl enc \\
-id-aes256-wrap \\
-d \\
-K 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F \\
-iv A6A6A6A6A6A6A6A6 \\
-in wrapped_01.bin \\
-out unwrap_01.bin

参数说明
-id-aes256-wrap AES-256 Key Wrap(RFC 3394)
-d Decrypt(Unwrap)
-K KEK(十六进制)
-iv iv(十六进制)
-in Wrapped Key
-out 恢复后密钥
  • 查看恢复密钥内容

xxd unwrap_01.bin
00000000: 0011 2233 4455 6677 8899 aabb ccdd eeff .."3DUfw……..

2.4 使用Key Wrap with Padding(RFC 5649)

2.4.1 Key Wrap之case1(与RFC 3394对比)

– 敲黑板:这个实验使用参数除了pad区别外,其他都一样,请观察结果 -** 参数相同的情况,结果依然不同,使用上不能混淆**

2.4.1.1 Wrap

注意: 加密的时候给了一个提示,hex string is too long, ignoring excess,这里指的IV太长了

openssl enc \\
-id-aes256-wrap-pad \\
-e \\
-K 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F \\
-iv A6A6A6A6A6A6A6A6 \\
-in key.bin \\
-out wrapped_02.bin
hex string is too long, ignoring excess

  • 查看查看Wrap结果
  • 发现,相同的参数输入,与RFC 3394计算的结果不同
    • 证明:RFC 3394 与 RFC 5649不是相互替代,有不能混用

xxd wrapped_02.bin
00000000: bdd6 3552 e627 e7bd 8ba7 dabd 855e 29ac ..5R.'…….^).
00000010: 1174 db41 4855 9917

2.4.1.2 Unwrap
  • 解密

openssl enc \\
-id-aes256-wrap-pad \\
-d \\
-K 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F \\
-iv A6A6A6A6A6A6A6A6 \\
-in wrapped_02.bin \\
-out unwrap_02.bin
hex string is too long, ignoring excess

  • 查看还原结果,一致

xxd unwrap_02.bin
00000000: 0011 2233 4455 6677 8899 aabb ccdd eeff .."3DUfw……..

2.4.2 Key Wrap之case2(加密非8bytes倍数数据)

2.4.2.1 Wrap
  • 准备被加密数据

echo "Hello PKCS11" > data.bin

  • 数据为13bytes,

xxd data.bin
00000000: 4865 6c6c 6f20 504b 4353 3131 0a Hello PKCS11.

  • 加密命令

openssl enc \\
-id-aes256-wrap-pad \\
-e \\
-K 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F \\
-in data.bin \\
-iv A65959A6 \\
-out wrapped.data.bin

  • 加密后数据

xxd wrapped.data.bin
00000000: 9491 edf3 84a2 db5f 345d 6bf8 1ab7 fbae ……._4]k…..
00000010: 3846 f77f e4f7 20a7

2.4.2.2 UnWrap
  • 恢复命令

openssl enc \\
-id-aes256-wrap-pad \\
-d \\
-K 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F \\
-iv A65959A6 \\
-in wrapped.data.bin \\
-out unwrap.data.bin

  • 查看恢复结果

xxd unwrap.data.bin
00000000: 4865 6c6c 6f20 504b 4353 3131 0a Hello PKCS11.

赞(0)
未经允许不得转载:171主机测评 » Key Wrap 认识(一)— 专门为了密钥安全传输设计的标准
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址