Короткий ответ на ваш вопрос заключается в том, что вы комбинируете пароль и соль и неоднократно хешируете их для создания своего ключа. Затем вы добавляете соль в зашифрованный текст, чтобы вы могли сгенерировать ключ для расшифровки. Чтобы убедиться, что у меня был правильный ответ, я сделал несколько функций для выполнения работы. Они приведены ниже.
В своем ответе я использовал pycrypto, поэтому нам нужно импортировать несколько таких библиотек.
import Crypto.Random
from Crypto.Cipher import AES
import hashlib
Чтобы улучшить читабельность, я определил несколько констант, которые я буду использовать позже.
# salt size in bytes
SALT_SIZE = 16
# number of iterations in the key generation
NUMBER_OF_ITERATIONS = 20
# the size multiple required for AES
AES_MULTIPLE = 16
Чтобы использовать соль, я разработал схему шифрования на основе пароля. Я использовал стандарт RSA PKCS # 5 для генерации и заполнения ключей шифрования на основе пароля, адаптированный для алгоритма шифрования AES.
Для генерации ключа пароль и соль объединяются. Эта комбинация хэшируется столько раз, сколько требуется.
def generate_key(password, salt, iterations):
assert iterations > 0
key = password + salt
for i in range(iterations):
key = hashlib.sha256(key).digest()
return key
Чтобы дополнить текст, вы выясните, сколько дополнительных байтов у вас есть, помимо четного числа, равного 16. Если это 0, вы добавляете 16 байтов заполнения, если это 1, вы добавляете 15 и т. Д. всегда добавляйте отступы. Символ, которым вы дополняете, является символом с тем же значением, что и число байтов заполнения (chr(padding_size)
), чтобы помочь удалить заполнение в конце (ord(padded_text[-1])
).
def pad_text(text, multiple):
extra_bytes = len(text) % multiple
padding_size = multiple - extra_bytes
padding = chr(padding_size) * padding_size
padded_text = text + padding
return padded_text
def unpad_text(padded_text):
padding_size = ord(padded_text[-1])
text = padded_text[:-padding_size]
return text
Шифрование требует генерации случайной соли и использования ее вместе с паролем для генерации ключа шифрования. Текст дополняется с помощью вышеуказанной функции pad_text
, а затем шифруется с помощью объекта шифрования. Зашифрованный текст и соль объединяются и возвращаются в результате. Если вы хотите отправить его в виде открытого текста, вам необходимо закодировать его с помощью base64.
def encrypt(plaintext, password):
salt = Crypto.Random.get_random_bytes(SALT_SIZE)
key = generate_key(password, salt, NUMBER_OF_ITERATIONS)
cipher = AES.new(key, AES.MODE_ECB)
padded_plaintext = pad_text(plaintext, AES_MULTIPLE)
ciphertext = cipher.encrypt(padded_plaintext)
ciphertext_with_salt = salt + ciphertext
return ciphertext_with_salt
Расшифровка продолжается в обратном направлении, удаляя соль из зашифрованного текста и используя ее для расшифровки оставшейся части зашифрованного текста. Затем открытый текст распаковывается с помощью unpad_text
.
def decrypt(ciphertext, password):
salt = ciphertext[0:SALT_SIZE]
ciphertext_sans_salt = ciphertext[SALT_SIZE:]
key = generate_key(password, salt, NUMBER_OF_ITERATIONS)
cipher = AES.new(key, AES.MODE_ECB)
padded_plaintext = cipher.decrypt(ciphertext_sans_salt)
plaintext = unpad_text(padded_plaintext)
return plaintext
Дайте мне знать, если у вас есть другие вопросы / разъяснения.