Шифрование / расшифровка данных в python с помощью соли



Я хотел бы знать, в основном, как я могу зашифровать данные с помощью сгенерированного ключа salt, а затем расшифровать их с помощью python ?



Я прошелся по множеству веб-сайтов и модулей, и все они отлично смотрятся в части encrpytion, но ни один не может расшифровать, как кажется.



Моя главная забота-иметь сильный солевой ключ, который, вероятно, будет генерироваться в течение нескольких hunderd раз, а затем использовать этот ключ для шифрования данных - в частности, я изучаю шифрование JSON-кодированных данных с помощью солевого ключа, отправляя зашифрованные данные на другую сторону (слушающий клиент), а затем расшифровать данные там на основе алгоритма, который используется для генерации соляного ключа.



Я обнаружил, что модуль mcrypt будет лучше всего работать с этим, но для модуля python-mcrypt не так много документации (которая в настоящее время устарела и не поддерживается).

701   2  

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 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
Дайте мне знать, если у вас есть какие-либо другие вопросы/разъяснения.

Вам не нужно ничего, кроме 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

    Ничего не найдено.