Шифрование / расшифровка данных в python с помощью соли
Я хотел бы знать, в основном, как я могу зашифровать данные с помощью сгенерированного ключа salt, а затем расшифровать их с помощью python ?
Я прошелся по множеству веб-сайтов и модулей, и все они отлично смотрятся в части encrpytion, но ни один не может расшифровать, как кажется.
Моя главная забота-иметь сильный солевой ключ, который, вероятно, будет генерироваться в течение нескольких hunderd раз, а затем использовать этот ключ для шифрования данных - в частности, я изучаю шифрование JSON-кодированных данных с помощью солевого ключа, отправляя зашифрованные данные на другую сторону (слушающий клиент), а затем расшифровать данные там на основе алгоритма, который используется для генерации соляного ключа.
Я обнаружил, что модуль mcrypt будет лучше всего работать с этим, но для модуля python-mcrypt не так много документации (которая в настоящее время устарела и не поддерживается).
2 ответов:
Короткий ответ на ваш вопрос заключается в том, что вы объединяете пароль и соль и многократно хэшируете их, чтобы создать свой ключ. Затем вы добавляете соль к зашифрованному тексту, чтобы сгенерировать ключ для расшифровки. Чтобы убедиться, что у меня есть правильный ответ, я сделал несколько функций, чтобы сделать работу. Они приведены ниже.
В своем ответе я использовал 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 textpad_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_saltunpad_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
Вам не нужно ничего, кроме RNCryptor :
import rncryptor data = '...' password = '...' # rncryptor.RNCryptor's methods cryptor = rncryptor.RNCryptor() encrypted_data = cryptor.encrypt(data, password) decrypted_data = cryptor.decrypt(encrypted_data, password) assert data == decrypted_data # rncryptor's functions encrypted_data = rncryptor.encrypt(data, password) decrypted_data = rncryptor.decrypt(encrypted_data, password) assert data == decrypted_dataОн обеспечивает семантически безопасное (случайное соль и IV для каждого шифрования) шифрование и включает в себя безопасную проверку целостности (шифротекстом нельзя манипулировать, не заметив) через HMAC.
RNCryptor также имеет определенный формат данных, поэтому вам не нужно думать об этом и реализацияхна многих языках .
Comments