Шаг 11.
Задачи ComputerScience на Python. Простые задачи. Невскрываемое шифрование. Шифрование и дешифрование

    На этом шаге мы рассмотрим особенности выполнения этих операций.

    Как объединить фиктивные данные с исходными данными, которые мы хотим зашифровать? В этом поможет операция XOR - логическая побитовая (работает на уровне битов) операция, которая возвращает true, если один из ее операндов равен True, и False, если оба оператора равны true или ни один из них не равен true. Как вы уже догадались, аббревиатура XOR означает exclusive or (исключающее ИЛИ).

    В Python оператор XOR обозначается как ^. В контексте битов двоичных чисел XOR возвращает 1 для 0 ^ 1 и 1 ^ 0, но 0 для 0 ^ 0 и 1 ^ 1. Если объединить два числа, выполнив для каждого их бита XOR, то полезным свойством этой операции будет то, что при объединении результата с одним из операндов получим второй операнд:

  А ^ B = С 
  С ^ В = А 
  С ^ А = В

    Такое представление ключа лежит в основе шифрования с использованием одноразового шифра. Чтобы сформировать результат, мы просто выполняем XOR для значения int, представляющего байты исходной строки str, и случайно сгенерированного значения int той же битовой длины, полученного с помощью random_key(). Полученная пара ключей будет фиктивными данными и результатом шифрования.

def encrypt(original: str) -> Tuple[int, int]:
    original_bytes: bytes = original.encode()
    dummy: int = random_key(len(original_bytes))
    original_key: int = int.from_bytes(original_bytes, "big")
    encrypted: int = original_key ^ dummy  # XOR
    return dummy, encrypted


Функция int.from_bytes() получает два аргумента. Первый, bytes - это строка, которую нужно преобразовать в int. Второй - порядок следования этих байтов (big). Порядок следования означает последовательность байтов, используемую для хранения данных. Какой байт идет первым, старший или младший? В нашем случае, если применять один и тот же порядок при шифровании и дешифровке, это не имеет значения, потому что мы фактически манипулируем данными только на уровне отдельных битов. В других ситуациях, когда вы не контролируете обе стороны процесса шифрования, порядок может иметь значение, поэтому будьте осторожны!

    Расшифровка - это просто рекомбинация пары ключей, сгенерированной с помощью encrypt(). Она достигается посредством повторного выполнения операции XOR побитово для двух ключей. Окончательный результат должен быть преобразован обратно в тип str. Для этого сначала int преобразуется в bytes с помощью int.to_bytes(). Данный метод требует, чтобы число байтов было преобразовано из int. Чтобы получить это число, нужно разделить длину в битах на 8 (количество битов в байте). А затем метод bytes decode() возвращает str.

def decrypt(key1: int, key2: int) -> str:
    decrypted: int = key1 ^ key2  # XOR
    temp: bytes = decrypted.to_bytes((decrypted.bit_length() + 7) // 8, "big")
    return temp.decode()

    Здесь также необходимо прибавить 7 к длине расшифрованных данных, прежде чем использовать целочисленное деление (//) на 8, чтобы гарантировать округление и избежать ошибки смещения на единицу. Если наше шифрование с одноразовыми ключами работает, то мы должны шифровать и дешифровать одну и ту же строку Unicode без проблем.

if __name__ == "__main__":
    key1, key2 = encrypt("One Time Pad!")
    result: str = decrypt(key1, key2)
    print(result)
Архив с файлом можно взять здесь.

    Если в консоль выводится фраза "One Time Pad!", значит, все заработало.

    На следующем шаге мы рассмотрим вычисление числа π.




Предыдущий шаг Содержание Следующий шаг