Шифрование на основе SHA-256 (часть 2)

от автора

Вступление

Статья частично является продолжениям идеи создания своего алгоритма шифрования на основе хеш функций из первой части. И так, продолжим. Большинство практических схем шифрования строятся вокруг проверенных стандартов вроде AES или RSA. В этом материале мы разберем альтернативный, исследовательский подход: шифрование, где для каждого байта сообщения подбирается собственное значение salt на основе SHA-256. Главная особенность алгоритма в том, что для шифрования используется хеш функция. Цель статьи — интуитивно и пошагово объяснить механику новой версии алгоритма, чтобы вы могли оценить его сильные и слабые стороны.

Идея алгоритма

Алгоритм обрабатывает сообщение как последовательность байтов. Для каждого байта используется текущее состояние ключа. Из ключа вычисляется хэш, а его первый байт играет роль маски XOR. Дальше происходит ключевой шаг, алгоритм подбирает число salt. Перебор продолжается, пока первый байт полученного хэша не совпадет с целевым значением, которое было рассчитано из исходного байта и маски XOR. Найденный salt и сохраняется в шифротекст. После этого ключ обновляется (снова через SHA-256), и следующий байт обрабатывается уже с новым ключом. Каждый шаг зависит от предыдущего состояния.

Шифрования

Шаг 1. Из секретной фразы получаем стартовый ключ

Берем любую секретную фразу произвольной длины (лучше конечно не меньше 16 символов) и хэшируем ее через SHA-256. Результат всегда 32 байта — это и есть стартовый ключ алгоритма.

import hashlibsecret_phrase = "my very secret passphrase"secret_seed = secret_phrase.encode("utf-8")initial_key = hashlib.sha256(secret_seed).digest()

Шаг 2. Готовим данные для шифрования

Алгоритм работает с байтами, поэтому сообщение тоже переводим в bytes.

message = "Hello!"message_bytes = message.encode("utf-8")

Шаг 3. Шифруем один байт

Для каждого байта:

  • берем маску из текущего ключа (первый байт SHA-256 от ключа);

  • считаем целевое значение через XOR;

  • подбираем salt перебором, пока первый байт SHA-256 от key + salt не совпадет с целью, другими словами, не будет равно xor_target (single_byte ^ mask_byte).

def encrypt_byte(single_byte: int, current_key: bytes) -> tuple[int, bytes]:    mask = hashlib.sha256(current_key).digest()    mask_byte = mask[0]    xor_target = single_byte ^ mask_byte    salt = 0    while True:        salt_bytes = salt.to_bytes(4, byteorder="big")        attempt_hash = hashlib.sha256(current_key + salt_bytes).digest()        if attempt_hash[0] == xor_target:            break        salt += 1    next_key = hashlib.sha256(current_key).digest()    return salt, next_key

Шаг 4. Шифруем все сообщение

Повторяем шаг для каждого байта. В результате получаем массив salt — это и есть шифротекст.

salts = []current_key = initial_keyfor b in message_bytes:    salt, current_key = encrypt_byte(b, current_key)    salts.append(salt)print("Ciphertext (salts):", salts)

Расшифрования

Шаг 1. Расшифровываем один байт

На расшифровке перебора уже нет. Мы знаем salt, поэтому сразу восстанавливаем байт.

def decrypt_byte(salt: int, current_key: bytes) -> tuple[int, bytes]:    mask = hashlib.sha256(current_key).digest()    mask_byte = mask[0]    salt_bytes = salt.to_bytes(4, byteorder="big")    attempt_hash = hashlib.sha256(current_key + salt_bytes).digest()    xor_target = attempt_hash[0]    single_byte = xor_target ^ mask_byte    next_key = hashlib.sha256(current_key).digest()    return single_byte, next_key

Шаг 2. Расшифровываем все сообщение

Идем по всему массиву salts, восстанавливаем байты, собираем обратно строку.

decrypted_bytes = bytearray()current_key = initial_keyfor salt in salts:    single_byte, current_key = decrypt_byte(salt, current_key)    decrypted_bytes.append(single_byte)decrypted_message = decrypted_bytes.decode("utf-8")print("Decrypted:", decrypted_message)

Итоги

Этот алгоритм — интересный пример того, как можно построить обратимое преобразование вокруг SHA-256 или другой хеш функции и использовать это для шифрования данных. Алгоритм конечно можно модифицировать и улучшать, здесь показана только идея и принцип работы. Полный код можно найти на GitHub. Спасибо за внимание и комментарии.

ссылка на оригинал статьи https://habr.com/ru/articles/1046289/