欢迎光临
我们一直在努力

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)

评论 抢沙发

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