如何从文件中解码 utf-8

How do I decode utf-8 from a file

我有一个程序试图使用 aes 加密消息。当我必须加密消息并得到 TypeError: Object type <class 'str'> cannot be passed to C code 时,问题就出现了。我发现如果我将它编码为 utf-8 它可以工作,但是当我尝试解密它时它不会摆脱 b'...' 并且 base64 解密失败,使我的 iv 不是 16 字节。每当我尝试使用 aes.decrypt(file.readline().decode("utf-8")) 解码文件的第一行时,它都会说我不能在 str 上使用解码。

from Crypto.Cipher import AES
from Crypto import Random

def pad(s):
    pad = s + (16 - len(s) % 16) * chr(16 - len(s) % 16)
    return str(pad)

def unpad(s):
    unpad = s[:-ord(s[len(s)-1:])]
    return str(unpad)


class AESCipher:
    def __init__( self, key ):
    self.key = key

    def encrypt( self, s ):
        raw = pad(s)
        iv = Random.new().read( AES.block_size )
        cipher = AES.new( self.key, AES.MODE_CBC, iv )
        return base64.b64encode( iv + cipher.encrypt( raw.encode("utf-8") ) )

    def decrypt( self, enc ):
        enc = base64.b64decode(enc)
        iv = enc[:16]
        cipher = AES.new(self.key, AES.MODE_CBC, iv )
        return unpad(cipher.decrypt( enc[16:] ))

我是加密新手,所以我真的不知道以前是否有人回答过这个问题,我只是不知道如何表达,但我已经四处寻找几个小时了,还没有'没找到任何东西。 谢谢你。 再次抱歉,如果措辞不当。

您的加密和解密操作不是彼此的镜像。

def encrypt( self, s ):
    iv = Random.new().read( AES.block_size )       # new IV
    cipher = AES.new( self.key, AES.MODE_CBC, iv ) # create cipher
    payload = s.encode("utf-8")                    # string to bytes
    encrypted = cipher.encrypt(pad(payload))       # pad before encrypt
    return base64.b64encode( iv + encrypted )      # b64 data

def decrypt( self, enc ):
    data = base64.b64decode( enc )                 # b64 data
    iv = data[:AES.block_size]                     # split it up
    encrypted = data[AES.block_size:]              # 
    cipher = AES.new(self.key, AES.MODE_CBC, iv )  # recreate cipher
    payload = unpad(cipher.decrypt( encrypted ))   # unpad after decrypt
    return payload.decode("utf8")                  # bytes to string

只能加密字节。字符串不是字节,因此必须先将字符串编码为字节表示形式。 UTF-8 是一种合适的表示形式,但也可以是 UTF-16 甚至 UTF-32 (read about the differences)。

但是,由于密码可以处理 任何 字节有效负载,我将删除目前将这些函数限制为字符串的部分。我会将它们更改为 expect 和 return 字节,然后是:

  • 分别称它们为x = aes.encrypt(s.encode('utf8'))s = aes.decrypt(x).decode('utf8'),或
  • 为字符串处理创建包装函数。

要加密文件,您可以直接这样做:

with open('some.txt', 'rb') as fp:
    encrypted = aes.encrypt(fp.read())

这根本不会强加任何编码假设,而是按原样加密文件的字节。

AES 是分组密码,这意味着 encrypt(a) + encrypt(b)encrypt(a + b) 相同。对于加密文件非常有用,因为您可以 read the file incrementally in chunks of N * AES.block_size,只填充最后一个块。这比先将整个文件读入内存更节省内存。您当前的 encryptdecrypt 设置没有使用它。