Я создаю класс, который имеет 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')