Python中使用AES GCM解密报错:'Cipher'对象无'decrypt'属性
问题解决建议
核心错误原因
你遇到的问题都是因为AES-GCM解密时未正确传入认证标签,以及对cryptography库的GCM模式API使用有误。
修正后的解密代码
正确的解密流程需要在decryptor对象上调用authenticate_tag()方法传入标签,再执行解密和finalize:
import base64 import json from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC from cryptography.hazmat.primitives import hashes from cryptography.hazmat.backends import default_backend # 接收并解码数据 encrypted_data_b64 = request['encrypted_data'] tag_b64 = request['tag'] salt_b64 = request['salt'] encrypted_data = base64.b64decode(encrypted_data_b64) tag = base64.b64decode(tag_b64) salt = base64.b64decode(salt_b64) # 重新推导密钥 password = b'password' kdf = PBKDF2HMAC( algorithm=hashes.SHA256(), length=32, salt=salt, iterations=10000, backend=default_backend() ) key = kdf.derive(password) # 初始化Cipher和decryptor cipher = Cipher(algorithms.AES(key), modes.GCM(salt), backend=default_backend()) decryptor = cipher.decryptor() # 关键步骤:传入认证标签 decryptor.authenticate_tag(tag) # 执行解密 try: decrypted_data = decryptor.update(encrypted_data) + decryptor.finalize() # 转成JSON对象 data = json.loads(decrypted_data.decode('utf-8')) except Exception as e: print("解密或认证失败:", str(e))
加密代码的优化建议
- 不要复用PBKDF2的salt作为GCM的nonce:虽然16字节长度符合GCM要求,但PBKDF2的salt是用于密钥推导的,GCM的nonce应该是独立的随机值(推荐12字节长度,能提升性能),避免逻辑混淆。修改后的加密代码示例:
import os import json from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC from cryptography.hazmat.primitives import hashes from cryptography.hazmat.backends import default_backend # 分别生成密钥推导用的salt和GCM用的nonce salt = os.urandom(16) nonce = os.urandom(12) # GCM推荐12字节nonce password = b'password' kdf = PBKDF2HMAC( algorithm=hashes.SHA256(), length=32, salt=salt, iterations=10000, backend=default_backend() ) key = kdf.derive(password) # 使用独立的nonce初始化GCM cipher = Cipher(algorithms.AES(key), modes.GCM(nonce), backend=default_backend()) encryptor = cipher.encryptor() data = {'xxxx': 'xxxx', 'xxxx': 'xxxx'} encrypted_data = encryptor.update(json.dumps(data).encode('utf-8')) + encryptor.finalize() tag = encryptor.tag # 此时需要把salt、nonce、encrypted_data、tag都传给服务端(都做base64编码)
对应的解密时,需要接收nonce_b64,解码后传入modes.GCM(nonce)。
- 添加异常处理:加密解密过程中可能出现密钥推导错误、标签认证失败等情况,添加try-except块能捕获并处理这些异常。
内容的提问来源于stack exchange,提问作者Sam11
相关产品推荐
相关产品推荐

