Добавлен: 01.04.2023
Просмотров: 90
Скачиваний: 2
• Lisp - содержит примитивы системы .
• User - умалчиваемый пакет прикладных программ и данных пользователя .
• Keyword - содержит ключевые слова всех встроенных функций и функций, определяемых пользователем .
• System - зарезервированный пакет для системных целей.
Значительной переработке и расширению в CommonLISP подверглись средства ввода-вывода и передачи информации. Для эффективной организации различных обменов с внешней средой введена концепция потоков, позволяющих осуществлять одно- и (или) двухстороннюю передачу информации. Для потоков предусмотрен набор базовых функций. В диалекте различают символьные и двоичные потоки. В первом случае передача осуществляется по байтам, а во втором - целыми числами. Кроме стандартных потоков пользователь имеет возможность создавать и использовать собственные потоки. В дополнение к указанным типам данных CommonLISP имеет ряд специфических классов объектов:
⁕ Хэш-таблицы, обеспечивающие эффективный способ доступа к данным по ключу;
⁕ READ-таблицы, обеспечивающие управление обработкой информации поступающей из входного потока Лисп-системы, и некоторые другие.
Такое множество имеющихся в диалекте различных типов данных, с одной стороны, развеивает существующее ошибочное представление о языке LISP как о средстве обработки только символьной информации, а с другой - наличие мощных средств манипулирования типами данных существенно усложняет его. Этот диалект оставлен открытым: принципиальным является то, что осталась возможность в будущем, когда подойдет время и будет достигнуто согласие, добавить новые средства и методы. CommonLISP не является готовой программной системой в том же смысле, что и Интерлисп, поскольку вопросы среды в основном оставлены открытыми. В стандарте не определено, каким должен быть редактор или другие вспомогательные средства. Сказано лишь в самом общем виде, каким образом они вызываются. Для того чтобы обеспечить быстрое развитие, среда и инструментальные средства еще не затронуты стандартизацией, и поэтому есть возможность создавать различные среды для различных целей. CommonLISP не определяет также и интерфейс пользователя.
В CommonLISP на современном этапе не включены даже средства объектного программирования, хотя и определены необходимые для этого базовые механизмы (замыкание и др.). Таким образом, объекты можно реализовать на Лиспе. Но уже ведется работа по стандартизации средств и форм объектного программирования. В CommonLISP много внимания уделено практическим требованиям, и, вероятно, поэтому не все его черты эстетичны и чисты. Несомненно, что и другие LISP -системы будут использоваться в дальнейшем, и их также необходимо развивать. CommonLISP предназначен не только для работы со списками или символьной обработки. Он является универсальным языком программирования, включающим в себя особенно хорошие средства для численных вычислений, управления данными и связи. На CommonLISP можно с одинаковым успехом писать программы в традиционных операторном, процедурном, фразовом стиле, а также и в свойственных LISP стилях. В языке содержатся предпосылки для использования различных способов и стилей программирования, таких как операторное, функциональное, макропрограммирование, программирование, управляемое данными, и продукционное программирование, а также средства, необходимые для логического и объектного программирования и реализации других средств более высокого уровня. Можно смело сказать, что CommonLISP содержит почти все, что на сегодняшний день могут дать другие известные языки программирования, и, кроме того, он предусматривает средства для расширения языка.
Пример 1.
- Выбираем два простых числа: p = 3557, q = 2579.
- Вычисляем их произведение: n = p · q = 3557 · 2579 = 9173503.
- Вычисляем функцию Эйлера: φ(n) = (p-1) (q-1) = 9167368.
- Выбираем открытый показатель: e = 3.
- Вычисляем секретный показатель: d = 6111579.
- Публикуем открытый ключ: (e, n) = (3, 9173503).
- Сохраняем секретный ключ: (d, n) = (6111579, 9173503).
- Выбираем открытый текст: M = 127.
- Вычисляем шифротекст: P(M) = Me mod n = 10223mod 9173503 = 116.
- Вычислить исходное сообщение: S(C) = Cd mod n = 1166111579mod 9173503 = 1022.
Пример 2.
- Выбираем два простых числа: p = 79, q = 71.
- Вычисляем их произведение: n = p · q = 79 · 71 = 5609.
- Вычисляем функцию Эйлера: φ(n) = (p-1) (q-1) = 5460.
- Выбираем открытый показатель: e = 5363.
- Вычисляем секретный показатель: d = 2927.
- Публикуем открытый ключ: (e, n) = (5363, 5609).
- Сохраняем секретный ключ: (d, n) = (2927, 5609).
- Выбираем открытый текст: M = 23.
- Вычисляем шифротекст: P(M) = Me mod n = 235363mod 5609 = 5348.
- Вычислить исходное сообщение: S(C) = Cd mod n = 53482927mod 5609 = 23.
2. Математические и алгоритмические основы решения задачи
Первым этапом любого асимметричного алгоритма является создание пары ключей: открытого и закрытого и распространение открытого ключа «по всему миру». Для алгоритма RSA этап создания ключей состоит из следующих операций:
1). Выбираются два простых числа p и q
2). Вычисляется их произведение n (=p*q)
3). Выбирается произвольное число e (e<n), такое, что
НОД (e, (p-1) (q-1))=1,
то есть e должно быть взаимно простым с числом (p-1) (q-1).
4). Методом Евклида решается в целых числах уравнение
e*d+(p-1) (q-1)*y=1.
Здесь неизвестными являются переменные d и y – метод Евклида как раз и находит множество пар (d, y), каждая из которых является решением уравнения в целых числах.
5). Два числа (e, n) – публикуются как открытый ключ.
6). Число d хранится в строжайшем секрете – это и есть закрытый ключ, который позволит читать все послания, зашифрованные с помощью пары чисел (e, n).
Как же производится собственно шифрование с помощью этих чисел:
Отправитель разбивает свое сообщение на блоки, равные k=[log2(n)] бит, где квадратные скобки обозначают взятие целой части от дробного числа.
Подобный блок может быть интерпретирован как число из диапазона (0; 2k-1). Для каждого такого числа (назовем его mi) вычисляется выражение
ci=((mi)e) mod n.
Блоки ci и есть зашифрованное сообщение Их можно спокойно передавать по открытому каналу, поскольку операция возведения в степень по модулю простого числа, является необратимой математической задачей. Обратная ей задача носит название «логарифмирование в конечном поле» и является на несколько порядков более сложной задачей. То есть даже если злоумышленник знает числа e и n, то по ci прочесть исходные сообщения mi он не может никак, кроме как полным перебором mi.
А вот на приемной стороне процесс дешифрования все же возможен, и поможет нам в этом хранимое в секрете число d. Достаточно давно была доказана теорема Эйлера, частный случай которой утвержает, что если число n представимо в виде двух простых чисел p и q, то для любого x имеет место равенство
(x(p-1)(q-1)) mod n = 1.
Для дешифрования RSA-сообщений воспользуемся этой формулой. Возведем обе ее части в степень
(-y): (x(-y)(p-1)(q-1)) mod n = 1(-y) = 1.
Теперь умножим обе ее части на x:
(x(-y)(p-1)(q-1)+1) mod n = 1*x = x.
А теперь вспомним как мы создавали открытый и закрытый ключи. Мы подбирали с помощью алгоритма Евклида d такое, что
e*d+(p-1) (q-1)*y=1,
то есть
e*d=(-y) (p-1) (q-1)+1.
Следовательно, в последнем выражении предыдущего абзаца мы можем заменить показатель степени на число (e*d). Получаем
(xe*d) mod n = x.
То есть для того чтобы прочесть сообщение ci=((mi)e) mod n достаточно возвести его в степень d по модулю m:
((ci)d) mod n = ((mi)e*d) mod n = mi.
На самом деле операции возведения в степень больших чисел достаточно трудоемки для современных процессоров, даже если они производятся по оптимизированным по времени алгоритмам. Поэтому обычно весь текст сообщения кодируется обычным блочным шифром (намного более быстрым), но с использованием ключа сеанса, а вот сам ключ сеанса шифруется как раз асимметричным алгоритмом с помощью открытого ключа получателя и помещается в начало файла.
Скорость работы алгоритма RSA
Как при шифровании и расшифровке, так и при создании и проверке подписи алгоритм RSA по существу состоит из возведения в степень, которое выполняется как ряд умножений.
В практических приложениях для открытого (public) ключа обычно выбирается относительно небольшой показатель, а зачастую группы пользователей используют один и тот же открытый (public) показатель, но каждый с различным модулем. (Если открытый (public) показатель неизменен, вводятся некоторые ограничения на главные делители (факторы) модуля.) При этом шифрование данных идет быстрее чем расшифровка, а проверка подписи – быстрее чем подписание.
Если k – количество битов в модуле, то в обычно используемых для RSA алгоритмах количество шагов необходимых для выполнения операции с открытым (public) ключом пропорционально второй степени k, количество шагов для операций частного (private) ключа – третьей степени k, количество шагов для операции создания ключей – четвертой степени k.
Методы «быстрого умножения» – например, методы основанные на Быстром Преобразовании Фурье (FFT – Fast Fourier Transform) – выполняются меньшим количеством шагов; тем не менее они не получили широкого распространения из-за сложности программного обеспечения, а также потому, что с типичными размерами ключей они фактически работают медленнее. Однако производительность и эффективность приложений и оборудования реализующих алгоритм RSA быстро увеличиваются.
Алгоритм RSA намного медленнее чем DES и другие алгоритмы блокового шифрования. Программная реализация DES работает быстрее по крайней мере в 100 раз и от 1,000 до 10,000 – в аппаратной реализации (в зависимости от конкретного устройства). Благдаря ведущимся разработкам, работа алгоритма RSA, вероятно, ускорится, но аналогично ускорится и работа алгоритмов блокового шифрования.
Функциональные модели и блок-схемы решения задачи
Функциональные модели и блок-схемы решения задачи представлены на рисунках 1 – 6.
Условные обозначения:
- P и Q – случайные простые числа;
- N – произведение простых чисел P и Q;
- PHI – значение функции Эйлера;
- E – взаимно простое число с PHI;
- PRIVATE_KEY – секретный ключ;
- LST – список простых чисел;
- NUM – число для шифрования / дешифрования;
- I, IO, I1, J, JO, R, L – рабочие переменные.
Рисунок 1 – Функциональная модель решения задачи для функции SIMPLE_NUMBER
Рисунок 2 – Функциональная модель решения задачи для функции ENCRYPT
Рисунок 3 – Функциональная модель решения задачи для функции DECODING
Рисунок 4 – Функциональная модель решения задачи для функции RSA
Рисунок 5 – Блок-схема решения задачи для функции DISTINCT_SIMPLE_NUM
Рисунок 6 – Блок-схема решения задачи для функции ALG_ EUCLID
Программная реализация решения задачи
; ПОИСК ВЗАИМНО ПРОСТОГО ЧИСЛА
(DEFUN DISTINCT_SIMPLE_NUM (NUM PH)
(DO
()
((< NUM PH) NUM)
; TRUNCATE – ЦЕЛОЧИСЛЕННОЕ ДЕЛЕНИЕ
(SETQ NUM (TRUNCATE NUM 2))
)
(DO
()
; GCD – НАИБОЛЬШИЙ ОБЩИЙ ДЕЛИТЕЛЬ
((EQL (GCD NUM PH) 1) NUM)
; REM – ОСТАТОК ОТ ДЕЛЕНИЯ
(IF (EQL (REM NUM 2) 0) (SETQ NUM (+ NUM 1)))
(SETQ NUM (+ NUM 2))
)
)
; ГЕНЕРИРУЕМ СЛУЧАЙНОЕ ПРОСТОЕ ЧИСЛО
(DEFUN SIMPLE_NUMBER ()
; ОБЪЯВЛЕНИЕ ПЕРЕМЕННОЙ
(DECLARE (SPECIAL LST))
; СПИСОК ПРОСТЫХ ЧИСЕЛ
(SETQ LST ' (2 3 5 7 11 13 17 19 23 31 37 41 43 47 53 61 67 71 73 79 83 89 97 101))
; ВЫБИРАЕМ СЛУЧАЙНОЕ ЧИСЛО ИЗ СПСКА
(NTH (RANDOM (– (LENGTH LST) 1)) LST)
)
; РАСШИРЕННЫЙ АЛГОРИТМ ЕВКЛИДА
(DEFUN ALG_EUCLID (X Y)
; – ОБЪЯВЛЕНИЕ ПЕРЕМЕННЫХ–
(DECLARE (SPECIAL I))
(DECLARE (SPECIAL I0))
(DECLARE (SPECIAL I1))
(DECLARE (SPECIAL J0))
(DECLARE (SPECIAL J1))
(DECLARE (SPECIAL R))
(DECLARE (SPECIAL L))
;–
(IF (EQL X 1) (SETQ X (+ X Y))
; ИНАЧЕ
(PROGN
(SETQ I0 0)
(SETQ I1 1)
(SETQ L Y)
(SETQ R (REM L X))
(SETQ J0 (TRUNCATE L X))
(SETQ L X)
(SETQ X R)
(SETQ R (REM L X))
(SETQ J1 (TRUNCATE L X))
(SETQ L X)
(SETQ X R)
(DO
(())
((<= R 0) R)
(SETQ R (REM L X))
(SETQ I (– I0 (* I1 J0)))
(IF (< I 0) (SETQ I (- Y (REM (* -1 I) Y))) (SETQ I (REM I Y)))
(SETQ I0 I1)
(SETQ I1 I)
(SETQ J0 J1)
(SETQ J1 (TRUNCATE L X))
(SETQ L X)
(SETQ X R)
)
(SETQ I (– I0 (* I1 J0)))
(IF (< I 0) (SETQ I (FLOOR (- Y (REM (* -1 I) Y)))) (SETQ I (FLOOR (REM I Y))))
I
)
)
)
; РЕАЛИЗАЦИЯ АЛГОРИТМА RSA
(DEFUN RSA ()
; – ОБЪЯВЛЕНИЕ ПЕРЕМЕННЫХ–
(DECLARE (SPECIAL N))
(DECLARE (SPECIAL E))
(DECLARE (SPECIAL PHI))
(DECLARE (SPECIAL PRIVATE_KEY))
(DECLARE (SPECIAL P))
(DECLARE (SPECIAL Q))
;–
; ВЫБИРАЮТСЯ ДВА ПРОСТЫХ ЧИСЛА
(SETQ P (SIMPLE_NUMBER))
(SETQ Q (SIMPLE_NUMBER))
; ВЫЧИСЛЯЕМ ИХ ПРОИЗВЕДЕНИЕ