Ответ 1
Короткий ответ на ваш вопрос заключается в том, что вы комбинируете пароль и соль и повторяете их повторно для создания своего ключа. Затем вы добавляете соль в зашифрованный текст, чтобы вы могли генерировать ключ для дешифрования. Чтобы убедиться, что у меня есть правильный ответ, я сделал несколько функций для выполнения этой работы. Они приведены ниже.
В моем ответе я использовал 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
Сообщите мне, есть ли у вас какие-либо другие вопросы/разъяснения.