Шифр Цезаря

Первый шифр в нашем курсе — сдвиг букв по алфавиту. Им пользовался ещё Юлий Цезарь две тысячи лет назад.
Цезарь сдвигал каждую букву на 3 позиции вперёд, чтобы враги не прочитали его военные приказы.

Как устроен шифр Цезаря

Идея предельно проста: каждую букву сообщения заменяем на букву, стоящую на k позиций дальше в алфавите. Число k — это ключ. Например, при ключе 3 буква A превращается в D, B — в E, и так далее. Когда доходим до конца алфавита, продолжаем с начала (Z + 3 = C).

Шифруем на Python

Возьмём английский алфавит из 26 букв и реализуем сдвиг. Деление по модулю 26 (% 26) обеспечивает «закольцовывание» алфавита:

import string

alphabet = string.ascii_uppercase  # A..Z

def caesar_encrypt(text, key):
    result = ""
    for ch in text.upper():
        if ch in alphabet:
            i = (alphabet.index(ch) + key) % 26
            result += alphabet[i]
        else:
            result += ch
    return result

print(caesar_encrypt("HELLO WORLD", 3))

Вывод:

KHOOR ZRUOG

Расшифровка

Чтобы вернуть текст обратно, сдвигаем в другую сторону — то есть применяем тот же алгоритм с ключом -key:

import string
alphabet = string.ascii_uppercase

def caesar(text, key):
    result = ""
    for ch in text.upper():
        if ch in alphabet:
            result += alphabet[(alphabet.index(ch) + key) % 26]
        else:
            result += ch
    return result

secret = caesar("ATTACK AT DAWN", 7)
print("Зашифровано:", secret)
print("Расшифровано:", caesar(secret, -7))

Вывод:

Зашифровано: HAAHJR HA KHDU
Расшифровано: ATTACK AT DAWN

Почему его легко взломать

У шифра Цезаря всего 25 возможных ключей (сдвиг от 1 до 25). Это значит, что Ева может просто перебрать их все и посмотреть, какой вариант осмысленный. Такой перебор называют атакой «грубой силой» (brute force). Попробуем:

import string
alphabet = string.ascii_uppercase

def caesar(text, key):
    return "".join(
        alphabet[(alphabet.index(c) + key) % 26] if c in alphabet else c
        for c in text.upper()
    )

cipher = "KHOOR"
for key in range(1, 26):
    print(key, "->", caesar(cipher, -key))

Вывод:

1 -> JGNNQ
2 -> IFMMP
3 -> HELLO
4 -> GDKKN
...
25 -> LIPPS

Среди 25 вариантов глазами легко найти осмысленный — HELLO при ключе 3. Вот почему шифр Цезаря годится только для развлечения, а не для защиты настоящих секретов: пространство ключей слишком мало.

Проверьте себя
1. Сколько всего различных рабочих ключей у шифра Цезаря для латинского алфавита?
A3
B25
C26
DБесконечно много
2. Как называется взлом шифра простым перебором всех возможных ключей?
AЧастотный анализ
BАтака грубой силой (brute force)
CСоциальная инженерия
DХеширование