Шифр простой подстановки меняет названия букв, но почти не трогает привычки
языка. Если «ст» часто соседствуют в русском тексте, то их зашифрованные
образы тоже будут встречаться рядом. MCMC превращает этот статистический след
в маршрут по пространству ключей — и заодно показывает, где заканчивается
информация, а где начинается фантазия исследователя.
Ключ как перестановка
Пусть алфавит содержит m символов. Ключ k — перестановка: каждую букву
открытого текста он заменяет ровно одной буквой шифротекста. Число возможных
ключей равно m!. Для 33 русских букв
33!≈8,68⋅1036,
а в информационных единицах
log233!≈122,7бит.
Расшифровка — применение обратной перестановки:
k−1(k(xt))=xtдлявсехt.
Перебрать такое пространство невозможно: если проверять по миллиарду ключей в
секунду, возраста Вселенной не хватит и на ничтожную долю списка. При этом
шифр не скрывает длины слов, повторов букв и статистики соседства. В слове
«топот» первая и последняя буквы совпадают — и после шифрования тоже.
Для учебного опыта удобно привести текст к фиксированному алфавиту: строчные
русские буквы плюс пробел, удалить редкие знаки, а ё либо сохранить отдельно,
либо заранее заменить на е. Правило должно быть одинаковым для обучающего
корпуса и шифротекста. Это не мелкая чистка: она определяет модель языка.
Что шифр не прячет
Гистограмма частот при подстановке не меняет формы — меняются только подписи
столбцов. Возьмём реальный корпус: тексты уроков 01–40 этого учебника,
приведённые к 33 буквам и пробелу, — 921 345 знаков. Самая частая буква — о
(10,4 % всех букв), затем е (8,7 %). Пробел занимает 14,6 % всех символов.
После шифрования те же доли достанутся образам этих букв.
#{tyt=k(c)}=#{txt=c}длялюбойбуквыc.
Иначе говоря, вектор частот шифротекста — это вектор частот открытого текста,
переставленный тем же ключом:
Рис. 68.1. Ключ меняет имена букв, но не рисунок повторов
Верхняя часть: одинаковые буквы открытого текста дают одинаковые буквы
шифротекста, и наоборот. Нижняя часть: столбцы частот совпадают по высоте, но
подписаны разными буквами. Всё, что должен сделать взломщик, — правильно
переставить подписи; вопрос лишь в том, чем измерять правильность.
Наивный частотный анализ говорит: самый частый символ шифра — это о. Иногда
угадывает. Но между а (8,0 %) и и (7,6 %) разницы почти нет, и на коротком
тексте порядок частот перемешивается случайно. Нужна статистика более высокого
порядка — соседство.
Язык как вероятностная цепь
Возьмём тот же корпус и посчитаем частоты биграмм и триграмм. Сглаженная
вероятность символа ct после контекста:
Логарифм превращает произведение малых вероятностей в сумму и защищает от
численного обнуления. Сглаживание λ>0 не даёт одной невиданной
триграмме уничтожить весь балл.
Это маленькая языковая модель: она знает только короткий
контекст, зато её балл прозрачен и считается за микросекунды. Высокий L не
доказывает осмысленность текста, но обычно предпочитает русские сочетания
случайным.
В обозначениях статистической физики это распределение Больцмана:
π(k)=Ze−βE(k),Z=k′∈K∑e−βE(k′),∣K∣=m!.
Заметим важное свойство: балл зависит от ключа только через расшифрованный
текст. Два ключа, дающие одинаковый текст, неразличимы для модели, как бы
по-разному ни были записаны их таблицы.
Сколько информации в одном знаке
Измерим язык в битах. Если бы все 34 символа были равновероятны и независимы,
каждый нёс бы
H0=log234≈5,09бита.
Посчитаем кросс-энтропию наших моделей на отложенном тексте (уроки 41–50,
128 344 знака, при обучении не использованы):
H=−n1t∑log2p(xt∣контекст).
Получаем 4,42 бита для униграмм, 3,59 для биграмм и 2,88 для триграмм. Каждый
следующий порядок контекста отнимает у текста примерно по три четверти бита
неопределённости.
Разность между максимальной и фактической энтропией — избыточность:
D=H0−H3≈5,09−2,88=2,20битаназнак.
Каждый знак шифротекста приносит примерно 2,20 бита сведений о ключе. Ключ
«весит» 122,7 бита. Значит, ждать однозначного ответа раньше, чем
U=Dlog2m!≈2,20122,7≈56
знаков, бессмысленно — это расстояние единственности Шеннона.
Локальные ходы в огромном пространстве
Соседний ключ получают обменом образов двух букв. Такой ход меняет лишь две
строки таблицы, но может исправить много позиций текста. Предложение
симметрично: вероятность поменять а и б такая же, как вернуть их обратно,
q(k′∣k)=q(k∣k′)=(2m)−1.
Число соседей у каждого состояния одинаково:
(233)=233⋅32=528.
Граф состояний связен: любую перестановку раскладывают в произведение
транспозиций, а значит, от любого ключа можно добраться до любого другого не
более чем за m−1 обменов. Локальность хода и связность графа — два условия,
без которых цепь либо не сдвинется, либо не дойдёт.
Целевая плотность на ключах:
π(k)∝exp{βL(k−1y)}.
Коэффициент β задаёт обратную температуру. Переход k→k′ принимается
с вероятностью
a(k,k′)=min(1,exp{β[L(k′−1y)−L(k−1y)]}).
Правило выбрано так, чтобы выполнялось детальное равновесие:
π(k)P(k,k′)=π(k′)P(k′,k)⟹πP=π.
Нормировочная сумма по m! ключам не нужна: она сокращается, как в общем
алгоритме Метрополиса–Хастингса. Именно поэтому метод вообще
применим: посчитать Z=∑kexp{βL(k−1y)} нельзя ни при каких
вычислительных ресурсах, а отношение π(k′)/π(k) считается за
микросекунду.
Почему жадный подъём проигрывает
Проверим утверждение экспериментом на реальных данных. Берём 20 фрагментов по
400 знаков из отложенных уроков, шифруем каждый случайной перестановкой и даём
двум алгоритмам одинаковый бюджет — 20 000 предложений. Жадный подъём
принимает только улучшения. Цепь с температурой иногда идёт вниз.
Медианная доля верно расшифрованных знаков: 0,15 у жадного подъёма и 1,00 у
цепи. В 18 случаях из 20 цепь нашла ключ с более высоким баллом; медианный
отрыв по баллу — 880 нат. Доля принятых предложений: 11,9 % у цепи против
0,27 % у жадного подъёма — тот почти сразу перестаёт двигаться.
Рис. 68.2. Жадный подъём застревает, цепь переваливает через гребень
Слева: двенадцать запусков на одном шифротексте в 400 знаков. Красные — жадный
подъём: все шесть выходят на плато заметно ниже зелёной линии истинного ключа.
Синие — цепь Метрополиса с остыванием: три из шести доходят до уровня истины.
Справа: точность на 20 разных шифротекстах, медианы 0,15 против 1,00. Ниже
диагонали не оказалось ни одной точки.
Пересчитывать весь балл заново не обязательно: обмен пары (a,b) меняет лишь
те слагаемые, где встречается хотя бы одна из двух букв,
Картина типична для комбинаторной оптимизации: локальных максимумов много, и
почти все они плохи. Та же логика, что в уроке 21 про овраги и
локальные минимумы, но пространство здесь дискретное, и «шаг вниз» — не малое
смещение, а обмен двух букв.
Температура должна знать длину текста
Тонкость, о которой молчат учебники: масштаб ΔL растёт вместе с длиной
текста. Обмен двух частых букв в тексте из 400 знаков меняет балл на сотни
нат, а в тексте из 40 — на десятки. Поэтому фиксированная температура ведёт
себя по-разному на разных задачах: на длинном тексте цепь замерзает и
превращается в жадный подъём.
В наших опытах τ=0,03, γ=0,03, N=20000: цепь начинает
горячей и заканчивает почти жадной. Это уже не выборка из фиксированного
π, а имитация отжига — оптимизационная эвристика. Разницу надо называть
вслух: у отжига нет стационарного распределения, и все гарантии сходимости
MCMC к нему не относятся.
Как быстро цепь забывает старт: Добрушин
У цепи Маркова есть скорость перемешивания. Насколько быстро распределение
μt после t шагов приближается к целевому π — вопрос не философский,
а измеримый. Ответ на него дал Роланд Львович Добрушин, введя в 1956 году
коэффициент эргодичности переходного ядра P:
δ(P)=21s,s′maxu∑∣P(s,u)−P(s′,u)∣.
Это максимальное расстояние по вариации между строками матрицы переходов.
Основное неравенство Добрушина утверждает: применение ядра сжимает расстояние
между любыми двумя распределениями,
∥μP−νP∥TV≤δ(P)∥μ−ν∥TV,
откуда сразу следует геометрическая сходимость
∥μt−π∥TV≤δ(P)t∥μ0−π∥TV.
Позже Добрушин перенёс ту же идею на случайные поля: его условие
единственности гиббсовского состояния (1968) ограничивает влияние соседей
суммой, меньшей единицы. Наша π(k)∝exp{βL} — в точности
гиббсовская мера на конечном пространстве конфигураций, а обмен пары букв —
локальное обновление; поэтому язык Добрушина здесь родной.
Лаборатория: расшифровка вживую
Цепь Метрополиса взламывает подстановку
График шире экрана — листайте по горизонтали →
Загружается живая иллюстрация…
Модель языка в лаборатории настоящая: биграммы считаются прямо в браузере по
фрагменту этого учебника, а шифротекст — кусок урока 45, замкнутый случайной
перестановкой. Нажмите «запустить» и смотрите на нижнюю кривую Lt: она
растёт ступенями, потому что каждая пойманная частая буква чинит десятки
позиций сразу.
Три опыта, ради которых лаборатория и сделана. Первый: переключите режим на
«жадный» и убедитесь, что балл упирается в плато, а текст остаётся кашей.
Второй: верните «цепь», поднимите температуру до 0,1 — доля принятых
предложений вырастет, но балл перестанет расти: слишком горячая цепь бродит
и не оптимизирует. Третий: сократите текст до 60 знаков. Балл будет расти
бодро, а осмысленный текст так и не появится — 60 знаков едва дотягивают до
расстояния единственности.
Текст проявляется скачками
Один запуск на фрагменте в 600 знаков: доля верных позиций держится около
18 % первые две тысячи шагов, потом за полторы тысячи итераций поднимается до
58 %, ещё через шестьсот шагов до 75 %, а к концу достигает 100 % и больше не
меняется.
Рис. 68.3. Текст проявляется из шума почти мгновенно
Каждая строка — лучшая расшифровка на своём шаге; справа доля верных позиций.
До шага 2000 текст неотличим от шума; на шаге 3800 угадано 58 % позиций и
слова уже угадываются, а к концу фраза «точки мира считать соседними
сезонность требует круговой коор…» проступает целиком. Нижняя кривая показывает, что прогресс идёт ступенями:
удачный обмен пары частых букв чинит сразу много позиций.
Ступенчатость — не случайность реализации, а свойство задачи. Пока
пара о↔е перепутана, каждая пятая буква текста неверна, и правильный обмен
разом поднимает точность на десятки процентов. Промежуточных состояний между
«почти всё неверно» и «почти всё верно» мало.
Чего нельзя узнать в принципе
Возьмём фрагмент в 200 знаков. В нём встречается лишь 25 различных букв из 33
— строки ключа для остальных восьми текст не проверяет никак. Отсюда честный
потолок: точность ключа не может превысить 25/33, даже когда точность
текста равна 100 %. Медианное покрытие растёт медленно: 19 букв при 50
знаках, 27 при 200, 32 при 1000.
Двадцать независимых поисков на этом фрагменте дали 20 различных ключей — и
при этом медианную позиционную точность 0,99. Из 25 встретившихся букв 23
совпали в 90 % и более поисков, а две (й и х, по одному вхождению) кочуют
между почти равными по баллу расшифровками.
Сверху — сколько раз каждая буква встретилась в 200 знаках; снизу — как часто
её образ совпал у 20 независимых поисков. Буквы с шестью и более вхождениями (их 14)
угаданы в 91 % поисков, буквы с одним-двумя — лишь в 60 %. Красным помечены
две спорные: текст просто не содержит свидетельств, чтобы их различить.
Первая усредняет по буквам алфавита, вторая — по позициям текста, где частые
буквы имеют больший вес. Отсюда практическое правило отчёта: публиковать не «найденный ключ», а карту
уверенности — какие строки подтверждены многими запусками, какие спорны. Ровно
так же в уроке 46 мы отказывались от точечной оценки в пользу
интервала.
Максимум балла — не истина
Ещё одна честная оговорка. В 2 опытах из 20 найденный ключ получил балл выше,
чем истинный: на 200-знаковом фрагменте превышение составило 0,6 нат. Ничего
удивительного: L — балл модели, а не мера правды. Модель, обученная на
конечном корпусе, вполне может считать чуть более вероятной строку, немного
отличающуюся от оригинала.
argkmaxL(k−1y)=kиствобщемслучае.
Формально мы максимизируем не истинную вероятность, а сглаженную оценку по
конечному корпусу:
k=argkmaxt∑logpλ(xt∣xt−2,xt−1),x=k−1(y).
Это тот же зазор между правдоподобием и истиной, который мы обсуждали в
уроке 45: максимум правдоподобия — оценка, а не гарантия. Чем
короче текст, тем шире зона, где балл почти не различает конкурентов.
Диагностика без известного ответа
В настоящем шифре эталонного открытого текста нет. Значит, качество приходится
оценивать косвенно:
сравнивать лучшие баллы независимых запусков;
смотреть, совпадают ли наиболее частые пары ключа;
проверять правдоподобие на отложенной языковой модели;
измерять стабильность результата при изменении корпуса и сглаживания;
публиковать несколько конкурирующих расшифровок, если разрыв мал.
Можно зашифровать известные тексты и оценить долю правильно восстановленных
букв — так мы и делали в этом уроке. Это synthetic benchmark: он проверяет
алгоритм, но может быть легче исторических шифров с опечатками, именами и
необычной орфографией.
Именно этот сюжет и превратил взлом подстановки в учебный пример: задача
комбинаторная, целевая функция дешёвая, а результат видно глазами — редкое
сочетание в вычислительной статистике.
Корпус решает, какой язык «нормален»
Если обучить модель на статьях XXI века, она может плохо оценивать
дореволюционное письмо, диалект или программный код. Наш корпус — учебник по
информатике: в нём подозрительно часто встречаются слова «модель», «выборка»,
«вероятность». Для шифровки школьного сочинения это приемлемо, для перехвата
разговорной переписки — уже нет.
Полезный эксперимент: построить две триграммные модели, например на новостях
и на прозе, затем расшифровать один текст. Сопоставьте число правильных букв
и места расхождения ключей. Имена собственные и редкая лексика особенно
чувствительны к домену.
Модель должна обучаться только на открытом корпусе, не содержащем самого
исходного текста. Мы для этого разделили уроки: 01–40 в обучение, 41–50 в
проверку. Иначе длинные совпадения превращают расшифровку в поиск утечки, а
не в статистический вывод — та же утечка между обучением и проверкой, что и в
уроке 32; а если корпус подбирать, глядя на результат взлома, добавится
и переплата за просмотр кандидатов из урока 63.
Медианы и межквартильный размах по 12 опытам на реальных фрагментах. Униграммы
не поднимаются выше 0,39 при любой длине: сортировка по частоте не различает
и и т. Биграммы и триграммы взлетают там, где текст переваливает за
расстояние единственности: 0,22 при 50 знаках, 0,71 при 100 и 1,00 при 200.
Более сложная модель окупает разреженность только после этого рубежа.
Информация, модель и поиск — три разные причины неудачи
Успех расшифровки определяется тремя отдельными вещами, и путать их нельзя.
Формально причины входят в разные места. Информация решает, насколько остр
максимум; модель задаёт саму функцию L; поиск определяет, какое значение
Lнайдено=t≤NmaxL(kt)≤kmaxL(k)
мы вообще увидим за бюджет N шагов. Различить их можно экспериментом. Дайте алгоритму заведомо хорошую модель и
огромный бюджет: если при 50 знаках разные запуски всё равно дают разные
ключи, ограничение информационное — лечится только длиной перехвата. Уменьшите
число итераций, не трогая текст: если результат испортился, мешал поиск —
лечится температурой и рестартами. Смените корпус на другой жанр: если ответ
изменился, виновата модель.
От частотного анализа к современным моделям
Классический частотный анализ сопоставляет самые частые символы. MCMC
обобщает его: оценивает весь ключ через совместную статистику контекста и
умеет менять несколько гипотез последовательно. Пространство дискретно и
комбинаторно, но локальное предложение делает его проходимым.
Современная нейросетевая модель оценивала бы длинный контекст лучше и
опустила бы расстояние единственности почти вдвое — ещё в 1951 году Шеннон
экспериментально оценил энтропию английского текста для человека примерно в
один бит на знак — втрое меньше, чем даёт наша триграммная модель. Но её score
дороже вычислять, труднее калибровать и проще переоптимизировать: поиск
найдёт странные строки, которым сеть случайно назначает высокий балл. Переход
от триграмм к трансформеру не отменяет диагностику, а делает её
обязательной.
Что мы взяли из этого урока
Взлом подстановки — маленькая, но полная модель прикладного вывода. Есть
дискретное пространство гипотез, есть дешёвая целевая функция, полученная из
данных, есть локальный ход, делающий пространство проходимым, и есть три
независимые причины неудачи. Мы научились измерять каждую: избыточность языка
в битах говорит, сколько знаков нужно; кривая точности по длине показывает,
где начинается разрешимость; сравнение запусков отделяет поиск от информации.
Главный урок аккуратности: цепь оптимизирует балл, а не смысл. Максимум L
может стоять не там, где истина, и в наших опытах стоял не там дважды из
двадцати. Отчёт, который сообщает один ключ без карты уверенности и без числа
запусков, скрывает главное.
Следующий шаг курса переносит марковскую структуру из пассивного наблюдения в
управление: у переходов появятся действия и награды, а вместо
«где живёт цепь» мы будем спрашивать «как ей управлять».