使用PyCryptodome的OCB模式通过Socket传输JSON时MAC校验失败
AES-OCB 加密Socket传输后MAC校验失败的排查方案
核心问题定位方向
你遇到的问题大概率是密钥不一致或加密模式不匹配导致的,以下是具体排查步骤和修复建议:
1. 核对加密和解密的密钥
加密函数中使用的是局部变量key,但解密函数用的是glob.aes_key,这两个必须是完全相同的字节串:
- 加密前打印
key.hex(),解密前打印glob.aes_key.hex(),逐字符对比是否一致 - 建议统一密钥来源,比如加密时也使用
glob.aes_key,避免局部变量和全局变量的差异
2. 确认加密模式一致
加密函数中用的是Amode,解密用的是AES.MODE_OCB,必须确保Amode就是AES.MODE_OCB:
- 可以直接替换成
AES.MODE_OCB,避免自定义变量被误赋值
3. 校验传输前后的字节完整性
即使JSON内容看起来一致,也要确认Base64解码后的字节和加密时完全相同:
- 加密端打印各字段的十六进制值:
cipher.nonce.hex()、ciphertext.hex()、tag.hex() - 解密端解码后打印对应字段的十六进制值:
jv['nonce'].hex()、jv['ciphertext'].hex()、jv['tag'].hex() - 逐字节对比,确保没有差异(PyCryptodome的
b64encode是标准Base64,编码解码逻辑本身无问题)
4. 检查Socket接收逻辑
如果Socket传输时数据被分段接收,可能导致实际接收的字节不完整(即使JSON看起来完整):
- 确保接收端用循环接收所有数据,比如先接收数据长度,再根据长度接收对应字节数的内容
修复后的示例代码
from Crypto.Cipher import AES from Crypto.Random import get_random_bytes import base64 as b64 import json import pickle import glob def enc_pic(data): # 统一使用全局密钥,避免不一致 cipher = AES.new(glob.aes_key, AES.MODE_OCB, nonce=get_random_bytes(8)) data = pickle.dumps(data) ciphertext, tag = cipher.encrypt_and_digest(data) # 打印加密端字段的十六进制,方便对比 print(f"加密nonce: {cipher.nonce.hex()}") print(f"加密密文: {ciphertext.hex()}") print(f"加密tag: {tag.hex()}") json_k = ['nonce', 'ciphertext', 'tag'] json_v = [b64.b64encode(x).decode('utf-8') for x in (cipher.nonce, ciphertext, tag)] return json.dumps(dict(zip(json_k, json_v))).encode("UTF-8") def decr_pic(data): try: b64_data = json.loads(data.decode("UTF-8")) json_k = ['nonce', 'ciphertext', 'tag'] jv = {k: b64.b64decode(b64_data[k]) for k in json_k} # 打印解密端字段的十六进制,和加密端对比 print(f"解密nonce: {jv['nonce'].hex()}") print(f"解密密文: {jv['ciphertext'].hex()}") print(f"解密tag: {jv['tag'].hex()}") cipher = AES.new(glob.aes_key, AES.MODE_OCB, nonce=jv['nonce']) plaintext = cipher.decrypt_and_verify(jv['ciphertext'], jv['tag']) res = pickle.loads(plaintext) except (ValueError, KeyError) as e: res = "解密失败" print(f"错误信息: {e}") return res
内容的提问来源于stack exchange,提问作者Сapy
相关产品推荐
相关产品推荐

