跳到主要内容

2.8 AEAD Construction (AEAD 构造)

2.8 AEAD Construction (AEAD 构造)

AEAD_CHACHA20_POLY1305 是一种带关联数据的认证加密 (Authenticated Encryption with Associated Data, AEAD) 算法. AEAD_CHACHA20_POLY1305 的输入为:

  • 一个 256 位密钥

  • 一个 96 位 nonce, 在同一密钥的每次调用中必须不同

  • 任意长度的明文 (plaintext)

  • 任意长度的附加认证数据 (Additional Authenticated Data, AAD)

某些协议可能具有并非 96 位长度的、每次调用唯一的输入. 例如, IPsec 可能规定 64 位 nonce. 在此情况下, 应由协议文档定义如何将协议 nonce 变换为 96 位 nonce, 例如通过拼接常量值.

ChaCha20 与 Poly1305 原语按如下方式组合为采用 256 位密钥和 96 位 nonce 的 AEAD:

  • 首先, 按照第 2.6 节所述过程, 由 256 位密钥和 nonce 生成 Poly1305 一次性密钥.

  • 其次, 调用 ChaCha20 加密函数对明文加密, 使用相同的密钥和 nonce, 并将初始计数器设为 1.

  • 最后, 使用上文算出的 Poly1305 密钥调用 Poly1305 函数, 并对其消息实参使用以下内容的拼接:

    • AAD

    • padding1, 填充最多 15 个零字节, 使截至目前总长度为 16 的整数倍. 若 AAD 长度本身已是 16 字节的整数倍, 则该字段长度为零.

    • 密文 (ciphertext)

    • padding2, 填充最多 15 个零字节, 使截至目前总长度为 16 的整数倍. 若密文长度本身已是 16 字节的整数倍, 则该字段长度为零.

    • 附加数据的字节长度 (以 64 位小端整数表示).

    • 密文的字节长度 (以 64 位小端整数表示).

AEAD 的输出为以下内容的拼接:

  • 与明文等长的密文.

  • 128 位标签 (tag), 即 Poly1305 函数的输出.

解密过程类似, 但有如下差异:

  • 密文与明文的角色互换, 因而对密文应用 ChaCha20 加密函数以产生明文.

  • Poly1305 函数仍对 AAD 与密文运行, 不对明文运行.

  • 将计算得到的标签与接收到的标签进行按位比较. 当且仅当两个标签相等时, 消息通过认证.

关于本设计的若干说明:

  1. 单次调用中可加密的数据量最多为 2^32-1 个 64 字节块, 原因是 ChaCha20 块函数中块计数器字段的大小. 这相当于总共 274,877,906,880 字节, 接近 256 GB. 对 IPsec 和 TLS 等流量协议通常足够, 但对文件和/或磁盘加密可能过小. 对此类用途, 可以回到最初设计, 将 nonce 缩减为 64 位, 并把位置 13 处的整数用作 64 位块计数器的高 32 位, 从而将总消息量提高到超过一百万 PB (精确值为 1,180,591,620,717,411,303,360 字节).

  2. 尽管有上一条, 在 Poly1305 所运行缓冲区的构造中, 密文长度字段将密文 (因而也包括明文) 的大小限制为 2^64 字节, 即一万六千 PB (精确值为 18,446,744,073,709,551,616 字节).

本节中的 AEAD 构造是 ChaCha20 与 Poly1305 的一种新颖组合. 对该组合的安全性分析见 [Procter].

以下列出本构造在 [RFC5116] 第 4 节中所定义的各项参数:

  • K_LEN (密钥长度) 为 32 字节.

  • P_MAX (明文最大长度) 为 274,877,906,880 字节, 接近 256 GB.

  • A_MAX (关联数据最大长度) 由关联数据的长度字段设为 2^64-1 字节.

  • N_MIN = N_MAX = 12 字节.

  • C_MAX = P_MAX + 标签长度 = 274,877,906,896 字节.

(如 [RFC5116] 第 3.3 节所述) 不同的 AAD 输入必须拼接为送入 AEAD_CHACHA20_POLY1305 的单一输入. 若需要在 AAD 输入中承载结构, 由应用自行构造.

2.8.1 Pseudocode for the AEAD Construction (AEAD 构造的伪代码)

pad16(x):
if (len(x) % 16)==0
then return NULL
else return copies(0, 16-(len(x)%16))
end

chacha20_aead_encrypt(aad, key, iv, constant, plaintext):
nonce = constant | iv
otk = poly1305_key_gen(key, nonce)
ciphertext = chacha20_encrypt(key, 1, nonce, plaintext)
mac_data = aad | pad16(aad)
mac_data |= ciphertext | pad16(ciphertext)
mac_data |= num_to_8_le_bytes(aad.length)
mac_data |= num_to_8_le_bytes(ciphertext.length)
tag = poly1305_mac(mac_data, otk)
return (ciphertext, tag)

2.8.2 Example and Test Vector for AEAD_CHACHA20_POLY1305 (AEAD_CHACHA20_POLY1305 的示例与测试向量)

作为测试向量, 我们对 AEAD_CHACHA20_POLY1305 函数使用如下输入:

明文 (Plaintext):

000  4c 61 64 69 65 73 20 61 6e 64 20 47 65 6e 74 6c  Ladies and Gentl
016 65 6d 65 6e 20 6f 66 20 74 68 65 20 63 6c 61 73 emen of the clas
032 73 20 6f 66 20 27 39 39 3a 20 49 66 20 49 20 63 s of '99: If I c
048 6f 75 6c 64 20 6f 66 66 65 72 20 79 6f 75 20 6f ould offer you o
064 6e 6c 79 20 6f 6e 65 20 74 69 70 20 66 6f 72 20 nly one tip for
080 74 68 65 20 66 75 74 75 72 65 2c 20 73 75 6e 73 the future, suns
096 63 72 65 65 6e 20 77 6f 75 6c 64 20 62 65 20 69 creen would be i
112 74 2e t.

AAD:

000  50 51 52 53 c0 c1 c2 c3 c4 c5 c6 c7              PQRS........

密钥 (Key):

000  80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f  ................
016 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f ................

IV:

000  40 41 42 43 44 45 46 47                          @ABCDEFG

32 位固定公共部分 (32-bit fixed-common part):

000  07 00 00 00                                      ....

用于生成 Poly1305 一次性密钥的设置 (发送方 id=7):

    61707865  3320646e  79622d32  6b206574
83828180 87868584 8b8a8988 8f8e8d8c
93929190 97969594 9b9a9998 9f9e9d9c
00000000 00000007 43424140 47464544

生成 Poly1305 一次性密钥之后:

    252bac7b  af47b42d  557ab609  8455e9a4
73d6e10a ebd97510 7875932a ff53d53e
decc7ea2 b44ddbad e49c17d1 d8430bc9
8c94b7bc 8b7d4b4b 3927f67d 1669a432

Poly1305 密钥 (Poly1305 Key):

000  7b ac 2b 25 2d b4 47 af 09 b6 7a 55 a4 e9 55 84  {.+%-.G...zU..U.
016 0a e1 d6 73 10 75 d9 eb 2a 93 75 78 3e d5 53 ff ...s.u..*.ux>.S.

Poly1305 r = 455e9a4057ab6080f47b42c052bac7b

Poly1305 s = ff53d53e7875932aebd9751073d6e10a

密钥流字节 (keystream bytes):

9f:7b:e9:5d:01:fd:40:ba:15:e2:8f:fb:36:81:0a:ae:
c1:c0:88:3f:09:01:6e:de:dd:8a:d0:87:55:82:03:a5:
4e:9e:cb:38:ac:8e:5e:2b:b8:da:b2:0f:fa:db:52:e8:
75:04:b2:6e:be:69:6d:4f:60:a4:85:cf:11:b8:1b:59:
fc:b1:c4:5f:42:19:ee:ac:ec:6a:de:c3:4e:66:69:78:
8e:db:41:c4:9c:a3:01:e1:27:e0:ac:ab:3b:44:b9:cf:
5c:86:bb:95:e0:6b:0d:f2:90:1a:b6:45:e4:ab:e6:22:
15:38

密文 (Ciphertext):

000  d3 1a 8d 34 64 8e 60 db 7b 86 af bc 53 ef 7e c2  ...4d.`.{...S.~.
016 a4 ad ed 51 29 6e 08 fe a9 e2 b5 a7 36 ee 62 d6 ...Q)n......6.b.
032 3d be a4 5e 8c a9 67 12 82 fa fb 69 da 92 72 8b =..^..g....i..r.
048 1a 71 de 0a 9e 06 0b 29 05 d6 a5 b6 7e cd 3b 36 .q.....)....~.;6
064 92 dd bd 7f 2d 77 8b 8c 98 03 ae e3 28 09 1b 58 ....-w......(..X
080 fa b3 24 e4 fa d6 75 94 55 85 80 8b 48 31 d7 bc ..$...u.U...H1..
096 3f f4 de f0 8e 4b 7a 9d e5 76 d2 65 86 ce c6 4b ?....Kz..v.e...K
112 61 16 a.

用于 Poly1305 的 AEAD 构造 (AEAD Construction for Poly1305):

000  50 51 52 53 c0 c1 c2 c3 c4 c5 c6 c7 00 00 00 00  PQRS............
016 d3 1a 8d 34 64 8e 60 db 7b 86 af bc 53 ef 7e c2 ...4d.`.{...S.~.
032 a4 ad ed 51 29 6e 08 fe a9 e2 b5 a7 36 ee 62 d6 ...Q)n......6.b.
048 3d be a4 5e 8c a9 67 12 82 fa fb 69 da 92 72 8b =..^..g....i..r.
064 1a 71 de 0a 9e 06 0b 29 05 d6 a5 b6 7e cd 3b 36 .q.....)....~.;6
080 92 dd bd 7f 2d 77 8b 8c 98 03 ae e3 28 09 1b 58 ....-w......(..X
096 fa b3 24 e4 fa d6 75 94 55 85 80 8b 48 31 d7 bc ..$...u.U...H1..
112 3f f4 de f0 8e 4b 7a 9d e5 76 d2 65 86 ce c6 4b ?....Kz..v.e...K
128 61 16 00 00 00 00 00 00 00 00 00 00 00 00 00 00 a...............
144 0c 00 00 00 00 00 00 00 72 00 00 00 00 00 00 00 ........r.......

注意第 000 行中的四个零字节以及第 128 行中的 14 个零字节.

标签 (Tag):

1a:e1:0b:59:4f:09:e2:6a:7e:90:2e:cb:d0:60:06:91