PyCrypt AES не может расшифровать после "reencrypt" - PullRequest
0 голосов
/ 20 октября 2018

Я создаю класс, который имеет 3 метода и пытаюсь работать как «база паролей».

Данные хранятся в двоичном файле, который имеет следующую структуру:

  • Первые 16 байтов -> Системный пароль, уже зашифрованный ключом аутентификации.
  • Следующие 16 байтов -> IV, случайным образом сгенерированный временемсистемный пароль был зашифрован.
  • Следующие 16-байтовые блоки -> Системный пароль, зашифрованный с помощью ключа, введенного пользователем.

Классы эти:

  • Первый - «регистрация» (ввод: auth_key, key).Он использует ключ аутентификации для расшифровки системного пароля, который хранится в двоичном файле.Как только пароль расшифрован, я снова его зашифровал, но на этот раз ключом, вставленным пользователем.Этот новый зашифрованный пароль теперь добавляется в двоичный файл.

  • Второй - «вход» (вход: ключ).Этот цикл проходит по каждому куску по 16 байт в двоичном файле, пытаясь расшифровать его с помощью ключа, сообщенного пользователем.

  • Третий пытается спросить: «Вы изменили свой пароль?"(входные данные: ключ, old_key).Ключ пользователя основан на его системном пароле (у каждого пользователя есть), который меняется ежемесячно.Если он сообщит этот новый ключ, код не сможет расшифровать системный пароль.Поэтому он попросит пользователя ввести старый пароль.Если старый пароль расшифровывает системный пароль, код попытается заменить байтовый блок, соответствующий старому паролю, на тот, который соответствует системному паролю, зашифрованному новым ключом.

Проблема: Все идет хорошо с «регистрацией» и «регистрацией».Хотя каждый раз, когда я заменяю блок, соответствующий старому паролю, на новый, я не могу расшифровать его позже.

Я попробовал и проверил все, что мог представить.

Это код:

# -*- coding: utf-8 -*-
#Created on Fri Oct 05 19:08:51 2018
#@author: LSP

from Crypto.Cipher import AES
from PyDrive.PyDrive import drive


class Robot:

def __init__(self):
    self.user = None
    self.password = None
    self.iv = None
    self.key = None
    self.old_key = None
    self.auth_key = None
    self.comp = None

################################################################################

def sign_up(self, key, auth_key):
    """ Cadastra uma senha para ser utilizada com key para descriptografar a senha do robô.

        :key: Chave utilizada para criptografar a senha (vai ser a senha do usuário na Drive).
        :complement_key: Chave utilizada para complementar a senha até que atinja 16bytes
        :authentication_key: Chave mestra utilizada para descriptografar a senha original do robô.
    """

    with open(r'robot', 'rb') as file:
        self.password = file.read(16)
        self.iv = file.read(16)

    # Transforms the key to 16Bytes
    self.transform_key(key=key, auth_key=auth_key, encode=True)

    # Decrypt the system password using authentication key
    aes = AES.new(self.auth_key, AES.MODE_CBC, self.iv)
    decd = aes.decrypt(self.password)

    # Reencrypt the system password using key entered by the user
    aes = AES.new(self.key, AES.MODE_CBC, self.iv)
    encd = aes.encrypt(decd)

    # Stores the new password in the binary file
    with open(r'robot', 'ab') as file:
        file.write(encd)

################################################################################

def sign_in(self, user, key):

    # Set some properties
    self.user = user
    self.transform_key(key=key, encode=True)

    # In case it couldn't decrypt, tries to access the system with the password entered by the user.

    if not self.decrypt():

        self.old_key = input("Por favor, insira a senha antiga: ")
        self.transform_key(old_key=self.old_key, encode=True)
        self.decrypt(recrypt=True)

################################################################################

def transform_key(self, key=None, old_key=None, auth_key=None, password=None, encode=False, decode=False):

    # Complement used to guarantee that the key has length equal to 16
    self.comp = '#'

    # Garante que a key tenha 16 Bytes
    if key is not None:
        self.key = key

        if encode:
            while len(self.key) != 16:
                self.key += self.comp
            self.key = self.key.encode('utf8')

        elif decode:
            self.key = self.key.decode('utf8')
            while self.key[-1] == self.comp:
                self.key = self.key[:-1]

    # Garante que a old_key tenha 16 Bytes
    if old_key is not None:
        self.old_key = old_key

        if encode:
            while len(self.old_key) != 16:
                self.old_key += self.comp
            self.old_key = self.old_key.encode('utf8')

        elif decode:
            self.old_key = self.old_key.decode('utf8')
            while self.old_key[-1] == self.comp:
                self.old_key = self.key[:-1]

    # Garante que a auth_key tenha 16 Bytes
    if auth_key is not None:
        self.auth_key = auth_key

        if encode:
            while len(self.auth_key) != 16:
                self.auth_key += self.comp
            self.auth_key = self.auth_key.encode('utf8')

        elif decode:
            self.auth_key = self.auth_key.decode('utf8')
            while self.auth_key[-1] == self.comp:
                self.auth_key = self.auth_key[:-1]

    if password is not None:
        self.password = password

        if encode:
            while len(self.password) != 16:
                self.password += self.comp
            self.password = self.password.encode('utf8')

        elif decode:
            self.password = self.password.decode('utf8')
            while self.password[-1] == self.comp:
                self.password = self.password[:-1]

####################################################################################################################

def decrypt(self, recrypt=False):

    # Creates AES object
    if recrypt:
        aes = AES.new(self.old_key, AES.MODE_CBC, self.iv)
    else:
        aes = AES.new(self.key, AES.MODE_CBC, self.iv)

    # Tries to decrypt passwords in binary file
    decrypted = False
    with open('robot', 'rb') as file:
        chunk = file.read(16)
        line = 1
        while chunk != b'':
            self.password = aes.decrypt(chunk)
            try:
                self.transform_key(password=self.password, decode=True)
                decrypted = True
                break
            except UnicodeDecodeError:
                chunk = file.read(16)
                line += 1

    if recrypt:

        self.transform_key(password=self.password, encode=True)
        aes_ini = AES.new(self.key, AES.MODE_CBC, self.iv)
        encd = aes_ini.encrypt(self.password)

        with open('robot', 'rb') as file:
            chunk_ini = file.read(16*(line-1))
            file.seek(16*line)
            chunk_fim = file.read()

        with open('robot', 'wb') as file:
            file.write(chunk_ini)
            file.write(chunk_fim)
            file.write(encd)

        self.transform_key(password=self.password, decode=True)

    return decrypted


if __name__ == "__main__":
    robot = Robot()
    robot.sign_up(key="testkey123@", auth_key="strongauthkey")
    robot.sign_up(key="secondkey123@", auth_key="strongauthkey")
    robot.sign_in(user='user', key='newkeyprovided')
...