如何从文件解码utf-8

时间:2018-12-09 08:42:08

标签: python-3.x encryption python-unicode unicode-string

我有一个程序尝试使用es加密消息。当我必须加密消息并且得到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:] ))

我是加密技术的新手,所以我真的不知道以前是否已经回答过这个问题,而且我只是不知道该怎么写,但是我已经环顾了几个小时,却没有发现任何东西。 谢谢。 再次,抱歉,如果措词不正确。

1 个答案:

答案 0 :(得分:4)

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

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)。

但是,由于密码可以处理任何个字节的有效负载,因此我将删除当前将这些功能限制为字符串的部分。我将其更改为期望并返回字节,然后:

  • 将它们分别称为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)相同。对于加密文件非常有用,因为您可以N * AES.block_size中的read the file incrementally in chunks,仅填充最后一个块。这比先将整个文件读入内存要高得多的内存效率。您当前的encryptdecrypt设置没有使用它。