Сравнение криптографических средств языков программирования
Содержание
Введение
Наше время часто называют переходным от индустриальной цивилизации к цивилизации преимущественно информационной. Вследствие этого роль накопленных и обработанных знаний постоянно растет. Появление и стремительное развитие компьютерных сетей обеспечило эффективные способы передачи данных и быстрый доступ к информации, как для отдельных люднй, так и для крупных организаций. Однако известно, что локальные и глобальные компьютерные сети могут представлять угрозу для безопасности данных, особенно при отсутствии мер защиты от несанкционированного доступа.
По мере становления информационного общества средства защиты превращаются в один из основных инструментов, поскольку они обеспечивают конфиденциальность, секретность, авторизацию, корпоративную безопасность, возможность осуществления электронных платежей и множество других важных элементов современной жизни. В связи с этим наличие встроенных механизмов защиты информации и эффективность их работы в прикладных системах стали определяющими факторами при выборе потребителями оптимального решения.
Надлежащий уровень защиты может быть обеспечен с помощью криптографических методов. Математическая криптография возникла как наука о шифровании и о криптосистемах. В классической модели системы секретной связи имеются два участника, которым необходимо передать секретную (конфиденциальную) информацию, не предназначенную для третьих лиц. Обеспечение конфиденциальности, защиты секретной информации от внешнего вмешательства является одной из главных задач криптографии.
К защите информации можно подходить по-разному. Можно попытаться создать абсолютно надежный и недоступный другим канал связи. К сожалению, достичь этого сложно, по крайней мере на современном уровне развития науки и техники, поскольку существующие методы и средства передачи информации одновременно дают возможность несанкционированного доступа к ней. Так же можно использовать общедоступные каналы связи и при этом скрыть сам факт передачи информации. Этим направлением занимается стеганография, но применяемые здесь методы не гарантируют должного уровня конфиденциальности. Можно использовать общедоступный канал связи, но передавать данные в преобразованном виде, чтобы восстановить их мог лишь адресат. Разработкой методов преобразования информации, обеспечивающей ее шифрование, и занимается криптография.
Любая современная криптосистема работает по определенной методологии и использует следующие компоненты:
- алгоритм шифрования (один или более), который можно выразить в виде математических формул;
- ключи, используемые указанными алгоритмами шифрования;
- система управления ключами;
- незашифрованный (открытый) текст;
- зашифрованный текст (шифротекст).
Пример схемы методологии шифрования с использованием ключей представлен на рисунке 1.
Рисунок 1 - Схема шифрования
Наличие встроенных механизмов защиты информации в прикладных системах все чаще становится определяющим фактором при их выборе потребителями, о чем хорошо знают все разработчики программных средств. Однако работы по созданию и тестированию криптографической защиты требуют существенных финансовых затрат. Кроме того, необходимы квалифицированные сотрудники, в частности криптографы и программисты с математическим образованием. Все это в значительной степени определяет качество разработки и успех реализации универсальных интерфейсов.
Многие
фирмы, в том числе крупнейшие
системные интеграторы, применяя криптографическую
защиту в своих прикладных системах, пошли
по пути реализации универсальных интерфейсов.
В их задачи входит предоставление приложению
широкого набора возможностей по вызову
криптографических сервисов, что обеспечивает
гибкость системы и определенную ее независимость
от алгоритмов. В результате такого подхода
разработчикам программного обеспечения
нет необходимости задумываться над тем,
какие именно алгоритмы криптографической
защиты будут реализованы в конечном продукте
— используются лишь интерфейсы вызовов
функций защиты, созданных сторонними
производителями. Примером может служить
фирма Sun Microsystems, предлагающая разработчикам
программного обеспечения язык Java с широким
набором интерфейсов, реализующих основные
криптографические алгоритмы и протоколы.
1 Классификация
криптографических алгоритмов
В качестве основного критерия классификации криптографических алгоритмов используется тип выполняемого над исходным текстом преобразования. Классификация по этому критерию представлена на рисунке 2.
Рисунок 2 – Общая классификация криптографических алгоритмов
Тайнопись предполагает, что отправитель и получатель производят над сообщением преобразования, известные только им двоим. Сторонним лицам неизвестны выполняемые алгоритмом изменения над открытым текстом, что и является гарантией нераскрываемости данных на этапе анализа.
В противовес тайнописи, криптоалгоритмы с ключом построены на принципе, что алгоритм воздействия на передаваемые данные известен всем сторонним лицам, но он зависит от некоторого параметра, который держится в секрете – «ключа», который известен только двум лицам, участвующим в обмене информацией. Стойкость шифра определяться только секретностью ключа, т.е. криптоаналитику могут быть известны все детали алгоритма шифрования и дешифрования, но неизвестно, какой ключ использован для шифрования данного текста. В настоящее время криптография занимается исключительно алгоритмами с ключами.
Криптосистемы с ключом делятся на симметричные и асимметричные системы шифрования. Модель симметричной системы шифрования представлена на рисунке 3.
Рисунок 3 – Обобщенная модель симметричной системы шифрования
Отличительной чертой симметричных алгоритмов шифрования является наличие одного ключа шифрования – k, который должен быть известен только отправителю и получателю сообщения. Отправитель при помощи ключа k шифрует сообщение, получатель дешифрует полученный шифротекст ключом k. Криптоаналитик может перехватить шифротекст Y, передаваемый по открытым каналам связи, но, так как он не знает ключа, задача вскрытия шифротекста является очень трудоемкой.
Асимметричная система шифрования работает по схеме, представленной на рисунке 4.
Рисунок 4 – Обобщенная модель асимметричной системы шифрования
Отличительной особенностью асимметричных алгоритмов является наличие пары ключей шифрования: открытого kот, который передается второй стороне по незащищенному каналу связи и поэтому может быть известен криптоаналитику, а также закрытого kзак, который известен лишь одному человеку (получателю сообщения) и держится в секрете. Пара ключей обладает тем свойством, что сообщение, зашифрованное на одном из ключей, может быть расшифровано только на другом ключе.
В зависимости от размера блока шифруемой информации криптоалгоритмы делятся на блочные и поточные шифры. Единицей кодирования в потоковых шифрах является один бит. Результат кодирования не зависит от прошедшего ранее входного потока. Схема применяется в системах передачи потоков информации, то есть в тех случаях, когда передача информации начинается и заканчивается в произвольные моменты времени и может случайно прерываться. Для блочных шифров единицей кодирования является блок из нескольких байтов. Результат кодирования зависит от всех исходных байтов этого блока.
Еще одним критерием классификации криптоалгоритмов является тип выполняемых преобразований над блоками открытого текста. По этому критерию криптоалгоритмы разделяют на подстановочные и перестановочные. В перестановочных шифрах блоки информации не изменяются сами по себе, но изменяется их порядок следования, что делает информацию недоступной стороннему наблюдателю. Подстановочные шифры изменяют сами блоки информации по определенным законам.
Деление криптоалгоритмов на моноалфавитные и многоалфавитные характерно для подстановочных шифров. Моноалфавитные криптоалгоритмы заменяют блок входного текста (символ входного алфавита) на один и тот же блок шифротекта (символ выходного алфавита). В многоалфавитных шифрах одному и тому же блоку входного текста могут соответствовать разные блоки шифротекста, что существенно затрудняет криптоанализ.
2 Криптографическая в Java
Разработчик языка Java, компания Oracle (бывшая Sun Microsystems), предоставляет встроенные возможности для шифрования данных и построения безопасного программного обеспечения. Программисту предоставляется весь спектр возможностей построения системы:
- постановка/проверка электронной подписи;
- вычисление хэш-функции;
- генерация пар ключей открытый/секретный;
- создание сертификатов, подтверждающих аутентичность открытых ключей;
- хранение ключей, а также сертификатов надежных партнеров;
- преобразование ключей из представления со скрытой структурой в общепонятное представление и наоборот;
- управление параметрами криптографических алгоритмов;
- генерация параметров криптографических алгоритмов;
- генерация (псевдо)случайных чисел;-
- симметричное шифрование;
- выработка общего ключевого материала.
Механизмы безопасности в JDK оформлены в виде четырех основных пакетов и трех пакетов расширения:
- java.security — содержит интерфейсы и классы, составляющие каркас механизмов безопасности. Сюда входят средства разграничения доступа, а также криптографические средства (выработка электронной подписи, вычисление хэш-функции и т.п.).
- java.security.cert — средства поддержки сертификатов X.509 версии 3.
- java.security.interfaces — средства генерации RSA- и DSA-ключей.
- java.security.spec — средства спецификации ключевого материала и параметров криптографических алгоритмов.
- javax.crypto — интерфейс и классы для симметричного шифрования.
- javax.crypto.interfaces — интерфейсы средств выработки ключей для алгоритма Диффи-Хелмана.
- javax.crypto.spec — классы для управления ключами и параметрами криптографических алгоритмов.
Пакеты java.security и javax.crypto содержат классы, отображающие основные понятия криптографии:
- java.security.cert.Certificate – сертификат.
- javax.crypto.Cipher – шифр.
- java.security.Key,java.
security.PrivateKey,java. security.PublicKey,javax. crypto.SecretKey – ключи, используемые для шифрования и подписи. - javax.crypto.KeyAgreement – протокол передачи секретных ключей.
- javax.crypto.KeyGenerator – производит ключи для симметричных шифров.
- java.security.KeyPairGenerator – производит пары секретный ключ-секретный ключ для шифрования или цифровой подписи.
- javax.crypto.Mac – Message Authentication Code (MAC)
- java.security.MessageDigest – hash-функции.
- java.security.SecureRandom – генератор случайных чисел.
- java.security.Signature – цифровая подпись.
Все
методы классов делятся на две
части – Application Programming Interface и Service
Provider Interface (методы, которые надо реализовать
самому).
2.1
Алгоритм шифрования/дешифрования AES
Advanced
Encryption Standard (AES), также известный как
Rijndael –симметричный алгоритм блочного
шифрования (размер блока 128 бит, ключ 128/192/256
бит), принятый в качестве стандарта шифрования
правительством США по результатам конкурса
AES. Этот алгоритм хорошо проанализирован
и сейчас широко используется, как это
было с его предшественником DES. Национальный
институт стандартов и технологий США
опубликовал спецификацию AES 26 ноября
2001. 26 мая 2002 года AES был объявлен стандартом
шифрования. По состоянию на 2009 год AES является
одним из самых распространённых алгоритмов
симметричного шифрования. Поддержка
AES (и только его) введена фирмой Intel в семейство
процессоров x86 начиная с Intel Core i7-980X Extreme
Edition, а затем на процессорах Sandy Bridge.
2.1.1
Реализация алгоритма AES
2.1.1.1
Работа отправителя
Генерация ключей
Для генерации ключей программист, не вникая в математические формулы и особенности их реализации, может использовать уже готовые алгоритмы и методы криптографии. Они предоставляются определенными организациями, так называемыми провайдерами (provider). По умолчанию встроенные средства Java поставляет провайдер SUN. Таким образом, единственное, что необходимо сделать — это указать собственно алгоритм и провайдера.
В первую очередь нужно сгенерировать ключ для симметричного шифра, для этого используется класс KeyGenerator. С целью получения конкретного объекта этого класса необходимо вызвать метод getInstance(). В качестве аргументов передаются строки с указанием алгоритма. Например, для использования AES необходимо писать:
KeyGenerator
kg = KeyGenerator.getInstance(“AES”
Далее нужно инициализировать объект kg, используя SecureRandom – генератор случайных чисел:
kg.init(new SecureRandom());
Последним этапом является запрос у генератора ключа с помощью метода generateKey():
SecretKey key = kg.generateKey();
Зашифровка данных
Для шифрования данных используется класс Cipher. Для получения конкретного объекта этого класса необходимо вызвать метод getInstance(). Необходимо указать метод шифрования, в моем случае это AES:
Cipher cipher = Cipher.getInstance(“AES”);
Далее необходимо инициализировать полученный объект методом init(), для шифрования метод принимает значение Cipher.ENCRYPT_MODE и ключ:
cipher.init(Cipher.
Зашифровываем данные с помощью метода doFinal():
byte[]
cipherText = cipher.doFinal(text.getBytes()
2.1.1.2
Работа получателя
Работа с ключом
Сначала на основе текстового ключа формируется массив байтов ключа:
StringTokenizer st = new StringTokenizer(key);
byte[] out = new byte[st.countTokens()];
int i = 0;
while (st.hasMoreTokens()) {
out[i++] = Byte.parseByte(st.nextToken())
}
Затем на основе байтов ключа создается объект класса SecretKeySpec:
SecretKeySpec
keySpec = new SecretKeySpec(stringToByte(
Созданный SecretKeySpec передается в объект класса javax.crypto.Cipher, который непосредственно производит дешифрацию данных через вызов метода doFinal.
Расшифровка данных
Для расшифровки данных используется класс Cipher. Для получения конкретного объекта этого класса необходимо вызвать метод getInstance(). Необходимо указать метод шифрования, в моем случае это AES:
Cipher cipher = Cipher.getInstance(“AES”);
Далее необходимо инициализировать полученный объект методом init(), для расшифровки метод принимает значение Cipher.DECRYPT_MODE и ключ в виде массива байтов:
cipher.init(Cipher.
Расшифровываем данные с помощью метода doFinal():
out
= new String(cipher.doFinal(
Полный
код программы приведен в приложении
А.
2.1.2
Тестирование программы
Главное окно программы представлено на рисунке 1.
Рисунок 1 – Главное окно программы
В верхнее поле «Входной текст» необходимо ввести текст, который необходимо зашифровать, из списка выбрать нужный алгоритм и нажать на кнопку «Шифровать», в нижнем поле «Результат» появляется зашифрованный текст и в поле «Ключ» - сгенерированный ключ, как показано на рисунке 2.
Рисунок 2 – Шифрование AES
Для расшифровки зашифрованного текста в верхнее поле «Входной текст» вводится зашифрованный текст, в поле «Ключ» вводится сгенерированный ключ и нажимается кнопка «Расшифровать». В нижнем поле «Результат» появляется расшифрованный текст, как показано на рисунке 3.
Рисунок
3 – Расшифровка AES
2.2
Алгоритм криптографического хеширования
SHA
Secure Hash Algorithm — алгоритм криптографического хеширования. Описан в RFC 3174. Для входного сообщения произвольной длины (максимум 264 − 1 бит, что равно 2 эксабайта) алгоритм генерирует 160-битное хеш-значение, называемое также дайджестом сообщения. Используется во многих криптографических приложениях и протоколах. Принципы, положенные в основу SHA, аналогичны тем, которые использовались Рональдом Ривестом при проектировании MD4.
SHA
реализует хеш-функцию, построенную на
идее функции сжатия. Входами функции
сжатия являются блок сообщения длиной
512 бит и выход предыдущего блока сообщения.
Выход представляет собой значение всех
хеш-блоков до этого момента. Иными словами
хеш блока Mi равен
hi = f(Mi,hi
− 1). Хеш-значением всего сообщения
является выход последнего блока.
2.2.1
Реализация алгоритма SHA
Хэш-функции реализуются классами, наследующимися от java.security.MessageDigest.
Для того чтобы посчитать хэш от произвольного текста, нужно получить объект, реализующий функцию. Для получения объекта класса MessageDigest необходимо вызвать метод getInstance(). Необходимо указать аргумент метода, в моем случае это “SHA”:
MessageDigest
md5 = MessageDigest.getInstance("
Далее необходимо задать данные для подсчета функции и посчитать значение хеш:
byte
digest[] = md5.digest(formatDate.
Полный
код программы приведен в приложении
Б.
2.2.2
Тестирование программы
Главное окно программы представлено на рисунке 4.
Рисунок 4 – Главное окно программы
В верхнее поле вводится текст, хеш-значение которого необходимо сгенерировать, из списка выбирается алгоритм криптографического хеширования и нажимается кнопка «Сгенерировать хеш-значение». В нижнем поле появится сгенерированный хеш, как показано на рисунке 5.
Рисунок 5 – Генерация хеш-значения
3 Криптография
в Delphi
Для использования криптографии в программах на Delphi есть библиотека компонентов - DCPcrypt (Cryptographic Component Library) с готовой реализацией более ста алгоритмов шифрования и хеширования, среди них:
1) Алгортимы шифрования
- Blowfish
- Cast 128
- Cast 256
- DES, 3DES
- Ice, Thin Ice, Ice2
- IDEA
- Mars
- Misty1
- RC2, RC4, RC5, RC6
- Rijndael (the new AES)
- Serpent
- Tea
- Twofish
2)
А
л
г
о
р
и
т
м
ы
х
е
ш
и
р
о
в
а
н
и
я
-
Haval
- MD4
- MD5
- RipeMD-128
- RipeMD-160
- SHA-1
- SHA-256, SHA-384, SHA-512
- Tiger
Необходимо установить библиотеку DCPcrypt, для этого помещаем компоненты по адресу С:\Program Files\Borland\Delphi7\Lib. Заткм нужно добавить путь к созданной папке и её двум подпапкам Ciphers и Hashes в Library Path (в Delphi 7 в главном меню Tools — Enviroment Options, вкладка Library). Далее следует открыть нужный пакет и установить (для Delphi 6-ой версии и выше – DCPdelphi6.dpk).
После установки необходимый
компонент можно добавлять с вкладки DCPciphers или DCPhashes, а можно добавлять нужный модуль в раздел uses и использовать подпрограммы.
3.1 Алгоритма шифрования/
дешифрования DES DES (Data Encryption Standard) — симметричный алгоритм шифрования, разработанный фирмой IBM и утвержденный правительством США в 1977 году как официальный стандарт (FIPS 46-3). DES имеет блоки по 64 бита и 16 цикловую структуру сети Фейстеля, для шифрования использует ключ с длиной 56 бит. Алгоритм использует комбинацию нелинейных (S-блоки) и линейных (перестановки E, IP, IP-1) преобразований.
Входными данными для блочного шифра служат блок размером n бит и k-битный ключ. На выходе, после применения шифрующего преобразования, получается n-битный зашифрованный блок, причём незначительные различия входных данных как правило приводят к существенному изменению результата. Блочные шифры реализуются путём многократного применения к блокам исходного текста некоторых базовых преобразований.
Базовые преобразования:
- Сложное преобразование на одной локальной части блока.
- Простое преобразование между частями блока.
Так как преобразование производится поблочно, как отдельный шаг требуется разделение исходных данных на блоки необходимого размера. При этом вне зависимости от формата исходных данных, будь то текстовые документы, изображения или другие файлы, они должны быть интерпретированы в бинарный вид и только после этого разбиты на блоки.
3.1.1 Реализация алгоритма DES
Вначале необходимо добавить необходимый модуль в раздел uses для компонента DCPcrypt, в моем случае это модули SecUnit:
uses
SecUnit;
Далее необходимо сгенерировать случайный ключ при помощи RandomKey:
MemKey.Text:=RandomKey;
Для шифрования входного текста используется EncodeString. В качестве аргументов задается ключ и шифруемый текст:
Memo2.Text := EncodeString(MemKey.Text,
Memo1.Text); Для расшифровки зашифрованного текста используется DecodeString. В качестве аргументов задается ключ и зашифрованный текст:
Memo3.Text := DecodeString(MemKey.Text,
Memo2.Text); Полный код программы приведен в приложении В.
3.1.2 Тестирование программы
Главное окно программы представлено на рисунке 6.
Рисунок 6 – Главное окно программы
Вначале необходимо сгенерировать ключ, с помощью которого будет происходить шифрование. Для этого нужно нажать на кнопку «Генерация ключа». Получившейся ключ появится в поле «Ключ», как показано на рисунке 7.
Рисунок 7 – Генерация ключа
В верхнее поле «Текст» вводится текст, который необходимо зашифровать при помощи алгоритма DES и нажимается кнопка «Шифровать», в поле «Шифровка» появляется зашифрованный, как показано на рисунке 8.
Рисунок 8 – Шифрование DES
Для расшифровки зашифрованного текста нужно нажать на кнопку «Дешифровать». В нижнем поле «Дешифровка» появляется расшифрованный текст, как показано на рисунке 9.
Рисунок 9 – Расшифровка DES
3.2 Реализация криптографического хеширования
Процедура для поиска на форме всех добавленных компонентов библиотеки DCPcrypt для создания хеш-значения и их помещения в TCheckListBox с указанием максимального размера хеш-значения в битах:
procedure TfrmMain.FormCreate(Sender: TObject);
var
i: integer;
Hash: TDCP_hash;
begin
for i := 0 to ComponentCount - 1 do
begin
if Components[i] is TDCP_hash then
begin
Hash := TDCP_hash(Components[i]);
lstHashes.Items.AddObject(
Hash.Algorithm + ' (Digest size: ' + IntToStr(Hash.HashSize) + ' bits)',Components[i]); end;
end;
end;
Составление списка всех выбранных хеш-алгоритмов в списке TCheckListBox, т.е. создание экземпляра списка, состоящего из выделенных алгоритмов:
for i := 0 to lstHashes.Items.Count - 1 do
begin
if lstHashes.Checked[i] then
begin
SetLength(Hashes,Length(
Hashes) + 1); Hashes[Length(Hashes) - 1] := TDCP_hash(lstHashes.Items.
Objects[i]); TDCP_hash(lstHashes.Items.
Objects[i]).Init; end;
end;
Запись данных из открытого файла в поток данных:
strmInput := TFileStream.Create(
boxInputFile.Text,fmOpenRead); Считывание в буфер при помощи процедуры Read:
read := strmInput.Read(buffer,Sizeof(
buffer)); Вычисление хеш-суммы:
for i := 0 to Length(Hashes) - 1 do
Hashes[i].Update(buffer,read);
until read <> Sizeof(buffer);
Сохранение хеш-суммы в массив:
for i := 0 to Length(Hashes) - 1 do
begin
SetLength(HashDigest,Hashes[i]
.HashSize div 8); Hashes[i].Final(HashDigest[0])
; end;
Получение хеш-суммы строкой:
for i := 0 to Length(Hashes) - 1 do
begin
for j := 0 to Length(HashDigest) - 1 do
s := s + IntToHex(HashDigest[j],2);
txtOutput.Lines.Add(Hashes[i].
Algorithm + ': ' + s); end;
Полный код программы приведен в приложении Г.
3.2.1 Тестирование программы
Главное окно программы представлено на рисунке 10.
Рисунок 10 – Главное окно программы
Нужно открыть файл, где хранится текст, для которого нужно создать хеш-значение. В окне алгоритмы можно выбрать один или несколько алгоритмов создания хеш-значения, поставив галочки на нужных.
После загрузки файла и выбора алгоритмов нужно нажать на кнопку «Хэш». Созданные значения появятся в поле «Результат», как показано на рисунке 11.
Рисунок 11 – Генерация хеш-значения
4 Асимметричная криптография в Perl
Довольно популярный Интернет-направленный язык Perl также имеет встроенные средства обеспечения защиты. Для примера рассмотрим использование криптографического алгоритма шифрования RSA.
4.1 Алгоритм RSA
Задача, которую решает RSA — это передача секретной информации таким образом, чтобы прочитать ее смог лишь адресат.
Потенциальным получателем шифрованного сообщения выполняются следующие
действия: - генерируются два больших простых числа (например, 1024 бит, 308 знаков) — p и q;
- подсчитывается их произведение n = pq;
- выбирается случайное число e, которое взаимно просто с числом (p-1)(q-1), а также не превосходит его;
- подсчитывается величина d такая, что ed = 1 mod (p-1)(q-1);
- пара (n, e) становится открытым ключом (public key), а d — закрытым ключом (private key).
Открытый ключ публикуется в открытых источниках, например пересылается по электронной почте.
Отправителю шифрованного сообщения для работы необходимо выполнить следующие действия:
- получить открытый ключ;
- создать сообщение в числовом виде m, не превосходящем n;
- подсчитать величину c = (me) mod n.
Величина с — это и есть зашифрованное сообщение, которое отправляется создателю открытого ключа.
Получатель закодированного сообщения вычисляет m = (cd) mod n и получает сообщение в расшифрованном виде.
Стойкость алгоритма RSA обеспечивается благодаря тому, что злоумышленнику необходимо получить число d, которое можно вычислить только в случае, если удастся факторизовать число n. Однако на данный момент не существует быстрых алгоритмов, решающих задачу факторизации больших чисел.
4.1.1 Реализация алгоритма RSA
4.1.1.1 Основные методы работы с RSA
В языке Perl вся криптография поставляется через модули CPAN. Реализация RSA находится в пакете Crypt::RSA.
Генерация 2048-битовых ключей:
$rsa = new Crypt::RSA;
$public, $private) = $rsa->keygen( Size => 2048 )
Открытый ключ публикуется. Шифрование данных (строка $message) с использованием открытого ключа:
my $c = $rsa->encrypt( Message => $message,
Key => $public );
В результате получается шифрованное сообщение $c, которое отправляется обратно адресату. Получатель использует для расшифровки ранее сгенерированный закрытый ключ $private,:
$message = $rsa->decrypt( Ciphertext => $c,
Key => $private );
Кроме представленных строк исходного текста на языке Perl, отметим некоторые дополнительные особенности пакета. Для отправки защищенных сообщений информация должна быть представлена в виде одного или нескольких чисел, значения которых не превосходят n. При этом каждому сообщению соответствует определенное число, и наоборот. Средства языка Perl позволяют дробить сообщение на последовательность таких чисел, а также в дальнейшем соединять их обратно в текст.
К сожалению, в системе RSA есть одно слабое место, снижающее степень защищенности. Если злоумышленник может каким-либо образом заставить отправителя закодировать уже известное ему сообщение, то величины p и q могут быть подсчитаны без факторизации n. Однако с этим можно успешно бороться, перегружая исходное сообщение так называемым мусором (padding), и для этой операции был разработан стандарт PKCS #1.
Пример взят из журнала «КомпьютерПресс»
4.1.1.2 Пример использования цифровой подписи
Проверка подлинности и целостности
сообщения обычно решается с помощью DSA-алгоритма, однако можно использовать и пакет Crypt::RSA. В первую очередь необходимо сгенерировать ключи, причем обычно ключи уже готовы и хранятся в файле под паролем. Для создания $private используется конструктор Crypt::RSA::Key::Private(), которому в качестве параметров передается имя файла и пароль.
$private = new Crypt::RSA::Key::Private(
Filename => “keys/имя_файла.private”,
Password => ‘пароль’
);
Подпись осуществляется с помощью $rsa->sign(). При этом в качестве параметров выступают сообщение и закрытый ключ:
$rsa = new Crypt::RSA;
$signature = $rsa->sign ( Message => $message,
Key => $private );
Сообщение $message и подпись $signature отправляются адресату, который, используя открытый ключ, получает подтверждение подлинности подписи:
$public = new Crypt::RSA::Key::Public(
Filename => “keys/имя_файла.public”,);
$rsa->verify( Message => $message,
Signature => $signature,
Key => $public )
|| die “Подпись поддельная!\n”;
Пример взят из журнала «КомпьютерПресс».
5 Microsoft CryptoAPI
CryptoAPI — интерфейс программирования приложений, который обеспечивает разработчиков Windows-
приложений стандартным набором функций для работы с криптопровайдером. Входит в состав операционных систем Microsoft. Большинство функций CryptoAPI поддерживается начиная с Windows 2000. CryptoAPI поддерживает работу с
асимметричными и симметричными ключами, то есть позволяет шифровать и расшифровывать данные, а также работать с электронными сертификатами. Набор поддерживаемых криптографических алгоритмов зависит от конкретного криптопровайдера. В последних ОС функции CryptoAPI содержатся в модулях crypt32.dll и advapi32.dll, но они не реализуют криптографических алгоритмов, а обращаются к другим модулям, называемым Cryptographic Service Providers (CSP). Одновременно в операционной системе можно установить несколько CSP. При первом обращении к CryptoAPI прикладная программа выбирает, с каким именно модулем CSP она будет работать в зависимости от того, какие криптографические алгоритмы ей необходимы. Следует отметить, что система по организации похожа на ту, что используется в Java.
CryptoAPI позволяет шифровать данные, подписывать документы цифровой подписью и многое другое. Существуют и встроенные средства, например Microsoft Base Cryptographic Provider. Имеется возможность использовать CryptoAPI в таких программах разработки, как Visual Studio, то есть автоматически осуществляется поддержка таких языков, как Visual C++, Visual Basic, Visual FoxPro и др. С развитием компанией Microsoft языковой платформы .NET большинство языков программирования поддерживают криптографические методы защиты.
Примером функции генерации ключей может быть CryptGenKey(), а шифрования и дешифрования — CryptEncrypt() и CryptDecrypt() и т.д.
6 Сравнение криптографических средств языков программирования
Все рассмотренные
криптографические средства предоставляют богатый набор средств шифрования, позволяющих организовать собственную систему защиты данных. Сравнивая криптографические средства языков программирования Java и Delphi, средства Java гораздо шире. Компоненты DCPcrypt позволяют работать только с готовой реализацией алгоритмов шифрования и хеширования, а пакеты Java, кроме алгоритмов шифрования и хеширования, позволяют работать с готовой реализацией создания и проверка электронной подписи, создание сертификатов, подтверждающих аутентичность открытых ключей.
Интерфейс CryptoAPI является основой средств защиты Microsoft Internet Security Framework. Он позволяет создавать приложения, использующие криптографические методы и обеспечивает базовые функции защиты для безопасных каналов и подписи кода. Реализация CryptoAPI в Internet Explorer позволяет легко интегрировать со своими приложениями усиленные средства шифрования. Интерфейс CryptoAPI обеспечивает API высокого уровня для аутентификации, подписи, шифрования/дешифрации, а также полную инфраструктуру защиты с общим ключом. Благодаря данной инфраструктуре, можно воспользоваться функциями управления сертификатами, такими как запрос на создание сертификата, его сохранение или верификация.
.NET Framework предоставляет реализации многих стандартных криптографических алгоритмов. Классы в пространстве имен System.Security.Cryptography платформы .NET Framework управляют многими деталями шифрования. Некоторые из них являются оболочками для неуправляемого интерфейса Microsoft Cryptography API (CryptoAPI), в то время как другие реализованы полностью в виде управляемого кода. При использовании этих классов вам вовсе не обязательно быть экспертом в криптографии. При создании нового экземпляра одного из классов, реализующих алгоритмы шифрования, ключи создаются автоматически с целью удобства использования, а принятые по умолчанию значения свойств призваны обеспечить максимальную защищенность.
Обзор предоставляет общие сведения о методах и способах шифрования, поддерживаемых в .NET Framework поддерживает способы шифрования и дишефрования, создание цифровой подписи, генерации хеш.
CryptoAPI и .NET предоставляют богатый набор средств шифрования, позволяющих организовать собственную систему защиты данных без использования сторонних средств. В .NET, правда, эти средства пока плохо отлажены и документированы, но использовать их все равно можно.
Можно сделать вывод, что и JDK security API, и CryptoAPI, и встроенные средства .NET предоставляют богатый набор средств шифрования, позволяющих организовать собственную систему защиты данных.
Заключение
Каждый из описанных способов реализации криптографических средств защиты информации обладает как достоинствами, так и недостатками. Выбор определяется поставленными задачами с учетом особенностей реализации, эксплуатации и финансовых возможностей. При этом необходимо принимать во внимание используемые аппаратные средства, необходимую степень защиты информации и т.д.
Как показывает практика, криптографические методы защиты действительно обеспечивают безопасность на достаточно высоком уровне. Несомненно, что данное направление будет быстро развиваться с появлением новых коммуникационных аппаратно-программных средств. Большинство современных компаний стараются разработать универсальные криптографические интерфейсы и избавить разработчика программного обеспечения от самостоятельных реализаций сложных алгоритмов. И JDK security API, и CryptoAPI, и встроенные средства .NET предоставляют богатый набор средств шифрования, позволяющих организовать собственную систему защиты данных. Однако надо отметить, что на пути реализации эффективной защиты информации существует множество технологических трудностей. Поскольку соответствующие аппаратно-программные средства стремительно развиваются, это позволяет рассчитывать на появление новых решений, которые будут лишены существующих недостатков.
Список используемых источников
- Википедия [Электронный ресурс]/Свободная энциклопедия. Режим доступа: http://ru.wikipedia.org/, свободный. - Загл. с экрана.
- Компьютер
пресс [Электронный ресурс]/Журнал. Режим
доступа: http://www.compress.ru/
article.aspx?id=10153&iid=420, свободный. - Загл. с экрана. - Методы и средства защиты компьютерной информации [Электронный ресурс] / Режим доступа: http://www.tssonline.ru/, свободный. - Загл. с экрана.
- VinGrad [Электронный ресурс] / Форум программистов. Режим доступа: http://forum.vingrad.ru, свободный. - Загл. с экрана.
- Гонтарев А., Обзор Java Crypto API, изд. – М.: 2007.
Приложение А
Листинг программы
package ras;
import java.security.Key;
import java.security.SecureRandom;
import java.util.StringTokenizer;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.
SecretKeySpec;
public class Crypto {
Key key;
public String semetricEncrypt(String text, String algorithm) {
String out = "";
algorithm=algorithm.
toUpperCase(); try {
KeyGenerator kg = KeyGenerator.getInstance(
algorithm); kg.init(new SecureRandom());
SecretKey key = kg.generateKey();
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_
MODE, key); byte[] cipherText = cipher.doFinal(text.getBytes()
); for (int i = 0; i < cipherText.length; i++) {
out += cipherText[i] + " ";
}
this.key = key;
System.out.println(key.
toString()); } catch (Exception ex) {
ex.printStackTrace();
}
return out;
}
public String semetricDecrypt(String text, String key, String algorithm) {
String out = "";
algorithm=algorithm.
toUpperCase(); try {
SecretKeySpec keySpec = new SecretKeySpec(stringToByte(
key), algorithm); Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.DECRYPT_
MODE, keySpec); out = new String(cipher.doFinal(
stringToByte(text))); } catch (Exception ex) {
ex.printStackTrace();
}
return out;
}
public String byteToString(byte[] p) {
String out = "";
for (int i = 0; i < p.length; i++) {
out += p[i] + " ";
}
return out;
}
public String getKey() {
return byteToString(key.getEncoded())
; }
public byte[] stringToByte(String text) {
StringTokenizer st = new StringTokenizer(text);
byte[] out = new byte[st.countTokens()];
int i = 0;
while (st.hasMoreTokens()) {
out[i++] = Byte.parseByte(st.nextToken())
; }
return out;
}
}
package ras;
public class Form extends javax.swing.JFrame {
Crypto cp = new Crypto();
public Form() {
initComponents();
}
public void encrypt() {
if (jComboBox1.getSelectedIndex() == 0) {
jTextArea2.setText(cp.
semetricEncrypt(jTextArea1. getText(), "BLOWFISH")); jTextField1.setText(cp.getKey(
)); } else if (jComboBox1.getSelectedIndex() == 1) {
jTextArea2.setText(cp.
semetricEncrypt(jTextArea1. getText(), "ARCFOUR")); jTextField1.setText(cp.getKey(
)); } else if (jComboBox1.getSelectedIndex() == 2) {
jTextArea2.setText(cp.
semetricEncrypt(jTextArea1. getText(), "RC2")); jTextField1.setText(cp.getKey(
)); } else if (jComboBox1.getSelectedIndex() == 3) {
jTextArea2.setText(cp.
semetricEncrypt(jTextArea1. getText(), "DESEDE")); jTextField1.setText(cp.getKey(
)); } else if (jComboBox1.getSelectedIndex() == 4) {
jTextArea2.setText(cp.
semetricEncrypt(jTextArea1. getText(), "AES")); jTextField1.setText(cp.getKey(
)); } else if (jComboBox1.getSelectedIndex() == 5) {
jTextArea2.setText(cp.
semetricEncrypt(jTextArea1. getText(), "DES")); jTextField1.setText(cp.getKey(
)); }
}
public void decrypt() {
if (jComboBox1.getSelectedIndex() == 0) {
jTextArea2.setText(cp.
semetricDecrypt(jTextArea1. getText(), jTextField1.getText(), "BLOWFISH")); } else if (jComboBox1.getSelectedIndex() == 1) {
jTextArea2.setText(cp.
semetricDecrypt(jTextArea1. getText(), jTextField1.getText(), "ARCFOUR")); } else if (jComboBox1.getSelectedIndex() == 2) {
jTextArea2.setText(cp.
semetricDecrypt(jTextArea1. getText(), jTextField1.getText(), "RC2")); } else if (jComboBox1.getSelectedIndex() == 3) {
jTextArea2.setText(cp.
semetricDecrypt(jTextArea1. getText(), jTextField1.getText(), "DESEDE")); } else if (jComboBox1.getSelectedIndex() == 5) {
jTextArea2.setText(cp.
semetricDecrypt(jTextArea1. getText(), jTextField1.getText(), "AES")); } else if (jComboBox1.getSelectedIndex() == 6) {
jTextArea2.setText(cp.
semetricDecrypt(jTextArea1. getText(), jTextField1.getText(), "DES")); }
}
@SuppressWarnings("unchecked")
private void jButton1ActionPerformed(java.
awt.event.ActionEvent evt) { encrypt();
}
private void jButton2ActionPerformed(java.
awt.event.ActionEvent evt) { decrypt();
}
public static void main(String args[]) {
java.awt.EventQueue.
invokeLater(new Runnable() { public void run() {
new Form().setVisible(true);
}
});
}
}
Приложение БЛистинг программы
import java.security.MessageDigest;
public class AlgorithmXesh {
public String digest(String text,String algorithm){
String fileName="";
try{
MessageDigest md5 = MessageDigest.getInstance(
algorithm); String formatDate = String.valueOf(text);
StringBuffer code = new StringBuffer();
byte digest[] = md5.digest(formatDate.
getBytes()); for (int i = 0; i < digest.length; ++i) {
code.append(Integer.
toHexString(0x0100 + (digest[i] & 0x00FF)).substring(1)); }
fileName = code.toString();
}catch(Exception e){e.printStackTrace();}
return fileName;
}
}
public class Form extends javax.swing.JFrame {
AlgorithmXesh ax = new AlgorithmXesh();
public Form() {
initComponents();
}
public void digest() {
if (jComboBox1.getSelectedIndex() == 0) {
jTextArea2.setText(ax.digest(
jTextArea1.getText(), "SHA-256"));
} else if (jComboBox1.getSelectedIndex() == 1) {
jTextArea2.setText(ax.digest(
jTextArea1.getText(), "SHA-512"));
} else if (jComboBox1.getSelectedIndex() == 2) {
jTextArea2.setText(ax.digest(
jTextArea1.getText(), "SHA"));
} else if (jComboBox1.getSelectedIndex() == 3) {
jTextArea2.setText(ax.digest(
jTextArea1.getText(), "SHA-384"));
} else if (jComboBox1.getSelectedIndex() == 4) {
jTextArea2.setText(ax.digest(
jTextArea1.getText(), "MD5"));
} else if (jComboBox1.getSelectedIndex() == 5) {
jTextArea2.setText(ax.digest(
jTextArea1.getText(), "MD2"));
}
}
@SuppressWarnings("unchecked")
private void jButton1ActionPerformed(java.
awt.event.ActionEvent evt) { digest();
}
public static void main(String args[]) {
java.awt.EventQueue.
invokeLater(new Runnable() { public void run() {
new Form().setVisible(true);
}
});
}
}
Приложение ВЛистинг программы
unit Unit1;
interface
uses
Windows, Classes, Forms, StdCtrls, Controls, Buttons, ExtCtrls;
type
TForm1 = class(TForm)
Panel1 : TPanel;
Label1 : TLabel;
Label2 : TLabel;
Label3 : TLabel;
btnEncr : TSpeedButton;
Label4: TLabel;
MemKey: TMemo;
SpeedButton1: TSpeedButton;
Button1: TButton;
Memo1: TMemo;
Memo2: TMemo;
Memo3: TMemo;
procedure btnEncrClick(Sender: TObject);
procedure SpeedButton1Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var Form1: TForm1;
implementation
{$R *.dfm}
uses
SecUnit, // Интерфейс для компонентов DCP
SysUtils;
procedure TForm1.btnEncrClick(Sender: TObject);
begin
// Зашифровать(Ключ, Шифруемый текст): Шифровка;
Memo2.Text := EncodeString(MemKey.Text,
Memo1.Text); end;
procedure TForm1.SpeedButton1Click(
Sender: TObject); begin
MemKey.Text:=RandomKey;// "Случайный" ключ
Memo2.Text :='';
Memo3.Text:='';
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
// Расшифровать(Ключ, Шифровка): Исходный текст;
Memo3.Text := DecodeString(MemKey.Text,
Memo2.Text); end;
end.
Приложение Г
Листинг программы
unit uMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Buttons, StdCtrls, CheckLst, DCPtiger, DCPsha512, DCPsha256,
DCPsha1, DCPripemd160, DCPripemd128, DCPmd5, DCPmd4, DCPcrypt2, DCPhaval;
type
TfrmMain = class(TForm)
DCP_haval1: TDCP_haval;
DCP_md41: TDCP_md4;
DCP_md51: TDCP_md5;
DCP_ripemd1281: TDCP_ripemd128;
DCP_ripemd1601: TDCP_ripemd160;
DCP_sha11: TDCP_sha1;
DCP_sha2561: TDCP_sha256;
DCP_sha3841: TDCP_sha384;
DCP_sha5121: TDCP_sha512;
DCP_tiger1: TDCP_tiger;
grpInputFile: TGroupBox;
boxInputFile: TEdit;
grpHashes: TGroupBox;
lstHashes: TCheckListBox;
grpOutput: TGroupBox;
txtOutput: TMemo;
btnHash: TButton;
btnBrowseFiles: TSpeedButton;
dlgOpen: TOpenDialog;
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure btnBrowseFilesClick(Sender: TObject);
procedure btnHashClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
frmMain: TfrmMain;
implementation
{$R *.dfm}
procedure TfrmMain.FormCreate(Sender: TObject);
var
i: integer;
Hash: TDCP_hash;
begin
for i := 0 to ComponentCount - 1 do
begin
if Components[i] is TDCP_hash then
begin
Hash := TDCP_hash(Components[i]);
lstHashes.Items.AddObject(
Hash.Algorithm + ' (Digest size: ' + IntToStr(Hash.HashSize) + ' bits)',Components[i]); end;
end;
end;
procedure TfrmMain.btnBrowseFilesClick(
Sender: TObject); begin
if dlgOpen.Execute then
boxInputFile.Text := dlgOpen.FileName;
end;
procedure TfrmMain.btnHashClick(Sender: TObject);
var
Hashes: array of TDCP_hash;
HashDigest: array of byte;
i, j, read: integer;
s: string;
buffer: array[0..16383] of byte;
strmInput: TFileStream;
begin
txtOutput.Clear;
Hashes := nil;
for i := 0 to lstHashes.Items.Count - 1 do
begin
if lstHashes.Checked[i] then
begin
SetLength(Hashes,Length(
Hashes) + 1); Hashes[Length(Hashes) - 1] := TDCP_hash(lstHashes.Items.
Objects[i]); TDCP_hash(lstHashes.Items.
Objects[i]).Init; end;
end;
strmInput := nil;
try
strmInput := Memo1.Text,fmOpenRead);
repeat
read := strmInput.Read(buffer,Sizeof(
buffer)); for i := 0 to Length(Hashes) - 1 do
Hashes[i].Update(buffer,read);
until read <> Sizeof(buffer);
strmInput.Free;
for i := 0 to Length(Hashes) - 1 do
begin
SetLength(HashDigest,Hashes[i]
.HashSize div 8); Hashes[i].Final(HashDigest[0])
; // хэш s := '';
for j := 0 to Length(HashDigest) - 1 do
s := s + IntToHex(HashDigest[j],2);
txtOutput.Lines.Add(Hashes[i].
Algorithm + ': ' + s); end;
except
strmInput.Free;
MessageDlg('An error occurred while reading the file',mtError,[mbOK],0);
end;
end;
end.