Современные симметричные шифры, которыми мы пользуемся неявно, но повсеместно, появились в ходе своей многовековой эволюции, в ходе продолжительных и постоянных этапов собственного совершенствования. Каждый новый шаг улучшения приводил одновременно к разрушению старых уязвимых шифров и к порождению новых, более качественных и безопасных. Тем не менее, само разрушение старых алгоритмов всегда двояко свидетельствовало как об их недостатках, которые необходимо было искоренять, так и об их достоинствах, которые нужно было наследовать. В следствие этого, каждый новый, более качественный шифр, представлял собой количественный синтез старых, менее качественных алгоритмов шифрования.  Таким образом, для того, чтобы узнать как современные симметричные алгоритмы шифрования стали такими, какими мы их сейчас видим, нам необходимо углубиться в историю шифров, а именно — в классическую криптографию. Основной нашей целью будет являться выявление примитивов шифрования на базе классических шифров и реструктуризация современных шифров по их композиции. Это даст понимание того, что современные симметричные шифры появились не просто из пустого места, а из структур ранее созданных алгоритмов шифрования.  Данный материал также может быть полезен коллегам преподавателям по предмету КСЗИ (криптографические средства защиты информации) и непосредственно самим студентам при изучении классической и современной симметричной криптографии. По ходу статьи будут прикладываться программные коды на языке Си некоторых шифров классической криптографии. В конце данной статьи также будет указан список литературы по классической криптографии, с которым вы сможете ознакомиться. Если начать с самого начала, с понимания того, как мы пришли к такой жизни, как люди научились создавать современные блочные/поточные шифры, нам необходимо углубиться в историю, а именно во времена, когда криптография ещё не являлась наукой, а была порождением искусства — в классическую криптографию. Классическая криптография ныне является частью общей криптографии и представляет собой скорее исторический характер, нежели математический или информатический (современная криптография), относительно базисных наук. Таким образом, это говорит о том, что шифры которые будут описаны по ходу повествования, с большей долей вероятности не будут являться надёжными, и к ним нужно будет относиться исключительно как к экспонатам, играющим роль причины возникновения современных симметричных шифров. Эпоху классической криптографии можно датировать периодом: 3000 л.д.н.э — первая половина XX в.н.э.. Вторая половина XX века связывает себя с рождением криптографии как науки, где не малую роль сыграли следующие факторы: 1) Работа "Теория связи в секретных системах" (К. Шеннон), где были предложены базовые принципы шифров - конфузия и диффузия, было проведено математическое описание ранее существовавших шифров, доказано существование абсолютной криптостойкости на примере шифра Вернама; 2) Стандартизация шифра DES; 3) Появление нового раздела — асимметричной криптографии; 4) Информация о дешифровании Энигмы; 5) Появление криптографических хеш-функций; 6) Появление концепции ЭЦП; 7) Массовое применение в коммуникациях. Таким образом, всё что было в криптографии до второй половины XX века базировалось исключительно на необходимых мерах конфиденциальности передаваемой/хранимой информации, без признаков применения хеширования, ЭЦП, асимметричного распределения ключей и массового применения в коммуникации. В классической криптографии, в явном виде, существовало два класса шифров — подстановочные и перестановочные. Суть первых сводится к тому, что один символ или группа символов открытого текста заменяется на один символ или группу символов закрытого текста. Суть вторых сводится к тому, что открытый текст "перемешивается" или "перетасовывается" таким образом, что он становится в конечном счёте закрытым. Вследствие этого, основным отличием перестановочных шифров от подстановочных является использование в закрытом тексте тех же символов открытого текста, в ровно таком же количестве и такой же пропорции. Это можно представить в виде следующей схемы. Подстановочные и перестановочные шифры также делятся на подклассы. Подстановочные шифры содержат пять подклассов, а именно: 1) коды, 2) моноалфавитные, 3) омофонические, 4) полиалфавитные, 5) полиграммные. Перестановочные содержат всего один подкласс: 1) простые. Всю эту иерархию можно представить в виде следующей схемы. Являются самыми первыми методами шифрования в истории. Известно, что применялись в Древнем Египте, хоть и не в целях скрытия информации. Их суть заключается в замене (шифровании) целых слов на другие слова, группу символов или числа. Данный вид шифров можно видеть и в настоящем времени, где шпионы не говорят свои настоящие имена, а заменяют их псевдонимами. Ключевой особенностью кодов является существование кодовой книги по принципу "ключ-значение", например Алиса=Змея, Боб=Черепаха, Ева=Ящерица, а само сообщение может звучать так: "Змея-Змея, Ящерица вызывает Черепаху".  Коды могут также хорошо синтезироваться со стеганографией, то-есть не только шифровать сообщение, но и скрывать сам факт существования оригинального сообщения посредством другого (нейтрального) сообщения. Так например, сообщение "Я отнесу подарок часовщику в полдень" может трактоваться так: "Я положу бомбу у часовни в полночь". Если кодовая книга достаточно большая, то она может очень сильно искажать первоначальный смысл сообщения, "затмевая" истинное ложным. Хоть коды и представляют собой самый древний способ шифрования, тем не менее, при хорошо продуманной кодовой книге, результирующий шифр может оказаться сложно взламываемым даже в текущих реалиях.  При всём этом, стоит сказать, что коды не являлись основополагающими методами шифрования для развития классической криптографии, т.к. их основной проблемой являлась и продолжает являться прямая зависимость криптостойкости от размера кодовой книги. Для того времени это становилось (простите за мой каламбур) ключевой проблемой, потому как необходимо было иметь как минимум две копии одной и той же кодовой книги у двух людей на большой дистанции. Являются отправной и ключевой точкой отчёта развития классической криптографии. Самыми старыми представителями подобного подкласса являются шифр Атбаш (~ 500 л.д.н.э.), шифр Полибия (~ III в.д.н.э.) и шифр Цезаря (~ I в.д.н.э.). В отличие от кодов, шифрующих целые слова, как элементарную единицу, моноалфавитные шифры нацелены исключительно на посимвольное шифрование. Также как и коды, моноалфавитные шифры имеют прямую связь между открытой элементарной единицей (слово/символ) и закрытой (слово/число/символ). Данную связь мы будем называть 1к1, где например, если открытый символ A преобразуется в закрытый символом B, то он не может ещё и преобразовываться в закрытый символ C, D, E и т.д. И наоборот, если закрытый символ B был получен из открытого символа A, то он не может быть расшифрован как-либо иначе кроме этого же символа A. В качестве примера, часто приводят шифр Цезаря. Думаю вряд-ли кто-то с ним не знаком, если человек хоть когда-нибудь начинал увлекаться криптографией. Основной особенностью шифра Цезаря является его ключ, представленный числом сдвигов оригинального алфавита. Так например, предположим, что у нас присутствует ключ K=1 и сообщение M=HELLO, тогда шифрованный результат будет выглядить как IFMMP. Если ключ K=3, то сообщение становится равным KHOOR. Итого, количество всех возможных ключей в шифре Цезаря выражается мощностью алфавита |A| (количеством символов). Если это английский алфавит, то существует всего |A|=26 ключей, если русский, то |A|=33 ключа и т.д. При этом всегда присутствует ключ равный нулю, в итоге количество "нормальных" ключей равно |A|-1.  Часто те кто начинает изучать классическую криптографию, испытывает путаницу в понимании различия между подстановочными и перестановочными шифрами. Иногда (хоть и редко) можно услышать, что шифр Цезаря — это перестановочный шифр. Путаница возникает на моменте вышепоказанной схемы, где действительно происходит обычная перестановка алфавита. Тем не менее, перестановочным шифром является алгоритм, при котором все символы исходного текста также находятся в шифрованном тексте, в ровно такой же пропорции — постоянно, как бы вы часто не меняли ключ шифрования. В контексте же шифра Цезаря, алфавит — это не открытый текст, а полученный алфавит после сдвига — не шифротекст. Можно сказать, более обще, что алфавит в шифре Цезаря — это есть часть ключа, посредством которой мы шифруем все последующие сообщения.  Тем не менее, если подойти к проблеме с другой точки зрения и представить алфавит как открытый текст, то тут уже действительно применяется перестановочный шифр, результатом которого становится ключ для шифра Цезаря. Но само применение перестановочного шифра при генерации ключа для другого шифра (будь то подстановочного или перестановочного) не свидетельствует о том, что другой шифр становится также перестановочным. Файл encoder.h Файл encoder.c  Компиляция Запуск Результат исполнения  Теперь, хоть мы и рассмотрели шифр Цезаря в подробностях, он всё равно является лишь единичным случаем (реализацией) всех моноалфавитных шифров. Благо моноалфавитные шифры можно обобщить. Так например, наивысшая криптостойкость всех моноалфавитных шифров выражается в лице шифра простой подстановки. Можно также в равной степени сказать, что шифр простой подстановки — это и есть целый подкласс в лице моноалфавитных шифров, потому как посредством него могут быть выражены все другие моноалфавитные шифры, будь то шифр Атбаш, шифр Цезаря, шифр Полибия, шифр Бэкона, Аффинный шифр и т.д. Следовательно, если шифр простой подстановки будет обладать определённым рядом уязвимостей, то все они также будут наследоваться побочными шифрами. Ключом в шифре простой подстановки является сам алфавит, а точнее его подстановочная версия. Так например, предположим, что имеется подстановка, которая указана на схеме выше и открытое сообщение M=HELLO. Результатом шифрования станет зашифрованное сообщение C=ITSSG. В отличие от шифра Цезаря, здесь нет вообще никакой перестановки даже на уровне алфавита, потому как могут существовать символы в подстановочной алфавите, которых не существует в оригинальном, и наоборот. Так например, символа @ не существует в оригинальном алфавите, а символа B не существует в подстановочном алфавите.  Шифр простой подстановки поражает количеством всевозможных ключей, потому как таковое количество становится равным факториалу мощности алфавита |A|!. Для английского алфавита количество ключей равно |A|!=26!=403291461126605635584000000, для русского |A|!=33!=8683317618811886495518194401280000000. Если очень грубо выражать данное количество ключей через сложность вычисления в битовом представлении современных симметричных шифров, то получится, что для английского алфавита сложность составляет ~=288, а для русского ~=2122. Для сравнения с текущими реалиями, считается, что длина ключа в 120 бит является вычислительно надёжной к полному перебору подготовленным криптоаналитиком с огромными вычислительными ресурсами.  Но не нужно быть такими наивными. Вышеописанная сложность будет работать лишь при том условии, когда шифр является идеальным в том простом плане, что у него не существует более никаких других уязвимостей, кроме полного перебора. Тем не менее, шифр простой подстановки имеет ряд уязвимостей. Это можно даже доказать на априорных знаниях, где существуют другие методы шифрования, отличные от моноалфавитных. Если бы моноалфавитный шифр являлся бы надёжным, то другие шифры скорее всего бы даже не разрабатывались и не были бы так знамениты в своих применениях. Но всё же, для лучшего понимания уязвимостей, нужно исходить из апостериорных знаний. У шифра простой подстановки существует два основных вектора нападения — частотный криптоанализ и атака по маске. Первый вектор базируется на том факте, что у каждого алфавита, т.к. он естественный, существует некая избыточность символов, приводящая к тому, что одни символы в тексте встречаются гораздо чаще чем другие. Под текстом нам лучше понимать совокупность всех открытых текстов на выбранном языке. На практике конечно достаточно знать лишь несколько текстов с большим объёмом символов, чтобы выстроить частоту встречаемости каждого отдельного символа приближенную к частотам суммы всех текстов на данном языке. Второй вектор также базируется на факте избыточности символов в открытом тексте, но уже не на уровне каждого отдельного символа, как это предполагает частотный криптоанализ, а на уровне целой группы символов. Под группой символов могут выступать часто повторяемые слова, часто употребляемые приставки, суффиксы, предлоги, окончания, и т.д. В любом случае, лучше будет попрактиковаться на примере данных векторов нападения. Предположим, что у нас существует следующий шифротекст. Известно, что таковой закрытый текст был получен посредством моноалфавитного шифра. Значит это говорит о том, что сохраняется связь символов между открытым и закрытым текстами 1к1. В исторической действительности же люди понимали (хоть и не сразу), что всеразличные символы точки, двоиточия, запятые, пробелы, абзацы и т.д. могут сыграть плохую роль в скорейшем взломе (дешифровании) закрытого текста. Поэтому они исключались и сам шифртекст выглядил как сплошной набор закрытых символов. Тем не менее, для примера взлома вполне сгодится более легковесная и лёгкая версия.  1) Частотный криптоанализ Первое, что нам необходимо сделать — это вычислить частоты каждого отдельного символа в шифртексте. Для этого мы можем написать небольшую программу на Си, которая самостоятельно будет вычислять все частоты символов в закрытом тексте. Данная программа работает исключительно с символами ASCII, то-есть с английским алфавитом. Поэтому, если шифртекст будет написан на русском языке, то данную программу нужно будет переписать под поддержку кириллицы.  Получаем на выходе такие частоты. Здесь стоит помнить, что т.к. наш текст не сказать что большой, то и частоты могут перекрывать друг друга. Поэтому, при таком типе криптоанализа, становится необходимо иметь достаточно обширный текст, чтобы исключить как можно больше неопределённостей.  Теперь, второе, что нам необходимо сделать — это сравнить полученные частоты с оригинальными частотами символов английского алфавита.  Из сравнения мы видим, что (с большей долей вероятности) символ открытого текста E либо равен символу A закрытого текста, либо символу D закрытого текста. Оставшийся символ закрытого текста (A или D) должен будет также принадлежать (с большей долей вероятности) одному из первых оставшихся символов оригинального алфавита, то-есть к T, A, O, N или I. Делаем предположение, что символ E=D по большей частоте встречаемости. На самом деле мы также могли сделать предположение, что символ E=A), потому как расстояние частот между символами A и D невелико. Оставшийся символ A предполагаем следующему символу оригинального алфавита T, иными словами делаем предположение, что T=A. Теперь заменяем все символы A, D в шифротексте на E и T. Получаем следующий текст.  Третье, что мы делаем — это пытаемся найти в полученном тексте какие-либо похожие слова. Так например, очень часто попадается комбинация символов равная tFe. В английском алфавите, присутствует схожая комбинация и тоже часто встречаемая равная символам THE. Если наши первоначальные предположения на счёт символов T и E оказались верными, то скорее всего сопоставление H=F тоже окажется верным. Это можно проверить на примере косвенных сопоставлений. Так например, в тексте есть ещё комбинация tFeH которая может быть равна THEN или THEM, также слово tFeVe, которое может быть равно THERE или THESE, и tFZt может быть равно THAT. Таким образом, H=F скорее всего точно является верным, т.к. мы нашли достаточно много косвенных совпадений. Заменяем F на H, параллельно заменяем Z на A, и пытаемся поразмыслить теперь над H = N или M, а также V = R или S. Плюс к этому, в полученном тексте начинает вырисовываться слово attaQCU из которого мы можем предположить ATTACKS. Если это верно, то мы расскрываем дополнительные сразу три символа C, K, S, а также ставим однозначную связь V=R (потому как символ S нам стал известен).   Из полученного результата мы также начинаем видеть ещё новые слова, например rKsks может быть равно risks (это подкрепляется также thKs => this), Neek может быть равно week (это подкрепляется также Nhat => what и Nas => was), reasPO может быть равно reason (это подкрепляется также RrPcess => process и tP => to, и eYeO => even). Все полученные комбинации также пытаемся заменить. Если будет что-то неверно, может попытаться вернуться назад. Получаем уже такой текст, где его большая часть читается даже без последующего анализа и сравнения. Мы открыли следующие символы: t, h, e, p, o, i, n, t, o, r, v, w, c, k, s. В сумме 15, что представляет уже большую часть символов английского алфавита, более 50%. Далее, можете продолжить дешифровывать текст самостоятельно. Книга — Секреты и ложь (Б. Шнайер) P.S. На данном моменте (или даже раньше) могло возникнуть сомнение, что этот текст я уже знал и поэтому так легко его дешифровывал. На самом деле так и было, примерно пол года назад, пока я не удалил все открытые тексты. На моём ПК (а точнее на сервере) остались лишь самостоятельные работы для студентов, но без оригинальных текстов. Так что можно сказать, что это дешифрование было спонтанным. 2) Атака по маске Данный вид криптоаналитической атаки схож по своему методу на частотный криптоанализ, но лишь с тем отличием, что таковой смотрит не на частоты встречаемости каждого отдельного символа, а на частоты встречаемости целых слов в тексте, или на частоты появления приставок, суффиксов, предлогов, окончаний и т.д. Следовательно, он заменяет два первых этапа частотного криптоанализа на этап сравнивания групп символов. В некой степени данный вид атаки является более простым и быстрым, если вы знакомы с языком, на котором написан текст. Предположим, что у нас также существует тот самый текст. Забудем о том, что мы его смогли успешно дешифровать.   Первое, на что наше внимание теперь должно быть приковано, так это к структуре самого текста. Нам нужно найти наибольшее количество закономерностей. Так например, группа символов AFD очень часто встречается в начале предложений, что может быть равно группе символов THE английского алфавита. Если это так, то мы сразу сможем узнать три правильных символа. Далее, моё внимание приковывают предложения с вопросами, потому как в английском языке вопросительные предложения строятся немного по другому в сравнении с обычными, а также имеют вспомогательные слова. Предположим, что в этих предложениях могут существовать слова WHAT, WHY, WHERE, HOW и т.д. Под WHAT может подходить шифртекст NFZA, т.к. никакие четыре символа не совпадают и находятся в вопросительном предложении. Далее очень часто в тексте встречается одиночный символ Z, который может быть равен символу A в английском тексте, который также подкрепляет гипотезу о WHAT=NFZA. После того, как мы открыли несколько слов, нам будет легче продолжиать взламывать шифртекст, но уже посимвольно, как ранее мы это делали в частотном криптоанализе. На данном этапе, нам известны уже следующие символы: t, h, e, a, w. Если взглянуть вновь на частотный криптоанализ, то нам для этого текста было достаточно всего двух открытых символов для взлома всего текста, а именно T и E. Так что с полученным результатом также вполне реально доломать весь оставшийся шифртекст. Библиотека encoder, а также способ компиляции находятся во вложении с кодом шифра Цезаря. Результат исполнения  В итоге, на заре окончания использования моноалфавитных шифров уже было всем известно, что таковой подкласс шифров ни в коем случае нельзя считать надёжным. Хоть у него и вправду может существовать огромное количество ключей, тем не менее, у него существует и ряд значительных уязвимостей, позволяющих взламывать закрытый текст за считанные минуты. Люди того времени уже понимали на чём зиждется данная уязвимость, а именно на связи 1к1. Если такую связь скрыть, размыть или исключить, то частотный криптоанализ и атака по маске будут уже не такими эффективными орудиями в руках криптоаналитиков. Представляют собой развитие моноалфавитного подкласса, позволяющего шифровать один и тот же символ несколькими способами, тем самым образуя новый тип связи 1кN. Иными словами, теперь становится возможным отождествлять символ A одновременно с несколькими символами, как например B, C и D. При шифровании символа A случайным образом выбирается символ из данного множества, что как следствие, может порождать закрытый текст вида BCDBD из открытого текста AAAAA. Тем не менее, остаётся и в омофоническом шифре "наследие" моноалфавитного, а именно расшифрование становится всегда однозначным относительно множества закрытых символов. Так например, если A способен преобразовываться в B, C или D, то B, C и D не могут расшифровываться никак иначе как символ A. Поэтому связь и является однонаправленной. Представителем подобных шифров является книжный шифр (не путать с книжным шифром из стеганографии). Главной целью омофонических шифров является сокрытие частот встречаемости каждого отдельного символа посредством их выравнивания. Так предположим, что существует алфавит всего из трёх символов {A, B, C}. Предположим, что в текстах на этом языке, A=X (где X - шифросимвол) встречается в 50% случаев, а символы B=Y и C=Z в 25% случаев каждый. В моноалфавитном шифре частота символа X всегда бы сохранялась и была равна частоте символа A открытого текста, из-за чего могла бы применяться атака частотным криптоанализом. Омофонический же шифр размывает частотную закономерность посредством "деления" символа на несколько символов шифртекста. Так например, если A разделить на два символа Q и W, и при шифровании с равной и случайной вероятностью выбирать один из них, то символы Q и W, вместе с символами Y и Z будут иметь вероятность встречаемости по 25% каждый. Из этого следует, что применять на шифртекст с правильной омофонической заменой атаку частотного криптоанализа более становится невозможно. Омофонический шифр, искореняя атаку частотным криптоанализом, вдобавок и повышает количество возможных ключей при полном переборе. На первый взгляд кажется, что вот он, идеальный шифр, у которого более не существует уязвимостей, а полный перебор просто неосуществим на практике. Но вы ведь ещё не забыли об атаке по маске? Хоть атака по маске и представляет собой некий частный случай атаки частотного криптоанализа, но за счёт того, что атака по маске анализирует закономерность на уровне групп символов, то и векторы нападения начинают немного отличаться. Эта атака становится губительной для омофонических шифров. Основная суть атаки сводится к тому, что омофонический шифр (пока не берём в расчёт книжный шифр) имеет тенденцию повторять шифросимволы, хоть и с равной вероятностью. Если открытый текст будет достаточно объёмным, то таким же объёмным будет и шифртекст. Из-за объёмности в тексте будут часто повторяться одни и те же группы символов. Так например, предположим, что существует английский алфавит, где нашей маленькой задачей будет являться сокрытие огромного количества групп символов THE омофоническим шифром. И в чём же заключается проблема? Проблема заключается в том, что количество всех возможных комбинаций омофонических подстановок ограничено, что может приводить рано или поздно к повторам одних и тех же групп. Если T = (# или B), H = (2 или O), E = (& или 5), то в лучшем (именно в лучшем) случае группа символов THE повторит себя спустя 23=8 раз, т.к. для такой группы символов существует именно 8 разных способов написания: #2&, #25, #O&, #O5, B2&, B25, BO&, BO5. Таким образом, криптоаналитик всё равно будет видеть частоты встречаемости, хоть и не каждого отдельного символа, но именно повторяющихся групп символов. Но теперь представьте, что если количество омофонических подстановок для каждого отдельного символа растёт очень быстро? Так например, если для каждого символа существует 8 подстановок, то комбинация THE (опять таки в лучшем случае) повторится спустя 83=512 использований. Если выбрано 32 подстановки, то 323=32 768 и т.д. Можно сказать, что не словами едины и криптоаналитик начнёт искать также закономерности повторений не только в словах, но и в приставках, суффиках, предлогах, окончаниях и т.п. А теперь предположим, что если каждый отдельный зашифрованный символ будет обладать своей уникальной омофонической заменой? Иными словами, если вы будете шифровать много одинаковых символов AAA...AAA, то всегда будете получать разные символы #$8...0JD. Можно конечно сказать, что количество символов в какой-либо кодировке ограничено, но ничто не мешает шифровать символы числами, подобия (31)(222)(1)...(3123)(4454)(910). В таком случае шифрования, какие бы то ни было атаки окажутся бессмысленными, будь то частотный криптоанализ, т.к. частоты всегда будут априори выравнены из-за неповторяемости каждого отдельного символа, будь то атака по маске, т.к. не будет связей групп между собой.  Но существует ли такой омофонический шифр? Существует — это книжный шифр. Его суть крайне проста и может быть описана следующим алгоритмом действий. Взять случайную книгу, статью или какой-либо массивный текст. Взять открытый символ оригинального текста. Открыть книгу и найти там этот символ. Записать в качестве шифрсимвола (страницу/строку/позицию) этого символа. Зачеркнуть этот символ в книге и никогда больше его не применять. Перейти на пункт 2, если нужно продолжить шифрование. Таким образом, единственная атака на подобный вид омофонических шифров сводится к нахождению оригинальной книги (ключа) для возможности расшифрования. Иными словами, единственной атакой на книжный шифр становится атака полным перебором всех возможных ключей. С одной стороны действительно можно сказать, что это и есть идеальный шифр, но стоит учесть несколько факторов: 1) книги, статьи, текста нужно как-то уметь передавать, т.к. они могут быть достаточно большими в размерах; 2) если брать теоретически все возможные книги в мире и на основе них высчитывать количество ключей, то получится всего ~=130 000 000 возможных ключей (https://www.vesti.ru/article/2053203), что составляет примерно всего ~=227 сложности перебора. Что с первым, что со вторым пунктом действительно можно поспорить. Так например, по первому пункту, можно выбирать малую книгу, статью или какой-либо другой текст, но итоговый шифртекст также будет малым. Также со вторым пунктом, можно учитывать не только книги, но и статьи, а также всеразличные другие тексты, но 1) это может непозволить шифровать большие сообщения и 2) оставшиеся большие тексты также будут ограничены в количестве, что не на сильно повысит итоговое количество ключей.   Программная реализация более простая, чем оригинальный шифр, потому как не учитывает строки и страницы, а просто печатает позиции символов. Результат исполнения  В результате, наивысшая криптостойкость омофонических шифров становится противоречивой сущностью, потому как количественная характеристика ключа начинает идти в открытое противоречие с качеством криптостойкости самого алгоритма шифрования. Таким образом, с одной стороны, появляется уязвимость атаки по маске, но при этом исключается атака перебором, с другой стороны исключается уязвимость атаки по маске, но появляется возможность полного перебора ключей. В конечном счёте приходится выбирать определённые компромиссы. Являются дальнейшим развитием моноалфавитных, а также омофонических шифров, представляя новый тип связи NкN. В отличие от омофонических шифров, способных представлять множественную вариативность исключительно операции шифрования, полиалфавитные шифры способны представлять двунаправленную связь между открытым и закрытым текстом. Так например, становится возможным замена символа A на B или C и одновременно с этим, символ B может расшифровываться как символ A или C (такое же утверждение справедливо для символа C). Примерами подобных шифров являются диск Альберти, шифр Гронсвельда, шифр Виженера, шифр Вернама, шифр Тритемиуса.  Разберём для начала классический полиалфавитный шифр — шифр Виженера. Данный алгоритм шифрования представляет собой более общий случай шифра Цезаря, переводя ключ-число в ключ-строку. Каждый отдельный символ ключ-строки исполняет ту же самую функцию, что и ключ-число в шифре Цезаря для конкретно выбранного символа. Так например, предположим, что у нас существует ключ K=QWE и сообщение M=HELLO. Само шифрование осуществляется таким образом, что ключ начинает кодироваться в числовое представление, где символ ключа становится позицией оригинального алфавита. Так например, если бы ключ был равен ABC...XYZ, то он бы закодировался в 0,1,2,...,23,24,25 соответственно (нумерация начинается с нуля). Таким образом, ключ QWE становится равен 16,22,4. Далее, начинается этап дублирования ключа до тех пор, пока он не станет больше или равен количеству символов в открытом тексте. Следовательно, продублированный ключ станет равен 16,22,4,16,22. В конечном итоге, при шифровании происходит наложение ключа с открытым текстом, а операцией наложения становится сдвиг накладываемого символа на количество позиций накладываемого ключа, иными словами шифр Цезаря. Всё это можно описать следующим образом. Шифр Виженера также может быть представлен таблицей NxN, где N - количество символов алфавита. Так, на примере английского алфавита, это выглядит следующим образом. Чтобы зашифровать определённый символ с определённым ключом, необходимо будет найти его на пересечении данной матрицы. Если взять наш ключ K=QWE и сообщение M=HELLO, а также предположить, что слева по вертикали будут находиться символы ключа, а сверху по горизонтали символы сообщения, то на пересечении символов мы будем находить те же шифросимволы: Q+H=X, W+E=A, E+L=P, Q+L=B, W+O=K. Итого, XAPBK, что и требовалось ожидать.  Шифр Виженера при этом также является частным случаем более общего описания полиалфавитных шифров. Так например, в более абстрактном виде для полиалфавитного шифра не важен как таковой конкретный моноалфавитный шифр. Наиболее абстрактная, и как следствие, общая версия описания полиалфавитных шифров может быть представлена множественным применением шифров простой подстановки с разными ключами.  Может ложно показаться, что шифр Виженера является надёжным шифром, т.к. относится к типу связи NкN. Тем не менее, полиалфавитные шифры в массе своей наследуют уязвимости моноалфавитных шифров, но не таким явным образом. Так например, если взять вышеописанный случай шифрования с ключом K=QWE и сгруппировать полученный шифртекст C по группам символов типа (C[0], C[3], C[6], ..., C[3k]), (C[1], C[4], C[7], ..., C[3k+1]) и (C[2], C[5], C[8], ..., C[3k+2]), где значение в скобках - это нумерация символа в шифртексте C, то каждая группа будет обладать собственным смещением. Так группа шифросимволов (C[0], C[3], C[6], ..., C[3k]) обладает смещением равным 16, группа (C[1], C[4], C[7], ..., C[3k+1]) обладает смещением равным 22, а группа (C[2], C[5], C[8], ..., C[3k+2]) обладает смещением равным 4. Иными словами, каждая группа символов по отдельности была зашифрована просто шифром Цезаря с определённым ключом. И так, если нам известны все эти группы, то мы становимся способными применить частотный криптоанализ на каждую группу по отдельности, восстанавливая открытые символы. После того, как был применён частотный криптоанализ на каждую группу происходит этап слияния всех групп вновь в собранный текст. Если все или большая часть частот успешно подошла, то можно легко будет прочитать открытый текст.  Также в шифре Виженера остаётся уязвимость к атаке по маске. Так например, если текущая позиция ключа при шифровании открытого текста начинает совпадать с уже продублированным блоком открытого текста, который был зашифрован с точно такой же позицией ключа, то шифрованным результат данного блока будет аналогичным. По такому признаку как раз и становится возможным определять количество групп по шифртексту, или вернее сказать количество непродублированных символов ключа.  Библиотека encoder, а также способ компиляции находятся во вложении с кодом шифра Цезаря. Результат исполнения  Хоть такие уязвимости в шифре Виженера и присутствуют, но они прямолинейно зависят от 1) количества символов ключа; 2) качества ключа. Начнём с количества. Основной проблемой дешифрования (взлома) шифра Виженера является определение количества групп или, иными словами, количество непродублированных символов ключа. Для малой длины ключа и большого открытого текста найти группы не составит труда. Тем не менее, если ключ будет достаточно длинным, то найти повторяющиеся группы может быть проблематичным занятием. Если же длина ключа будет равна длине сообщения, то таковых групп и не будет существовать вовсе, и как следствие будет невозможным применение атаки по маске, для нахождения повторяемых групп символов, и атаки частотного криптоанализа, для дешифрования групп символов. В таком случае криптоаналитик полагается на существование некачественного, предсказуемого ключа, зависимого от контекста определённых событий. Например, началом ключа может быть какая-то дата, стих, прогноз погоды и т.д. P.S. Некоторые полиалфавитные шифры, подобия шифра Тритемиуса, могли быть также взломаны посредством линейного криптоанализа, анализирующего статистическкую закономерность между открытым и закрытым текстом, на основе каких-либо алгебраический закономерностей. Такая уязвимость возникает из особенности шифра Тритемиуса, где ключом является функция, аргументом которой становится позиция шифруемого символа. Но такой метод криптоанализа появился лишь в современной криптографии, а потому о таковом следует говорить лишь в пределах его зарождения и последующего использования.  На основе всех вышеописанных критериев создаётся шифр Вернама, как определение наивысшей криптостойкости всех полиалфавитных алгоритмов шифрования. Шифр Вернама можно рассматривать как частный случай шифра Виженера с тремя правилами: Необходимо использовать ключ, длина которого будет больше или равна длине сообщения. В данном контексте не позволяется как-либо дублировать или дополнять ключ. Он должен быть цельным. В качестве ключа нужно использовать случайную и равновероятную последовательность символов. Иными словами, если нам необходимо зашифровать какой-либо символ, то под него мы должны сгенерировать случайный символ. Вероятность угадать какой символ будет получен при генерации должна составлять 1/N, где N - количество символов в алфавите. Недопускать использование одного и того же ключа для двух разных сообщений. Иначе, это приведёт к уничтожению фактора случайности, то-есть к ликвидации второго пункта.  Шифр Вернама является не только представителем полиалфавитных шифров, не только их выражением наивысшей криптостойкости, но и шифром с теоретической (абсолютной) криптостойкостью. Иными словами, если в шифре Вернама были соблюдены все три критерия, то порождённый им шифртекст невозможно взломать ни за какое время и никакими вычислительными ресурсами. Я постараюсь привести простым языком доказательство абсолютной криптостойкости шифра Вернама.  Так например, Клод Шеннон в своей работе "Теория связи в секретных системах" говорит о теоретической криптостойкости с позиции того, что апостериорные знания полученные вследствие дешифрования (взлома) шифртекста должны оставаться равны априорным, до непосредственного криптоанализа. На этой основе давайте посмотрим шифр Вернама. Предположим, что у нас имеется следующий шифртекст GHX. Из априорных знаний нам известно, что здесь либо было зашифровано слово DOG с вероятностью 50%, либо слово CAT с вероятностью 30%, либо слово RAT с вероятностью 20%. Также нам известно, что был выбран случайный и равновероятный ключ, длина которого равна длине самого сообщения. Это говорит о том, что вероятность угадывания правильного ключа составит 1/(263)=1/17576. Количество ключей невелико, мы можем перебрать каждый ключ и попытаться дешифровать сообщение, но беда заключается в том, что при переборе найдётся ключ K=DTR, который приведёт к сообщению DOG, ключ K=EHF, который приведёт к сообщению CAT и ключ K=PHF, который приведёт к сообщению RAT. Иными словами, во всём множестве ключей будут априори существовать ключи под все предполагаемые варианты. Таким образом, нам ничего не даст полный перебор всех возможных ключей, а это лишь свидетельствует о том, что апостериорные знания (после попытки криптоанализа) остались равными априорным знаниям (до его попытки). Являются представителями развития кодов и моноалфавитных шифров, преобразующих не единичные символы и не целые слова в шифрованный результат, а целые блоки символов открытого текста в блоки закрытого текста. Можно сказать данный подкласс шифров является неким промежуточным или синтезирующим звеном между подклассами моноалфавитных шифров и кодов, усложняющих преобразования посредством стремления к кодам и увеличивающих количество вариантов шифрования в сравнении с моноалфавитными шифрами. В качестве примера, группа символов AB может шифроваться только как группа CD, в ровно такой же степени как и CD может расшифровываться исключительно и только как AB. Тем не менее, если один ранее использованный символ группы будет шифроваться, но уже с другим, то результатом преобразования может стать совершенно другая пара, например AC может быть преобразовано в EZ. В данном контексте сохраняется связь 1к1, но данный подкласс шифров становится более трудным по той лишь простой причине, что для взлома необходимым становится анализ частот не каждого отдельного символа, а целой группы символов. В качестве примера полиграммных шифров можно привести шифр Порты, шифр Плейфера, шифр Хилла.  Разберём полиграммные шифры на примере шифра Плейфера, как наиболее классического представителя полиграммных шифров. Шифр Плейфера является биграммным шифром, то-есть шифрует по два символа за раз, парно. В отличие от шифра Хилла, который может шифровать биграммами, триграммами, ..., N-граммами, шифр Плейфера шифрует исключительно биграммами.  Преобразование открытого текста в закрытый посредством шифра Плейфера происходит посредством выстраивания ключ-матрицы из ключа-строки. Предположим, что у нас существует английский алфавит, количество символов которого равно 26. Чтобы поместить эти 26 символов в матрицу, потребуется либо матрица 5x6, либо матрица 6x6 с дополнительными символами. В исторической же действительности брали матрицу 5x5, заменяя символ J символом I. Иными словами данные символы становились аналогичны друг другу при шифровании. При расшифровании они восстанавливались исходя из контекста самого сообщения. Ключ-строка играла роль первичного заполнения ключ-матрицы, посредством которого перемешивался оригинальный английский алфавит. Так например, предположим что у нас существует ключ-строка K=PARROT. В таком случае нам необходимо сконкатенировать к PARROT весь английский алфавит. Получим на выходе следующую строку: PARROTABCDEFGHIJKLMNOPQRSTUVWXYZ. Теперь нам нужно удалить все повторяющиеся символы начиная с конца данной строки, а также не забыть удалить символ J. В итоге, мы получаем такую строку PAROTBCDEFGHIKLMNQSUVWXYZ. Теперь создаём матрицу 5x5 и вносим туда получившуюся строку слева-направо, сверху-вниз. P A R O T B C D E F G H I K L M N Q S U V W X Y Z Как только была сгенерирована матрица-ключ мы можем приступать к шифрованию сообщений. Предположим, что мы шифруем сообщение M=HELL. У шифр Плейфера существует ряд условностей, которые необходимо выполнить с открытым сообщением ещё до момента шифрования. Первое — разбить текст на биграммы, таким образом HELL преобразуется в (HE, LL). Второе — начиная с первой биграммы идти по порядку и как только появляется биграмма с одинаковыми символами, необходимо вставить между двумя символами нейтральный символ. В истории классической криптографии таким символом являлся X. После вставки нужно вновь выстроить биграммы и продолжить проверку повторяющихся символов в биграммах. Третье — если последняя биграмма неполная, то-есть не имеет парного символа, тогда нужно дополнить её нейтральным символом. В следствие этого, у нас получатся уже такие биграммы (HE, LX, LX).  P.S. В данном алгоритме существует одна погрешность, которая может допустим при программной реализации привести к бесконечному циклу, а именно если биграмма будет состоять из символов XX или если последняя биграмма будет неполной и состоять только из символа X. В таком случае, алгоритм будет всегда пытаться либо вставить между двумя XX ещё X, либо будет добавлять к X ещё X и приведёт вновь к зацикленности вставления X между двумя XX. На практике же (в истории) такой проблемы не встречалось по той лишь простой причине, что два символа XX просто не могут существовать рядом в английских словах. Таким образом, для программных реализаций может сойти использование второго нейтрального символа, допустим Y при таком случае. Далее, как только мы получили биграммы открытого текста (HE, LX, LX), мы можем приступать к шифрованию. Шифр Плейфера предлагает нам три основных правила для шифрования сообщений. Если два символа одной биграммы находятся на одной строке и на разных столбцах матрицы, то необходимо сдвинуть позицию текущих символов на одну позицию вправо и взять символы стоящие под новыми позициями в качестве шифрованной биграммы. Предположим, если бы мы шифровали биграмму HK, то её результатом по нашей ключ-матрице стала бы биграмма IL (H=>I, K=>L). Если два символа одной биграммы находятся на одном столбце и на разных строках матрицы, то необходимо сдвинуть позицию текущих символов на одну позицию вниз и взять символы стоящие под новыми позициями в качестве шифрованной биграммы. Предположим, если бы мы шифровали биграмму DQ, то её результатом по нашей ключ-матрице стала бы биграмма IX (D=>I, Q=>X). Если два символа одной биграммы находятся на разных строках и столбцах матрицы, то необходимо прочертить прямоугольник, где символы биграммы будут являться его углами, и взять противоположные углы. Символы на противоположных углах прямоугольника будут являться шифром биграммы. Предположим, если бы мы шифровали биграмму AS, то её результатом по нашей ключ-матрице стала бы биграмма NO (A=>N, S=>O) или ON (A=>O, S=>N). Неоднозначность третьего пункта связана с нестандартизацией шифра Плейфера как такового. Такая же ситуация может происходить со множеством других алгоритмов шифрования классической криптографии (например — шифр вертикальной перестановки). Таким образом, абоненты в лице отправителя и получателя должны были заранее договориться о том, как следует шифровать биграммы находящиеся на разных строках и столбцах — либо по вертикали, либо по горизонтали.  Предположим, что мы будем придерживаться вертикальной шифрования при существовании третьего пункта. Таким образом, наши биграммы (HE, LX, LX) открытого текста будут преобразованы в биграммы (CK, ZI, ZI) закрытого текста. У шифра Плейфера существует ряд недостатков. Так например, при заполнении ключ-матрицы, последние символы часто находятся в алфавитном порядке и чисто теоретически можно предположить, исходя из частоты использования символов, что X, Y, Z скорее всего в конце как были, так и остались в неизменной позиции. Таким образом, нам становится возможным определение нескольких символов ключ-матрицы сразу на раннем этапе. Также, если будут шифроваться биграммы по первому или второму правилу с использованием одинаковых символов, например биграммы (CE, CF), то в качестве результата мы получим схожее соответствие (DF, DB). Иными словами, на данном примере символ C не зависит от изменения парного ему символа.  Помимо вышеописанных недостатков, на нашем примере также видны ещё классические уязвимости, унаследованные моноалфавитными шифрами. Так например, биграммы LX всегда одинакого будут шифроваться как биграммы ZI. Также на основе атаки по маске мы можем продолжать находить часто повторяемые последовательности групп биграмм в зашифрованном тексте. Эти классические уязвимости всегда присутствуют в полиграммных шифрах и не исчезают при каких-либо частных и более конкретных реализациях. Ещё одним и наверное самым простым представителем биграммных шифров является шифр Порты. Его можно представить в виде следующей таблицы. Здесь стоит понимать, что сам алфавит может быть перемешан, а потому количество ключей увеличится и будет равно N!, где N - количество символов в алфавите. Библиотека encoder, а также способ компиляции находятся во вложении с кодом шифра Цезаря. Результат исполнения  Криптостойкость полиграммных шифрова прямо пропорционально зависит от количества шифруемых символов за раз в качестве N-граммы. Чем больше символов будет шифроваться одновременно, тем сложнее осуществлять атаки частотного криптоанализа и атаки по маске. Следовательно, наивысшей криптостойкостью полиграммных шифров становится размер равный L-грамме, где L - количество символов в открытом тексте, при условии, что изменение одного символа L-граммы будет приводить к изменению большинства других символов (лавинный эффект). Предполагает собой полноценный и монолитный механизм, алгоритм перемешивания символов открытого текста с целью получения закрытого. По большей части это всё определение, а потому к такому подклассу шифров можно относить большинство известных перестановок, подобия маршрутной, вертикальной, решета Кардано, шифра Скитала (шифр Древней Спарты).  Так представим простую перестановку на примере вертикальной перестановки. У таковой перестановки ключом может быть строка или просто набор чисел. Количество символов (или чисел) ключа порождает размер блока, в который будут записываться блоки сообщения такого же размера. Если длина ключа равна длине сообщения, то происходит обычная математическая перестановка. Предположим, что у нас существует ключ K=KEY и сообщение M=HELLOWORLD. В таком случае, мы создаём матрицу 3x4, где первое число - это размер ключа (количество символов), а второе число - это количество используемых блоков по 3 для вместимости всего сообщения M. Вписывает в матрицу слева-направо, сверху-вниз сообщение. Если остаются пустые ячейки, то заполняем их либо нейтральным символов (подобия того же X), либо случайными символами. K E Y H E L L O W O R L D X X После заполнения всех ячеек, мы сортируем ключ KEY по алфавитному порядку, тем самым получая новый ключ EKY. Вместе с сортировкой символов ключа сортируем и столбцы под ними находящиеся. В итоге получае следующее. E K Y E H L O L W R O L X D X Результат шифрования выписываем снизу-вверх, справа-налево. Получаем на выходе следующий шифртекст C=XLWLDOLHXROE. Вышеописанный алгоритм является лишь одним из возможных вариантов. Так например, можно вписывать/выписывать символы снизу-вверх, слева-направо, а можно также слева-направо, сверху-вниз, также можно сортировать ключ в порядке убывания и т.д. Это шифр классической криптографии, стандартизации как таковой на данном этапе ещё не существует. При этом стоит заметить, что шифры простой перестановки никак не скрывают частоты символов открытого текста, в отличие от подстановочных шифров. Такое свойство играет двоякую роль, потому как с одной стороны применять частотный криптоанализ, в том привычном виде, становится бессмысленным. Частотный криптоанализ хорошо работает на классе подстановочных шифров, но не перестановочных. С другой стороны, сама перестановка всё же сохраняет в открытой форме символы открытого текста и если хорошо знать язык, на котором текст был написан, то нам становится возможно исключать определённые конструкции, которых просто не может существовать в оригинальном тексте. Так например, в русском тексте Ь не может существовать в начале слова, символ Н часто находится в сумме с другим Н, Й часто находится в конце слова, Ы существовует в массе своей с Й, Е или Н и т.д. Языковые конструкции избыточны, а потому могут приводить к дополнительным способам дешифрования, даже сложных перестановок.  Результат исполнения В данном программном случае, чтение при шифровании происходило сверху-вниз, слева-направо. Криптостойкость шифров простой перестановки увеличивается удлинением размера ключа, а соответственно и удлинением блоков перестановки. Таким образом, если шифр простой перестановки зависит от ключа, а длина ключа определяется длиной N входного текста, то количество всевозможных ключей будет равно N!. Так, на примере шифра вертикальной перестановки, количество всевозможных ключей при длине ключа равной 3 составляет 3!=6, а при длине ключа равной 4 составляет 4!=24 и т.д. Исходя из всего этого, наивысшая криптостойкость определяется схожим образом с полиграммными шифрами. Помимо всех перечисленных выше шифров, в истории криптографии существовал ещё ряд композиционных шифров, как вид объединения нескольких алгоритмов. В качестве примера, таковыми являлись шифр ADFGVX (шифр Полибия+вертикальная перестановка), Сложные перестановки (простая+простая перестановка) и шифровальная машина Энигма (парный шифр+полиалфавитный шифр). Тем не менее, их вид композиции в некой степени разный, неоднородный, потому как ADFGVX соединяет одновременно два класса, в то время как Энигма и Сложная перестановка объединяют два подкласса только из одного класса. В дальнейшем, чтобы понимать о каком конкретно типе объединения будет идти речь, введём различие на уровне терминологии, где для сочетания двух классов подстановка+перестановка мы будем использовать термин Композиционный (ADFGVX), а для сочетания двух подклассов одного класса — Комбинированный («Энигма», Сложная перестановка).  Комбинированные шифры легко могут быть рассмотрены на примере Сложной перестановки. Она представляет собой обычное сочетание, комбинирование нескольких простых перестановок. Это может быть как вертикальная+вертикальная перестановки с разной длиной ключа (желательно, чтобы НОД(a, b) = 1 (НОД = наибольший общий делитель), где a, b - длины блоков первой и второй перестановок), так и для примера маршрутная+решето Кардано. Теоретически количество сложений может быть неограничено, а потому и всевозможных комбинаций в таковом подклассе может существовать бесконечное множество.  При наилучшей композиции сложная перестановка приводит к произведению количества ключей простых перестановок. Так например, если одна простая перестановка имеет длину ключа равную 7, а другая равную 13, то итоговое количество ключей будет равно 7!*13!=31384184832000 всевозможным перестановкам, что в свою очередь представляет сложность ~=241.  Тем не менее, полученная длина ключа может быть урезана многократно, если криптоаналитик сможет найти один из делителей сложной перестановки. Иными словами, если он поймёт, что длина одной перестановки равна 7, то длина ключа сложной перестановки упадёт до 13!=6227020800. Таким образом, сложная перестановка продолжает наследовать внутри себя критерий наивысшей криптостойкости простой перестановки, что логично, ведь таковая сложность является лишь комбинацией простоты. Ещё, в качестве примера комбинированных шифров, вы можете рассмотреть устройство шифровальной машины «Энигма», а также её реализацию на языке программирования Си — тут. P.S. Стоит заметить, что свойство комбинирования существует не у всех шифров. Так например, бессмысленно комбинировать несколько моноалфавитных шифров, потому как выходом объединения станет обычный моноалфавитный шифр. Также нет смысла комбинировать несколько полиалфавитных шифров с одинаковой длиной ключа, потому как это приведёт ровно также к созданию одного полиалфавитного шифра с такой же длиной ключа. Из этого следует, что само комбинирование нескольких шифров должно происходить лишь на основе объединения разных длин ключей. P.P.S. Стоит также заметить, что у композиционных шифров такой проблемы, как у комбинированных, не наблюдается. И действительно, если существует два шифра, где один из них подстановочный, другой - перестановочный, то даже располагая одной и той же длиной ключа для обоих шифров, их результат композиции всё равно улучшит итоговую криптостойкость.  Пока что мы рассмотрели лишь классы и подклассы алгоритмов классической криптографии, не затрагивая при этом современную симметричную криптографию. Тем не менее, кто уже знаком с современной криптографией может увидеть достаточно много "деталей", которые были унаследованы современными шифрами.  UPD. Раздел со сложной перестановкой был заменён разделом комбинированных шифров. Из классификации шифров классической криптографии сложная перестановка была удалена. Таковые действия были связаны с противоречивостью самой классификации. Так например, если сложная перестановка относится к классу перестановок как отдельный подкласс, то почему не существует сложной подстановки (шифровальная машина Энигма)? И даже если бы таковая сложная подстановка существовала как отдельный подкласс, то что бы она нового приносила в классическую криптографию? Что бы её принципиально отличало от множества других шифров? Если само комбинирование подстановочных шифров становится отличием, то такое же свойство существовало бы и у перестановочных шифров, что неминуемо бы приводило к размытию грани между сложной подстановкой и сложной перестановкой из двух разных классов. Поэтому наилучшим решением стало удаление сложной перестановки как отдельного подкласса и создание новой главы о комбинированных шифрах. Взломщики кодов. Д. Кан Книга шифров. Тайная история шифров и их расшифровки. С. Сингх Основы классической криптологии. М. Адаменко История криптографии. А. Бабаш, Г. Шанкин История криптографии в Западной Европе в раннее новое время. И. Русецкая  Криптограф, Программист