cryptography 项目 AES-192-GCM-SIV 测试向量生成与验证全流程
密码学【免费下载链接】cryptographycryptography is a package designed to expose cryptographic primitives and recipes to Python developers.项目地址https://gitcode.com/gh_mirrors/cr/cryptography点击查看免费下载本文以 cryptography 仓库中 AES-GCM-SIV vector creation 文档为骨架完整剖析该项目如何为 OpenSSL 测试向量缺失的 192 位密钥长度补齐 AES-GCM-SIV 测试数据包括基于 Python 的向量生成脚本、基于 Rust 的独立验证程序、以及生成的向量文件最终如何被仓库测试套件消费。读完本文你将掌握一条OpenSSL 生成基准 → Python 改写密钥长度 → Rust 独立交叉验证 → 纳入单元测试的完整自定义测试向量生产流水线并理解 AES-GCM-SIV 在 cryptography 中的实际实现与限制。背景为什么要为 AES-GCM-SIV 专门生成 192 位密钥向量AES-GCM-SIV 是一种带非ce重放保护的非ce复用安全认证加密算法RFC 8452允许在 nonce 意外重复时仍然不泄露明文。在 cryptography 中它通过 src/cryptography/hazmat/primitives/ciphers/aead.py 暴露为AESGCMSIV类别名到 Rust 绑定rust_openssl.aead.AESGCMSIV属于hazmat高风险原语层。AES-GCM-SIV 支持 128、192、256 三种密钥长度但 OpenSSL 官方提供的测试向量只有 128 位和 256 位两种密钥192 位密钥的测试数据在官方向量集中是缺失的。仓库文档 aes-192-gcm-siv.rst 明确记录了解决这一缺口的方式本文档记录了用于生成 OpenSSL 测试向量中缺失密钥长度的 AES-GCM-SIV 测试向量的代码。所有向量均使用 OpenSSL 生成并使用 Rust 验证。即以 OpenSSL 自带的 128/256 位向量为基准通过改写密钥长度得到 192 位向量再用独立的 Rust 实现交叉验证从而获得可信的 192 位测试数据。从底层实现看src/rust/src/backend/aead.rs 中AesGcmSiv结构体按密钥长度选择不同的 cipher 名称let cipher_name match key_buf.as_bytes().len() { 16 aes-128-gcm-siv, 24 aes-192-gcm-siv, 32 aes-256-gcm-siv, ... };这从源码层面印证了 192 位24 字节密钥是AESGCMSIV合法且被专门映射的分支因此为其补齐测试向量是有实际意义的。向量生成的目录结构与关键文件与本文档配套的完整代码位于 docs/development/custom-vectors/aes-192-gcm-siv/目录结构如下docs/development/custom-vectors/aes-192-gcm-siv/ ├── generate_aes192gcmsiv.py # Python 向量生成脚本 └── verify-aes192gcmsiv/ ├── Cargo.toml # Rust 验证程序依赖声明 └── src/ └── main.rs # Rust 验证程序此外最终产物向量文件存放于 vectors/cryptography_vectors/ciphers/AES/GCM-SIV/aes-192-gcm-siv.txt与 OpenSSL 官方向量 openssl.txt 并列存放。生成阶段Python 脚本如何改写密钥长度并加密核心思路生成脚本 generate_aes192gcmsiv.py 不直接从头构造测试数据而是读取 OpenSSL 官方向量文件openssl.txt含 128 位与 256 位两组数据把每组向量的密钥改写为 192 位16 字节密钥补零到 24 字节32 字节密钥截断到 24 字节用 cryptography 自带的AESGCMSIV对同样的 IV、明文、AAD 重新加密输出新的密文与标签生成aes-192-gcm-siv.txt。由于 IV、明文、AAD 保持不变只有密钥长度改变因此生成的向量与 OpenSSL 官方向量在结构上完全同构便于对照与审计。密钥改写函数脚本中的convert_key_to_192_bits函数处理密钥长度转换def convert_key_to_192_bits(key: str) - str: new_key binascii.unhexlify(key) if len(new_key) 16: new_key b\x00 * 8 # 128 位密钥追加 8 字节零 elif len(new_key) 32: new_key new_key[0:24] # 256 位密钥截断到前 24 字节 else: raise RuntimeError( Unexpected key length. OpenSSL AES-GCM-SIV test vectors only contain 128-bit and 256-bit keys ) return binascii.hexlify(new_key).decode(ascii)规则总结输入密钥长度转换方式结果16 字节128 位末尾追加b\x00 * 824 字节192 位32 字节256 位截取前 24 字节24 字节192 位其他长度抛出RuntimeError—脚本对异常长度直接抛错而不是静默处理保证了只有 OpenSSL 向量集中合法的 128/256 位密钥才会进入转换流程。加密与输出格式encrypt函数使用AESGCMSIV完成认证加密并将结果拆分为密文与 16 字节标签def encrypt(key: str, iv: str, plaintext: str, aad: str) - (str, str): aesgcmsiv AESGCMSIV(binascii.unhexlify(key)) encrypted_output aesgcmsiv.encrypt( binascii.unhexlify(iv), binascii.unhexlify(plaintext), binascii.unhexlify(aad) if aad else None, ) ciphertext, tag encrypted_output[:-16], encrypted_output[-16:] ...注意两点实现细节AESGCMSIV.encrypt的返回值是密文与标签拼接的字节串ciphertext || tag因此用[:-16]和[-16:]切分——这与验证端 Rust 程序split_at(plaintext_bytes.len())的切分逻辑保持一致aad为空时传入None对应 AES-GCM-SIV 无附加认证数据的情形。build_vectors函数逐行解析 OpenSSL 向量文件中的Key、IV、AAD、Plaintext字段每遇到一个新Key即触发对上一组数据的加密最终输出与 NIST 向量风格一致的文本COUNT 0 Key 010000000000000000000000000000000000000000000000 IV 030000000000000000000000 Plaintext 0100000000000000 Tag 6b0606875a845eec145f44ae5b92e834 Ciphertext 0e49fb119666c8ae脚本末尾将输出写入 vectors/cryptography_vectors/ciphers/AES/GCM-SIV/aes-192-gcm-siv.txt共 399 行、多组 COUNT 数据并固定读取vectors/cryptography_vectors/ciphers/AES/GCM-SIV/openssl.txt作为基准输入。这份文件同时保留了 128 位向量的注释头#Cipher aes-128-gcm-siv说明生成脚本会遍历其中的 128 位与 256 位两组向量。验证阶段Rust 程序独立交叉验证为什么需要 Rust 验证生成脚本使用的是 cryptography 自身的AESGCMSIV实现底层为 Rust OpenSSL为避免用同一套实现自证带来的系统性偏差文档采用独立的 Rust 第三方 crate 实现进行交叉验证如果两个独立实现计算出的密文和标签完全一致则向量可信度大幅提升。验证程序位于 verify-aes192gcmsiv/src/main.rs其依赖在 verify-aes192gcmsiv/Cargo.toml 中声明[dependencies] aes-gcm-siv 0.11.1 aes 0.8.1 hex 0.4.3其中aes-gcm-siv是 Rust 生态中独立的 AES-GCM-SIV 实现aes提供Aes192分组密码实例hex负责十六进制编解码——三个 crate 与 cryptography 自身的 OpenSSL 后端完全无关保证了交叉验证的独立性。验证逻辑程序定义VectorArgs结构体存放单组向量的全部字段nonce、key、aad、tag、plaintext、ciphertextvalidate函数完成单组验证pub type Aes192GcmSiv AesGcmSivAes192; fn validate(v: VectorArgs) { let key_array: [u8; 24] key_bytes.try_into().unwrap(); let cipher Aes192GcmSiv::new(GenericArray::from(key_array)); let payload Payload { msg: plaintext_bytes.as_slice(), aad: aad_bytes.as_slice(), }; let encrypted_bytes cipher .encrypt(Nonce::from_slice(nonce_bytes.as_slice()), payload) .unwrap(); let (ciphertext_bytes, tag_bytes) encrypted_bytes.split_at(plaintext_bytes.len()); assert_eq!(ciphertext_bytes, expected_ciphertext_bytes); assert_eq!(tag_bytes, expected_tag_bytes); }关键点key_array.try_into()强制 24 字节密钥与 192 位密钥长度严格对应与 Python 生成端相同用split_at(plaintext_bytes.len())将加密输出拆为密文与标签通过assert_eq!同时比对密文与标签任一不匹配即验证失败。validate_vectors函数逐行读取向量文件以COUNT字段为分组边界累积字段、并在下一组开始前验证上一组最后再验证残留的最后一组。main函数指定读取路径fn main() { validate_vectors(Path::new( vectors/cryptography_vectors/ciphers/AES/GCM-SIV/aes-192-gcm-siv.txt, )); println!(AES-192-GCM-SIV OK.) }程序运行成功会打印AES-192-GCM-SIV OK.运行失败则因assert_eq!失败而 panic 退出。将验证程序与生成脚本对照可以发现两者对密文 ‖ 标签拼接格式的理解完全一致这正是两个独立实现能够对齐验证的前提。向量文件的消费测试套件如何使用 192 位数据生成的向量文件不是孤立产物而是被仓库测试套件直接引用。在 tests/hazmat/primitives/test_aead.py 中TestAESGCMSIV类的test_vectors与test_vectors_invalid两个测试都同时加载openssl.txt与aes-192-gcm-siv.txtvectors _load_all_params( os.path.join(ciphers, AES, GCM-SIV), [ openssl.txt, aes-192-gcm-siv.txt, ], load_nist_vectors, )测试逐组取密钥、nonce、明文与 AAD调用AESGCMSIV(key).encrypt(nonce, pt, aad)后断言computed_ct[:-16] ct且computed_ct[-16:] tag——与生成脚本、Rust 验证程序采用完全相同的密文在前、标签在后的约定。同时测试代码中还体现了 192 位向量在部分后端上的限制# AWS-LC and BoringSSL only support AES-GCM-SIV with # 128- and 256-bit keys if len(key) 24 and (rust_openssl.CRYPTOGRAPHY_IS_BORINGSSL ...): continue这一行为与 src/rust/src/backend/aead.rs 中的实现完全对应在 BoringSSL/AWS-LC 后端下AesGcmSiv::new只接受 16 或 32 字节密钥24 字节密钥会抛出UnsupportedAlgorithmOnly 128-bit and 256-bit keys are supported for AES-GCM-SIV with AWS-LC or BoringSSL。也就是说192 位向量仅在 OpenSSL 3.2 后端上被实际执行验证测试代码通过continue精确跳过了不支持该密钥长度的后端保证了测试在多种编译配置下均可通过。全流程复盘与扩展阅读把整条流水线串起来看基准OpenSSL 官方 openssl.txt 提供 128/256 位密钥的权威向量改写generate_aes192gcmsiv.py 将密钥补零或截断为 192 位用 cryptography 的AESGCMSIV重新加密产出 aes-192-gcm-siv.txt交叉验证verify-aes192gcmsiv/src/main.rs 用独立的 Rustaes-gcm-sivcrate 逐组比对密文与标签纳入回归tests/hazmat/primitives/test_aead.py 将新向量与官方向量一并加载按后端能力有选择地执行断言。如果你希望进一步深入可以继续阅读AES-GCM-SIV 的公开 API 与密钥生成AESGCMSIV.__init__、generate_key(bit_length)的签名定义Rust 后端实现AesGcmSiv如何按密钥长度选择 cipher、如何在 BoringSSL/AWS-LC 与 OpenSSL 3.2 后端间分派AES-GCM-SIV 完整测试除向量测试外还包括非ce 长度校验、空明文、decrypt_into等边界行为测试自定义向量开发指南 与 测试向量说明了解本项目为其他算法生成与验证自定义测试向量的通用规范。这套官方向量补全 双实现交叉验证的方法论是 cryptography 保证非主流密钥长度算法正确性的标准做法也可作为你在其他密码学项目中补充测试数据的参考模板。赞分享密码学【免费下载链接】cryptographycryptography is a package designed to expose cryptographic primitives and recipes to Python developers.项目地址https://gitcode.com/gh_mirrors/cr/cryptography点击查看免费下载相关推荐如何验证tiny-AES-c的正确性NIST测试向量验证流程如何验证tiny AES c的正确性NIST测试向量验证流程 tiny AES c 是一个轻量级的AES加密库实现专为资源受限环境设计。作为最流行的开源AE密码学Model Context Protocol TypeScript SDK 服务端 Resources 完整实战指南从静态资源到模板订阅Model Context Protocol TypeScript SDK 服务端 Resources 完整实战指南从静态资源到模板订阅 导读 Resourc密码学RIOT 中的 AES-CCM 加解密测试与实现解析基于 CAVP DVTP 测试向量的 128/192/256 位密钥验证RIOT 中的 AES CCM 加解密测试与实现解析基于 CAVP DVTP 测试向量的 128/192/256 位密钥验证 本篇技术指南围绕 RIOT 操作物联网嵌入式操作系统实时系统上一篇Home Assistant: homematicip_cloud.dump_hap_config 动作详解——导出与匿名化 Homematic IP 接入点配置下一篇ComfyUI-LTXVideo模型训练指南定制专属视频生成模型创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考