AES-256-GCM跨语言解密问题:Python解码NodeJS加密数据报错
解决NodeJS AES-GCM加密数据的Python解密问题
问题现象
使用Python解密NodeJS加密的AES-GCM数据时,执行decrypted.decode('utf-8')触发解码错误:
Error: 'utf-8' codec can't decode byte 0xc8 in position 0: invalid continuation byte
原代码对比
Python 解密代码(错误版本)
import base64 from Crypto.Cipher import AES args = { "content": "725cd5204cf64987a39a6622884527e0", "iv": "e6174b11cd2a18fc", "tag": { "data": [26, 91, 205, 206, 134, 22, 167, 101, 110, 27, 155, 100, 41, 99, 34, 135], "type": "Buffer" }, "key": "SqqUUMnwEVUCBYT7p/0Zfz4Cq2eazHqQ" } def decrypt_auth_tag(args): try: key = args["key"] content = bytes.fromhex(args["content"]) iv = bytes.fromhex(args["iv"]) tag = bytes(args["tag"]["data"]) cipher = AES.new(key.encode('utf-8'), AES.MODE_GCM, nonce=iv) cipher.update(tag) # 错误核心 decrypted = cipher.decrypt(content) return decrypted.decode('utf-8') except Exception as e: print("Error:", e) print(decrypt_auth_tag(args))
NodeJS 解密代码(正常工作版本)
const crypto = require('crypto'); let args = { "content": "725cd5204cf64987a39a6622884527e0", "iv": "e6174b11cd2a18fc", "tag": { "data": [26, 91, 205, 206, 134, 22, 167, 101, 110, 27, 155, 100, 41, 99, 34, 135], "type": "Buffer" } } // Decrypts the data using a key, iv, and auth tag function decryptAuthTag(args) { try { const key = "SqqUUMnwEVUCBYT7p/0Zfz4Cq2eazHqQ"; const encrypted = { content: args.content, iv: args.iv, tag: args.tag }; const alg = 'aes-256-gcm'; const decipher = crypto.createDecipheriv(alg, key, encrypted.iv); decipher.setAuthTag(Buffer.from(encrypted.tag)); let dec = decipher.update(encrypted.content, 'hex', 'utf8'); dec += decipher.final('utf8'); return dec; } catch (error) { return "ERROR" } } console.log(decryptAuthTag(args))
错误原因与修正方案
核心错误点
Python代码中错误地将**认证标签(tag)当作附加认证数据(AAD)**调用cipher.update(tag),但NodeJS里是通过setAuthTag()设置认证标签,用于解密后的完整性校验。
修正后的Python代码
import base64 from Crypto.Cipher import AES args = { "content": "725cd5204cf64987a39a6622884527e0", "iv": "e6174b11cd2a18fc", "tag": { "data": [26, 91, 205, 206, 134, 22, 167, 101, 110, 27, 155, 100, 41, 99, 34, 135], "type": "Buffer" }, "key": "SqqUUMnwEVUCBYT7p/0Zfz4Cq2eazHqQ" } def decrypt_auth_tag(args): try: key = args["key"] content = bytes.fromhex(args["content"]) iv = bytes.fromhex(args["iv"]) tag = bytes(args["tag"]["data"]) cipher = AES.new(key.encode('utf-8'), AES.MODE_GCM, nonce=iv) # 移除错误的cipher.update(tag) decrypted = cipher.decrypt(content) # 解密后验证认证标签 cipher.verify(tag) return decrypted.decode('utf-8') except Exception as e: print("Error:", e) print(decrypt_auth_tag(args))
关键修改说明
- 移除
cipher.update(tag):该方法用于处理附加认证数据(AAD),而非认证标签,NodeJS代码中并未使用AAD,因此不需要这一步。 - 添加
cipher.verify(tag):解密完成后调用此方法验证认证标签的完整性,这与NodeJS的setAuthTag()逻辑完全对应。
运行修正后的代码即可得到与NodeJS一致的解密结果。
内容的提问来源于stack exchange,提问作者Melque Lima
相关产品推荐
相关产品推荐

