Python cryptography AES-256-GCM与Rails OpenSSL AES-256-GCM交互适配
实现Python cryptography AES-GCM与Rails OpenSSL AES-256-GCM的加密一致性验证
我帮你补全并梳理了验证代码,同时整理了和Rails端对齐的关键要点,确保两边加密输出完全一致:
核心兼容要点
在对齐两个平台的AES-256-GCM实现时,这几个细节必须严格统一:
- 密钥长度:AES-256要求32字节密钥,你提供的密钥刚好符合要求
- Nonce(IV):GCM推荐使用12字节的nonce,验证阶段用固定值确保两边一致,生产环境必须随机生成
- 结果拼接顺序:Rails通常会把
nonce + 密文 + 认证标签组合成最终输出,Python端要完全遵循这个逻辑 - 附加数据(AAD):如果Rails端使用了认证附加数据,Python端必须传入完全相同的内容,否则标签验证会失败
完整Python验证代码
import os from cryptography.hazmat.primitives.ciphers.aead import AESGCM # 测试用固定参数(验证阶段用,生产环境请用os.urandom(12)生成随机nonce) data = b"a secret message" aad = None # 若Rails端设置了auth_data,此处需传入相同值 # 32字节的AES-256密钥 key = b'7\x98\xc1\xdf\x7f}\xea5?\\6\x17\tlT\xed\xa2a\x0fn\x87.(\x0c\xe4;*4\xda\x8fY\xc8' # 初始化AESGCM实例 aesgcm = AESGCM(key) # 验证用固定nonce(和Rails端保持完全一致) nonce = b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b' # 加密:返回密文+认证标签的组合 ciphertext_with_tag = aesgcm.encrypt(nonce, data, aad) # 拼接成和Rails一致的格式:nonce + 密文 + 标签 final_encrypted = nonce + ciphertext_with_tag # 打印Hex格式结果用于对比 print(f"Nonce (Hex): {nonce.hex()}") print(f"Ciphertext + Tag (Hex): {ciphertext_with_tag.hex()}") print(f"Final Encrypted (Hex): {final_encrypted.hex()}")
对应的Rails验证代码
你可以在Rails端运行这段代码,对比Hex输出是否和Python端完全匹配:
require 'openssl' data = "a secret message" aad = nil key = "\x7\x98\xc1\xdf\x7f}\xea5?\\6\x17\tlT\xed\xa2a\x0fn\x87.(\x0c\xe4;*4\xda\x8fY\xc8" nonce = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b" cipher = OpenSSL::Cipher.new('aes-256-gcm') cipher.encrypt cipher.key = key cipher.iv = nonce # GCM中IV等价于nonce cipher.auth_data = aad if aad ciphertext = cipher.update(data) + cipher.final tag = cipher.auth_tag # 拼接成和Python一致的格式 final_encrypted = nonce + ciphertext + tag puts "Final Encrypted (Hex): #{final_encrypted.unpack('H*')[0]}"
验证步骤
- 分别运行Python和Rails代码
- 对比两者输出的
Final Encrypted (Hex)值,如果完全相同,说明加密逻辑已经对齐 - 生产环境中,只需保证:
- Python用
os.urandom(12)生成随机nonce - 把nonce和加密后的密文+标签一起传给Rails端
- Rails端拆分出nonce、密文、标签后进行解密验证
- Python用
内容的提问来源于stack exchange,提问作者sscirrus




