Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
delphi / песни о паскале.pdf
Скачиваний:
63
Добавлен:
26.03.2016
Размер:
5.16 Mб
Скачать

Глава 24 Криптография

Говорят, что хороший разведчик стоит целой дивизии. Ещё бы! Ведь лишенный секретов противник почти безоружен. Но вот умолкли пушки, а разведка не спит, — у мирного времени свои тайны: коммерческие и технические секреты. Впрочем, если секретов нет, их можно придумать, — почему бы нам не поиграть в шпионов? Приятно сознавать, что «отмыленное» приятелю письмо никто, кроме вас двоих, не прочтет, — надо лишь зашифровать его. Придумана уйма способов шифрования, есть даже наука об этом — криптография; сейчас и мы коснемся краешка этой премудрости.

Секреты Юлия Цезаря

Римскому полководцу Юлию Цезарю выпали лихие времена: письмо, отправляемое им с гонцом в отдаленный уголок империи, могло стать добычей недругов, — ведь на дорогах было неспокойно. Это надоумило Юлия шифровать свои письма. В чем заключался метод полководца?

Цезарь просто-напросто заменял одни буквы другими путем кругового сдвига алфавита на несколько позиций. На рис. 54 показано превращение букв при сдвиге алфавита на две позиции. Буква «А» становится буквой «В», буква «Б» — буквой «Г» и так далее. Двум последним уготовано превратиться соответственно в буквы «А» и «Б». Такое шифрование превращает письмо в дикую абракадабру!

А Б В Г . . . Э Ю Я

А Б В Г

. . .

Э Ю Я А Б

Рис. 54 – Принцип шифрования Юлия Цезаря

Как расшифровать её? Очень просто — сдвинуть буквы в обратную сторону. Но надо знать количество сдвигов — это число называют ключом шифра (в примере на рисунке ключ шифра равен двум). Разумеется, что ключ шифра и метод шифрования знали лишь двое: получатель письма и сам Юлий Цезарь.

Пойдем и мы вслед римскому полководцу, — создадим программу для зашифровки текстового файла и его расшифровки. Скажу прямо: задача непростая, а потому решать её будем в два этапа. Вначале освоим шифрование отдельной строки, а уж потом замахнемся на файл. Но начнем с шифрования отдельного символа.

154

Глава 24

Криптография

Суть проблемы

Зашифровать строку — значит зашифровать каждый её символ. Будь у нас готовая функция шифрования символа, задача решалась бы вмиг. Так займемся ею и начнем с заголовка. Дадим нашей функции имя Encrypt — «шифровать», она должна принимать исходный символ и возвращать другой, зашифрованный. Значит, заголовок функции может быть таким:

function Encrypt (X: char): char;

Теперь сосредоточимся на теле функции и рассмотрим известные нам приёмы. Один из них состоит в применении каскада условных операторов:

if X=’А’

then Encrypt:=’В’

else if X=’Б’

then Encrypt:=’Г’

else . . .

Насколько удачно это решение? Прикинем количество вложенных операторов в этой лесенке. В русском алфавите 33 буквы, если взять заглавные и строчные, то получится 66. А если надумаем шифровать ещё и латинские буквы, и цифры и знаки препинания, то наберется около двух сотен символов. Такая лесенка условных операторов растянется на несколько этажей!

Не прибегнуть ли к оператору выбора CASE? Тогда тело функции будет намного проще:

case X of

’А’: Encrypt:=’В’;

’Б’: Encrypt:=’Г’;

. . .

end;

Обратите внимание, что метками оператора CASE здесь служат символы, — скоро вы узнаете, почему такое возможно. Этот вариант очевидно лучше первого, хотя две сотни меток — тоже не подарок. Но главное неудобство в ином: при изменении ключа шифра придется переписать все ветви оператора CASE, а это, согласитесь, скучно. Не поискать ли иного решения, простого и гибкого?

О кодировании символов

Первые компьютеры принесли инженерам массу неудобств. Взять хотя бы ввод и вывод данных. Дисплеи, принтеры и звуковые карты — тогда никто не слышал о них! Результат размышлений цифрового мозга высвечивался лампочками

155

Глава 24

Криптография

на инженерной панели ЭВМ, и в эту двоичную цветомузыку был посвящён лишь узкий круг мудрецов. Со временем изобрели простые принтеры, способные печатать лишь цифры, а затем и более совершенные — для печати букв и других символов. Как действуют подобные устройства?

Процессор компьютера, как известно, оперирует с числами. А людям подавай то текст, то картинку. Как связать одно с другим? Здесь инженеры вспомнили об алфавите. Ведь буквы в нём упорядочены, а значит, каждой букве можно сопоставить число; например, букве «А» — 1, «Б» — 2 и так далее. Такое сопоставление называют кодированием, оно и решает проблему представления символов. Намерившись напечатать некоторый символ, компьютер передает его код на принтер, а уж принтер знает, как поступить с этим числом. При вводе с клавиатуры происходит обратное преобразование: нажатие клавиши заставляет клавиатуру отправить в процессор код соответствующего символа.

Итак, символы внутри компьютера кодируются числами. Мы посчитали, что общее количество букв, цифр и других знаков составляет более двухсот. Инженеры не поскупились и отвели для кодирования символов 256 чисел — от 0 до 255 включительно. Почему именно 256, а не 300 или 500?

Дело в том, что в двоичной системе счисления 256 — это круглое число, оно равно двойке в восьмой степени (если вам знакомо слово «байт», то речь о нём). Так был создан алфавит для компьютеров, он включает буквы, цифры, знаки препинания и управляющие символы, — последние выполняют специальные действия с печатающим устройством, например, перевод на следующую строку.

Понятно, что можно придумать несметное количество вариантов кодирования символов. Желая добиться взаимопонимания между техническими устройствами разных изготовителей, инженеры договорились о единой системе кодирования. Теперь она известна под именем ASCII (читается «аски») — American Standard Code for Information Interchange — американский стандартный код для обмена информацией. Со временем этот стандарт стал международным. Ныне в ходу несколько стандартов кодирования, один из них (для MS-DOS) представлен в приложение И.

Все кодируемые символы разбиты на три группы. Первую составляют управляющие символы с кодами от 0 до 31. Их названия пока вам мало о чем скажут, обратите внимание лишь на символы с кодами 10 и 13, — они служат для разбивки текста на строки.

Вторую группу составляют символы с кодами от 32 до 127, — здесь собран весь латинский алфавит, цифры и основные знаки. Коды латинских букв следуют в порядке латинского алфавита, причем разница между кодами одноименных заглавных и строчных букв составляет 32.

Наконец, в третьей группе собраны русские буквы, символы псевдографики (применяются для рисования таблиц) и редко используемые знаки. Коды

156

Глава 24

Криптография

большинства русских букв тоже следуют в порядке русского алфавита, но некоторые выпадают из этой последовательности. К тому же, разница между кодами заглавных и строчных русских букв не всегда составляет 32.

Заметьте также, что символы русского и латинского алфавитов со схожими начертаниями (такие, как «А», «В», «Р») представлены разными кодами!

Чудесные превращения

Итак, символы в компьютере представлены своими кодами, то есть числами. А с числами работать легко: для превращения кода одного символа в код другого надо лишь прибавить либо вычесть некоторое число — шифрующий ключ.

Но как превратить символ в число и наоборот, — число в символ? Ведь это данные разных типов. Паскаль поможет вам своими встроенными функциями. Преобразовать число в символ можно либо функцией CHR, которая изначально присутствовала в языке, либо её современным аналогом по имени CHAR, которым я иногда буду пользоваться в дальнейшем. Обе функции принимают число, а возвращают символ, вот их объявления:

function Chr(arg : integer) : char;

function Char(arg : integer) : char;

Случайно ли, что имя функции CHAR совпадает с именем типа данных? Нет, ведь на самом деле обе эти функции ничего не делают! Они лишь подсказывают компилятору, что число в скобках — это код символа. И всё! С такими «ненастоящими» функциями мы ещё встретимся, их применяют для преобразования типов данных. Вот как можно напечатать нескольких символов с их кодами.

var n: integer; begin

for n:=40 to 50 do Writeln(n,' ', Chr(n))

end.

Для обратного преобразования — символа в число — применяют другую «ненастоящую» функцию по имени ORD (от ORDER — «порядковый номер»). Cейчас компиляторы предлагают и её аналог по имени Byte. Функция действительно возвращает порядковый номер символа в таблице ASCII, вот её заголовок:

function Ord(arg : char) : integer;

Воспользовавшись ею, мы тоже можем напечатать символы с их кодами.

157

Соседние файлы в папке delphi