AES-GCM-SIV:一个更好的AES-GCM版本?

本文介绍了AES-GCM-SIV,这是一种改进的AES-GCM版本,它通过从nonce值派生密钥来克服nonce重用问题,从而提供更高的安全性。文章对比了AES-GCM和AES-GCM-SIV的性能,并提供了Python代码示例,展示了如何在实际中使用AES-GCM-SIV进行加密和解密。

AES-GCM-SIV:AES-GCM 的更好版本?

我很高兴 AES-GCM 是目前最流行的对称密钥加密方法。通过这种方法,我们有了一种流加密方法,我们需要一个 GMAC 码(定义为 GHASH)来验证密码 —— 否则攻击者可以很容易地翻转密文中的位并修改恢复的明文。它还支持 AEAD(带有关联数据的认证加密),我们可以在加密和解密过程中添加额外的数据。

但是,单次重用初始化向量 (IV)(也称为 nonce 值)可能会导致密钥和明文泄露。由于我们有一个 96 位的 IV,因此可能会在合理的时间范围内创建相同的 IV 值。

AES-SIV(合成初始化向量)[ RFC 8452] 通过从 nonce 值派生密钥来克服这个问题:消息加密密钥 (MEK) 和消息认证密钥 (MAK)。在图 1 中,我们看到认证密钥是由 nonce 值以及 0 和 1 值的串联创建的,并使用主密钥对其进行加密:

图 1:认证密钥 [ ref]

加密密钥的过程类似,但我们在 nonce 值中添加 2 和 3:

图 2:加密密钥 [ ref]

对于加密过程,我们采用额外的数据和明文,并使用认证密钥应用 POLYVAL 方法。POLYAL 是一种多项式认证器,并使用具有不可约多项式 x¹²⁸ + x¹²⁷ + x¹²⁶ + x¹²¹ +1 的有限域。 然后将其与 nonce 值相加(异或),然后使用加密密钥对其进行加密以生成认证标签。 接下来,我们可以使用加密密钥和 AES-CTR 加密创建密码密钥流。 最后,将此密钥流与明文进行异或:

图 3:加密 [ ref]

总的来说,AES-GCM-SIV 具有出色的安全级别,因为我们从主密钥生成两个密钥(加密和认证)。 如果这些派生密钥中的任何一个泄露,都不会导致泄露任何其他密钥的优势。

主要优点之一是它能够抵抗 nonce 重用,这会影响 AES-GGM。 通过这种方式,攻击者可以从使用相同 nonce 值和加密密钥的两个密文中恢复明文。 发生这种情况时,攻击者可能会危及认证密钥,然后他们可以创建其他有效的明文、密文和认证标签。 对于 AES-GCM-SIV,攻击者只能确定明文值是否相同,但实际上无法泄露明文。 这是因为 AES-GCM-SIV 是一种确定性方法,对于相同的明文输入、加密密钥和 nonce 值,我们总是得到相同的输出。 AES-GCM-SIV 的另一个核心优势是它与 AES 方法兼容,并且通常可以使用硬件加速。 POLYEVAL 的多项式经过选择,因此它类似于 GHASH 方法(与 AES-GCM 一起使用)。

在你的收件箱中获取 Prof Bill Buchanan OBE FRSE 的故事

所以让我们运行以下命令:

% openssl speed -evp AES-256-GCM
Doing AES-256-GCM for 3s on 16 size blocks: 96160410 AES-256-GCM's in 2.99s
Doing AES-256-GCM for 3s on 64 size blocks: 71174553 AES-256-GCM's in 3.00s
Doing AES-256-GCM for 3s on 256 size blocks: 28719919 AES-256-GCM's in 3.00s
Doing AES-256-GCM for 3s on 1024 size blocks: 7961024 AES-256-GCM's in 2.99s
Doing AES-256-GCM for 3s on 8192 size blocks: 1025427 AES-256-GCM's in 3.00s
Doing AES-256-GCM for 3s on 16384 size blocks: 513050 AES-256-GCM's in 3.00s
version: 3.0.8
built on: Tue Feb  7 13:43:33 2023 UTC
options: bn(64,64)
compiler: clang -fPIC -arch x86_64 -O3 -Wall -DL_ENDIAN -DOPENSSL_PIC -D_REENTRANT -DOPENSSL_BUILDING_OPENSSL -DNDEBUG
CPUINFO: OPENSSL_ia32cap=0x298220f4f8b8f15:0x0
The 'numbers' are in 1000s of bytes per second processed.
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes  16384 bytes
AES-256-GCM      57802.51k   226193.75k   802563.83k  1945280.30k  3427209.63k  3644052.59k

结果是:

type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes  16384 bytes
AES-128-GCM      63684.98k   213907.69k   856181.96k  2158952.79k  3852730.37k  4080838.19k
AES-128-SIV       5636.19k    21683.91k    83252.05k   279043.37k   873848.10k  1044320.67k
AES-128-GCM-SIV  17335.13k    61187.87k   157961.23k   267790.79k   328884.22k   333862.23k
AES-256-GCM      57802.51k   226193.75k   802563.83k  1945280.30k  3427209.63k  3644052.59k
AES-256-SIV       5042.81k    19708.07k    73704.72k   236793.58k   686430.37k   773234.22k
AES-256-GCM-SIV  15171.86k    53498.09k   140854.53k   241812.66k   297645.40k   306605.84k

我们可以看到 GCM 模式比 SIV 模式快 10 倍以上,比 GCM-SIV 快 4 倍。

如果我们对 128 位方法进行更广泛的测试,我们会得到:

我们可以看到 AES-128-SIV 的吞吐量比 AES-128-GCM 慢得多,吞吐量大约快五倍。 话虽如此,可以设计加速 SIV 模式的硬件,使其在性能方面接近 GCM。

编码

总的来说,Python Hazmat 库支持 AEAD 的一系列 AES 模式。 这包括 SIV、CCM、GCM、ChaCha20 和 SOCB3。 这是此代码[here]:

import os
import sys
import base64

from cryptography.hazmat.primitives.ciphers.aead import AESSIV,AESOCB3,AESGCM,ChaCha20Poly1305,AESCCM

message = "Hello"
add = "Session 1234"
method=0
keysize=128
if (len(sys.argv)>1):
 message=str(sys.argv[1])
if (len(sys.argv)>2):
 add=str(sys.argv[2])
if (len(sys.argv)>3):
 method=int(sys.argv[3])
if (len(sys.argv)>4):
 keysize=int(sys.argv[4])

nonce = os.urandom(12)

try:
 if (method==0):
  key = AESSIV.generate_key(bit_length=2*keysize)
  cipher = AESSIV(key)
  print(f"==AES SIV key size={2*keysize} ==")
 elif (method==1):
  key = AESGCM.generate_key(bit_length=keysize)
  cipher = AESGCM(key)
  print("==AES CCM==")
 elif (method==2):
  key = AESOCB3.generate_key(bit_length=keysize)  # 128, 192, 256
  cipher = AESOCB3(key)
  print("==AES AESOCB3==")
 elif (method==3):
  key = ChaCha20Poly1305.generate_key()
  cipher = ChaCha20Poly1305(key)
  print("==AES ChaCha20Poly1305==")
 elif (method==4):
  key = AESCCM.generate_key(bit_length=keysize)
  cipher = AESCCM(key)
  print("==AES CCM==")

 if (method==0):
  aad = [add.encode(), nonce]
  ct = cipher.encrypt(message.encode(), aad)
  rtn=cipher.decrypt(ct, aad)
 else:
  ct = cipher.encrypt(nonce,message.encode(), add.encode())
  rtn=cipher.decrypt(nonce,ct, add.encode())

 print(f"Message:\t{message}")
 print(f"AAD:\t\t{add}")
 print(f"\nNonce:\t\t{nonce.hex()}")
 print(f"\nKey:\t\t{key.hex()}")
 print(f"Key:\t\t{base64.b64encode(key).decode()}")
 print(f"\nCipher:\t\t{ct.hex()}")
 print(f"Cipher:\t\t{base64.b64encode(ct).decode()}")

 print(f"\nDecrypt:\t{rtn.decode()}")
except Exception as e:
    print(e)

SIV 模式的示例运行[here]:

结论

因此,这是一个折衷方案。 AES-GCM 速度很快,但可能存在与 nonce 重用相关的问题。 AES-GCM-SIV 没有那么快,但更安全。 SIV 模式的用例非常有限,仅限于存在 nonce 重用风险的用例。 这可能与随机 nonce 生成中的弱点有关,或者与多次使用加密密钥有关。 这样做的风险在于,96 位 nonce 值可能会重复(由于生日攻击),并且其中 nonce 值的安全级别会降低到 48 位。

  • 原文链接: billatnapier.medium.com/...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
billatnapier
billatnapier
江湖只有他的大名,没有他的介绍。