You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中AES密钥字节数组转字符串及文件写入问题求助

问题根源与解决方案

核心问题:Python中字节(bytes)与字符串(str)的严格区分

C#中字节数组转Base64直接得到字符串,但Python里b64encode返回的是bytes类型,必须显式转为字符串才能和普通字符串拼接、写入文本文件。另外,随机生成的密钥字节本身不是合法UTF-8编码,直接decode("utf-8")必然报错。

逐个解决你的问题

  1. 解码UTF-8报错:随机密钥是二进制数据,不是UTF-8编码的文本,不能直接decode。正确做法是用Base64编码将二进制转为可打印字符串。
  2. 换行分割时类型错误:b64encode返回bytes,'\n'.join()要求元素是字符串,需先将Base64 bytes转为str(用decode("utf-8"))。
  3. 字符串与bytes拼接报错:同样是类型不匹配,先把Base64 bytes转成str再拼接。
  4. 写入文件时类型错误:open(file, 'w')模式只接受字符串,要么把Base64 bytes转str,要么用'wb'模式写二进制,但这里要和C#一致写文本,所以转str后写入。

修正后的Python实现(匹配C#功能)

先实现和你C#代码完全一致的密钥/IV生成、Base64编码、写入文件功能,再修正你原类中的错误:

1. 对应C#的核心功能实现

from tkinter.filedialog import asksaveasfilename
from Crypto.Random import get_random_bytes
from base64 import b64encode

# 生成256位AES密钥和IV(和C#的KeySize=256对应)
aes_key = get_random_bytes(32)  # 256位=32字节
aes_iv = get_random_bytes(16)

# 转Base64字符串(注意b64encode返回bytes,需decode成str)
key_b64 = b64encode(aes_key).decode("utf-8")
iv_b64 = b64encode(aes_iv).decode("utf-8")

# 构造文件内容,和C#格式一致
file_text = f"----- Start Key File -----\n<0>{key_b64}</0>\n<1>{iv_b64}</1>\n----- End Key File -----"

# 保存文件
file_path = asksaveasfilename(
    filetypes=[("SEA file", "*.sea")],
    defaultextension=".sea"
)
if file_path:
    with open(file_path, 'w', encoding="utf-8") as f:
        f.write(file_text)

2. 修正你的Crypton类(解决加密解密的字节/字符串处理错误)

你的原类中错误地将二进制数据(ciphertext、tag、nonce)直接用UTF-8解码/编码,这会导致数据损坏,正确做法是用Base64处理二进制数据:

from tkinter.filedialog import asksaveasfilename, askopenfilename
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from base64 import b64encode, b64decode

class Crypton:
    @staticmethod
    def GetKey():
        # 生成16字节密钥,转Base64字符串返回(不再直接decode UTF-8)
        return b64encode(get_random_bytes(16)).decode("utf-8")

    @staticmethod
    def Encrypt(data, key_b64):
        # 把Base64字符串密钥转回字节
        key = b64decode(key_b64)
        cipher = AES.new(key, AES.MODE_EAX)
        ciphertext, tag = cipher.encrypt_and_digest(data)
        nonce = cipher.nonce
        # 所有二进制数据转Base64字符串后返回
        return [
            key_b64,
            b64encode(ciphertext).decode("utf-8"),
            b64encode(tag).decode("utf-8"),
            b64encode(nonce).decode("utf-8")
        ]

    @staticmethod
    def Decrypt(str_data):
        # 把Base64字符串转回字节
        key = b64decode(str_data[0])
        ciphertext = b64decode(str_data[1])
        tag = b64decode(str_data[2])
        nonce = b64decode(str_data[3])
        cipher = AES.new(key, AES.MODE_EAX, nonce)
        return cipher.decrypt_and_verify(ciphertext, tag)

    @staticmethod
    def CreateCryptonKeyFile(key_b64):
        bricked_key = Crypton.BreakKey(key_b64)
        text = f"------ Crypton Key Begin ------\n{bricked_key}\n------  Crypton Key End  ------"
        file = asksaveasfilename(
            filetypes=[("Crypton Key File", ".cey")],
            defaultextension=".cey")
        if file:
            with open(file, 'w', encoding="utf-8") as fob:
                fob.write(text)

    @staticmethod
    def BreakKey(key):
        every = 31
        breaked = '\n'.join(key[i:i+every] for i in range(0, len(key), every))
        return breaked

    @staticmethod
    def ReadCryptonKeyFile():
        file = askopenfilename(
            filetypes=[("Crypton Key File", ".cey")],
            defaultextension=".cey")
        if file:
            with open(file, 'r', encoding="utf-8") as infile:
                return Crypton.ReadCryptonKeyString(infile.read())

    @staticmethod
    def ReadCryptonKeyString(string):
        key = ''.join(
            string.replace("------ Crypton Key Begin ------\n", "")\
            .replace("\n------  Crypton Key End  ------", "")\
            .split('\n')
        )
        return key

关键修正点说明

  • 所有二进制数据(密钥、ciphertext、tag、nonce)都通过Base64在字符串和字节之间转换,不再直接用UTF-8解码/编码。
  • AES.new()方法要求传入字节类型的密钥,因此加密解密时必须将Base64字符串转回字节。
  • 文件读写时指定encoding="utf-8",确保和C#的文本编码一致。

内容的提问来源于stack exchange,提问作者DazzRick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 11:35:14