本文介绍了AES-GCM-SIV,这是一种改进的AES-GCM版本,它通过从nonce值派生密钥来克服nonce重用问题,从而提供更高的安全性。文章对比了AES-GCM和AES-GCM-SIV的性能,并提供了Python代码示例,展示了如何在实际中使用AES-GCM-SIV进行加密和解密。
我很高兴 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 一起使用)。
所以让我们运行以下命令:
% 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 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!