Как мне декодировать utf-8 из файла - PullRequest
0 голосов
/ 09 декабря 2018

У меня есть программа, которая пытается зашифровать сообщение, используя 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")), он говорит, что я не могу использовать decode на 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 голосов
/ 09 декабря 2018

Ваши операции шифрования и дешифрования не являются зеркальным отображением друг друга.

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 ( читайте о различиях ).

Однако, поскольку шифр может обработать любой байт, я бы удалил часть, которая в настоящее время ограничивает эти функции строками.Я бы изменил их, чтобы они ожидали и возвращали байты, а затем либо:

  • вызываем их как 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, только с добавленным последним блоком.Это намного эффективнее, чем чтение всего файла в память.Ваша текущая настройка encrypt и decrypt не использует это.

...