Алгоритм Elliptic Curve Cryptography — ECC быстрее и надёжнее широко используемых аналогов
Сегодня сертификаты DigiCert SSL предлагают на выбор два различных алгоритма шифрования — RSA и ECC — они помогут вам создать в организации более надежную и масштабируемую среду.
- Более высокий уровень безопасности за счёт того, что сертификаты с алгоритмом ECC c 256-битным ключом в 10000 раз более устойчивы к взлому, чем сертификаты с алгоритмом RSA с 2048-битным ключом, и по безопасности эквивалентны сертификатам RSA с 3072-битным ключом;
- Повышение производительности серверов, особенно в периоды пиковой нагрузки, за счёт возможности обрабатывать большее количество запросов при меньшей загрузке ЦПУ, что становится все более важным по мере распространения планшетов и мобильного интернета и, следовательно, повышения требований к производительности веб-инфраструктуры;
- Повышение скорости обработки запросов и снижение времени отклика. Внутренние тесты DigiCert показали, что сервер с RSA-сертификатом в состоянии обрабатывать 450 запросов в секунду со средним временем отклика в 150 миллисекунд, тогда как у сервера с ECC-сертификатом при работе в тех же условиях среднее время отклика − примерно 75 миллисекунд.
ECC обеспечивает наилучшую масштабируемость и позволяет осуществлять одновременное взаимодействие миллиардов хостов, существенно повышая эффективность обмена информацией в виртуальных средах, использования облачных решений и глобальной электронной торговли. С точки зрения пользователя, улучшенная вычислительная производительность и эффективное использование инфраструктуры создают более благоприятные условия для работы и увеличивают производительность.
![]() Elliptic Curve #1 |
![]() Elliptic Curve #2 |
Эллиптическая кривая криптографии (ECC) существует с середины 1980-х годов, но она по-прежнему рассматривается как новичок в мире SSL и только начала получать признание за последние несколько лет. ECC — принципиально другой математический подход к шифрованию, чем почтенный алгоритм RSA. Эллиптическая кривая является алгебраической функцией (y2 = x3 + ax + b), которая выглядит как симметричная кривая, параллельная оси x при построении графика.
Как и в других формах криптографии с открытым ключом, ECC основан на одностороннем свойстве, в котором легко выполнить вычисление, но не поддается обратному или инвертировать результаты расчета, чтобы найти исходные числа. Для достижения этого свойства ECC использует иные математические операции чем RSA. Самый простой способ объяснить эту математику — для эллиптической кривой линия будет проходить только через три точки вдоль кривой (P, Q и R) и что, зная две из точек (P и Q), другая (R) можно легко вычислить, но только с R, другие два, P и Q, не могут быть получены. ECC используется как в цифровых подписях с помощью эллиптической кривой DSA (ECDSA), так и при обмене ключами через Elliptic Curve Diffie-Hellman (ECDH).
Эти алгоритмы применяются в разных частях стандарта SSL. Во-первых, сертификаты SSL могут быть подписаны с ECDSA вместо RSA. Второе использование для ECC во время рукопожатия, когда веб-сервер и клиент согласовывают ключи сеанса, которые используются для шифрования всех данных, отправляемых между сервером и браузером. В этом последнем случае сервер и браузер должны быть настроены для поддержки наборов шифрования ECDH. Правительство США одобрило ECC, включив его в стандарт Suite B.
Главным преимуществом ECC является то, что он просто сильнее RSA для ключевых размеров, используемых сегодня. Типичный размер ключа ECC 256 бит эквивалентен 3072-битовому RSA-ключу и в 10 000 раз больше, чем 2048-битный ключ RSA! Чтобы опередить вычислительную мощность злоумышленника, Ключи RSA должны быть длиннее. CA / Browser Forum и ведущие разработчики браузеров официально завершили поддержку 1024-битных ключей RSA после 2013 года, поэтому все новые сертификаты SSL должны использовать ключи, которые в два раза больше. Кроме того, будущие размеры ключей RSA быстро увеличиваются, а длина ключа ECC возрастает линейно.
| Key Size bits |
RSA and DSA Key Size |
ECC Key Size |
| 80 | 1024 | 160 |
| 112 | 2048 | 224 |
| 128 | 3072 | 256 |
| 192 | 7680 | 384 |
| 256 | 15360 | 521 |
Другим преимуществом ECC в плане безопасности является простое предоставление альтернативы RSA и DSA. Если обнаружена серьезная слабость RSA, ECC, вероятно, станет лучшей альтернативой, особенно если внезапная слабость RSA требует резкого увеличения размера ключа для компенсации.
ECC также быстрее по ряду причин. Во-первых, меньшие ключи означают меньше данных, которые должны быть переданы с сервера клиенту во время установления связи SSL. Кроме того, ECC требует меньше вычислительной мощности (ЦП) и памяти, что приводит к значительному увеличению времени отклика и пропускной способности на веб-серверах, когда они используются.
Третьим критическим преимуществом использования ECC является Perfect Forward Secrecy (PFS). Хотя PFS не является свойством ECC, набор шифров, поддерживаемый современными веб-серверами и браузерами, которые реализуют PFS, также реализует ECC. Веб-серверы, которые предпочитают Ephemeral ECDH (ECDHE) с использованием наборов шифров, таких как «TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA», получают преимущества как от ECC, так и от PFS.
Предостережение при использовании алгоритма ECC
Есть несколько вещей, которые следует учитывать при использовании алгоритма на элептических кривых. Вероятно, самое главное, что некоторые браузеры не поддерживают сертификаты ECC. Microsoft построила поддержку ECC в Windows Vista, но более ранние версии, включая Windows XP, не поддерживают ECC. Mozilla добавила поддержку ECC в ранней версии Firefox, а текущая версия OS X от Apple также поддерживает ECC, а также текущие версии Chrome и Opera на всех платформах.
Надежная информация о поддержке ECC на мобильных платформах в настоящее время недоступна. Одним из решений этой проблемы является использование веб-сервера для доставки различных сертификатов на основе возможностей клиента. Например, Apache может быть настроен для ведения переговоров с ECC с клиентами, которые его поддерживают, и для переговоров RSA с остальными клиентами
Еще одна проблема для веб-сайтов заключается в том, что, хотя тестирование показало, что ECC работает быстрее, проверка подписи ECC является сложной задачей, и она может быть медленнее, чем RSA на устройствах с более медленными процессорами. Неизвестные уязвимости представляют собой еще один риск для ECC. Теоретически возможны побочные / временные атаки, и поскольку поддержка ECC во многих приложениях является более новой, обнаружить уязвимости в конкретных реализациях не исключено.
Конечная проблема с ECC заключается в том, что в этой области существует много патентов, что создает определенный риск и неопределенность. Certicom Corp., дочерняя компания BlackBerry Ltd., имеет более 350 патентов, которые охватывают многие аспекты ECC, такие как оптимизация производительности и безопасности. Тем не менее, многие считают, что Certicom имеет только патенты на конкретные реализации ECC, и во всех случаях существуют альтернативы, которые не обременены патентами.
| RSA | ECC | |
| Алгоритм | Все SSL сертификаты | Secure Site EV Secure Site Pro Secure Site Pro with EV |
| Описание | RSA предложен Ron Rivest, Adi Shamir и Leonard Adleman. RSA является наиболее часто используемым алгоритмом шифрования. | Криптография на эллиптической кривой (ECC) обычно считается наиболее эффективным и масштабируемым алгоритмом. ECC находится в списке Национального института стандартов и технологий (NIST) Suite B. |
| Обычно используется | Наиболее широко используемый тип ключа шифрования. | ECC набирает обороты благодаря отрасли, поскольку она более эффективна и масштабируема, чем другие алгоритмы для небольших устройств и систем с высокой пропускной способностью. Мобильные приложения и другие более мелкие системы, такие как чипы смарт-карт, первыми использовали его из-за небольшого размера ключа. |
| Вопросы развертывания | С более новым требованием для 2048-битных ключей вы можете увидеть снижение производительности и нуждаться в виртуальных машинах или кластерах для поддержки одинакового количества подключений. | Некоторые браузеры и мобильные устройства еще не могут быть настроены на прием сертификатов ECC. |
| Алгоритм подписи | SHA-256 | SHA-256 |
| Реализация | Вы должны загрузить и установить промежуточные сертификаты для внедрения сертификатов ECC. |
DV OV EV WC SAN PRO CodeSign Email PDF Wi-Fi IoT ALL Купить сертификат

Copyright © 1997-2024 adgrafics
Криптография

Криптография (от греч. κρυπτός — скрытый и γράφω — писать) – древнейшая наука о способах защиты конфиденциальных данных от нежелательного стороннего прочтения. Криптоанализ – наука, изучающая методы нарушения конфиденциальности информации. Криптанализ и криптография вместе составляют науку криптологию, изучающую способы шифрования и дешифрования.
Каталог ИБ — Средства шифрования систем и проектов доступен на TAdviser
Средства криптографической защиты гостайны до сих пор приравниваются к оружию. Очень немногие страны мира имеют свои криптографические компании, которые делают действительно хорошие средства защиты информации. Даже во многих развитых странах нет такой возможности: там отсутствует школа, которая позволяла бы эти технологии поддерживать и развивать. Россия одна из немногих стран мира, – может быть таких стран пять, или около того, – где все это развито. Причем и в коммерческом, и в государственном секторе есть компании и организации, которые сохранили преемственность школы криптографии с тех времен, когда она только зарождалась.
Алгоритмы шифрования
На сегодняшний день существует масса алгоритмов шифрования, имеющих значительную стойкость перед криптоанализом (криптографическую стойкость). Принято деление алгоритмов шифрования на три группы:
- Симметричные алгоритмы
- Ассиметричные алгоритмы
- Алгоритмы хэш-функций
Симметричные алгоритмы
Симметричное шифрование предусматривает использование одного и того же ключа и для зашифрования, и для расшифрования. К симметричным алгоритмам применяются два основных требования: полная утрата всех статистических закономерностей в объекте шифрования и отсутствие линейности. Принято разделять симметричные системы на блочные и поточные.
В блочных системах происходит разбиение исходных данных на блоки с последующим преобразованием с помощью ключа.
В поточных системах вырабатывается некая последовательность (выходная гамма), которая в последующем накладывается на само сообщение, и шифрование данных происходит потоком по мере генерирования гаммы. Схема связи с использованием симметричной криптосистемы представлена на рисунке.
Схема связи с использованием симметричной криптосистемы
Где где М — открытый текст, К — секретный ключ, передаваемый по закрытому каналу, Еn(М) — операция зашифрования, а Dk(M) — операция расшифрования
Обычно при симметричном шифровании используется сложная и многоступенчатая комбинация подстановок и перестановок исходных данных, причем ступеней (проходов) может быть множество, при этом каждой из них должен соответствовать «ключ прохода»
Операция подстановки выполняет первое требование, предъявляемое к симметричному шифру, избавляясь от любых статистических данных путем перемешивания битов сообщения по определенному заданному закону. Перестановка необходима для выполнения второго требования – придания алгоритму нелинейности. Достигается это за счет замены определенной части сообщения заданного объема на стандартное значение путем обращения к исходному массиву.
Симметричные системы имеют как свои преимущества, так и недостатки перед асимметричными. К преимуществам симметричных шифров относят высокую скорость шифрования, меньшую необходимую длину ключа при аналогичной стойкости, большую изученность и простоту реализации. Недостатками симметричных алгоритмов считают в первую очередь сложность обмена ключами ввиду большой вероятности нарушения секретности ключа при обмене, который необходим, и сложность управления ключами в большой сети.
Примеры симметричных шифров
- ГОСТ 28147-89 — отечественный стандарт шифрования
- 3DES (Triple-DES, тройной DES)
- RC6 (Шифр Ривеста )
- Twofish
- SEED — корейский стандарт шифрования
- Camellia – японский стандарт шифрования
- CAST (по инициалам разработчиков Carlisle Adams и Stafford Tavares)
- IDEA
- XTEA — наиболее простой в реализации алгоритм
- AES – американский стандарт шифрования
- DES – стандарт шифрования данных в США до AES
Асимметричные алгоритмы
Ассиметричные системы также называют криптосистемами с открытым ключом. Это такой способ шифрования данных, при котором открытый ключ передается по открытому каналу (не скрывается) и используется для проверки электронной подписи и для шифрования данных. Для дешифровки же и создания электронной подписи используется второй ключ, секретный.
Само устройство асимметричных криптосистем использует идею односторонних функций ƒ(х), в которых несложно найти х, зная значение самой функции но почти невозможно найти саму ƒ(х), зная только значение х. Примером такой функции может служить телефонный справочник большого города, в котором легко найти номер человека, зная его фамилию и инициалы, но крайне сложно, зная номер, вычислить владельца.
Принцип работы асимметричных систем
Допустим, имеются два абонента: А и В, и абонент В хочет отправить шифрованное сообщение абоненту А. Он зашифровывает сообщение с помощью открытого ключа и передает его уже зашифрованным по открытому каналу связи. Получив сообщение, абонент А подвергает его расшифрованию с помощью секретного ключа и читает.
Схема работы в асимметричной сети
Здесь необходимо сделать уточнение. При получении сообщения абонент А должен аутентифицировать свою личность перед абонентом В для того, чтобы недоброжелатель не смог выдать себя за абонента А и подменить его открытый ключ своим.
Примеры асимметричных шрифтов
- RSA (Rivest-Shamir-Adleman, Ривест — Шамир — Адлеман)
- DSA (Digital Signature Algorithm)
- Elgamal (Шифросистема Эль-Гамаля)
- Diffie-Hellman (Обмен ключами Диффи — Хелмана)
- ECC (Elliptic Curve Cryptography, криптография эллиптической кривой)
- ГОСТ Р 34.10-2001
- Rabin
- Luc
- McEliece
Хеш-функции
Хешированием (от англ. hash) называется преобразование исходного информационного массива произвольной длины в битовую строку фиксированной длины.
Алгоритмов хеш-функций немало, а различаются они своими характеристиками – криптостойкостью, разрядностью, вычислительной сложностью и т.д.
Нас интересуют криптографически стойкие хеш-функции. К таким обычно предъявляют два требования:
- Для заданного сообщения С практически невозможно подобрать другое сообщение С’ с таким же хешем
- Практически невозможно подобрать пар сообщений (СС’), имеющих одинаковый хеш.
Требования называются стойкостью к коллизиям первого рода и второго рода соответственно. Для таких функций остается важным и другое требование: при незначительном изменении аргумента должно происходить значительное изменение самой функции. Таким образом, значение хеша не должно давать информации даже об отдельных битах аргумента.
Примеры хеш-алгоритмов
- Adler-32
- CRC
- SHA-1
- SHA-2 (SHA-224, SHA-256, SHA-384, SHA-512)
- HAVAL
- MD2
- MD4
- MD5
- N-Hash
- RIPEMD-160
Криптографические примитивы
Для придания зашифрованной информации большей криптографической стойкости, в криптографической системе могут многократно применяться относительно простые преобразования – примитивы. В качестве примитивов могут использоваться подстановки, перестановки, циклический сдвиг или гаммирование.
Квантовая криптография
Квантовая криптография по праву считается новым витком в эволюции информационной защиты. Именно она позволяет создать практически абсолютную защиту шифрованных данных от взлома. Идея использовать квантовые объекты для защиты информации от подделки и несанкционированного доступа впервые была высказана Стефаном Вейснером в 1970 г. Спустя 10 лет ученые Беннет и Брассард, которые были знакомы с работой Вейснера, предложили использовать квантовые объекты для передачи секретного ключа. Читать статью «Квантовая криптография (шифрование)»
Постквантовая криптография
Постквантовая криптография — криптографические алгоритмы, устойчивые к кибератакам с применением квантовых компьютеров.
Криптография в цифровых технологиях
Криптография в цифровых технологиях необходима как инструмент защиты конфиденциальных данных а так же как средство противодействия незаконному копированию и распространению данных, являющихся интеллектуальной собственностью. Читать статью «Криптография в цифровых технологиях»
История

Немецкая шифровальная машина «Enigma» времен 2-й мировой войны в действии
Криптография является древнейшей наукой, и первоначальными ее объектами были текстовые сообщения, которые с помощью определенных алгоритмов лишались смысла для всех, не обладающих специальным знанием по дешифровке этого сообщения – ключом.
Изначально использовались методы, сегодня применяемые разве что для головоломок, то есть, на взгляд современника, простейшие. К таким способам шифрования относятся, например, метод замены, когда каждая буква заменяется другой, отстоящей от нее на строго определенном расстоянии в алфавите. Или метод перестановочного шифрования, когда буквы меняют местами в определенной последовательности внутри слова.
В древние времена шифрование применялось главным образом в военном и торговом деле, шпионаже, среди контрабандистов.
Несколько позже ученые-историки определяют дату появления другой родственной науки – стеганография. Эта наука занимается маскировкой самого факта передачи сообщения. Зародилась она в античности, а примером здесь может служить получение спартанским царем Леонидом перед битвой с персами провощенной дощечки с текстом, покрытой сухим легкосмываемым раствором. При очистке оставленные на воске стилусом знаки становились отчетливо видимыми. Сегодня для сокрытия сообщения служат симпатические чернила, микроточки, микропленки и т.д.
С развитием математики стали появляться математические алгоритмы шифрования, но все эти виды криптографической защиты информации сохраняли в разной объемной степени статистические данные и оставались уязвимыми. Уязвимость стала особенно ощутима с изобретением частотного анализа, который был разработан в IX веке нашей эры предположительно арабским энциклопедистом ал-Кинди. И только в XV веке, после изобретения полиалфавитных шрифтов Леоном Баттистой Альберти (предположительно), защита перешла на качественно новый уровень. Однако в середине XVII века Чарлз Бэббидж представил убедительные доказательства частичной уязвимости полиалфавитных шрифтов перед частотным анализом.
Развитие механики позволило создавать приборы и механизмы, облегчающие шифрование – появились такие устройства, как квадратная доска Тритемиуса, дисковый шифр Томаса Джефферсона. Но все эти приборы ри в какое сравнение не идут с теми, были созданы в XX веке. Именно в это время стали появляться различные шифровальные машины и механизмы высокой сложности, например, роторные машины, самой известной из которых является «Энигма»
До бурного развития науки в XX веке криптографам приходилось иметь дело только с лингвистическими объектами, а в ХХ веке открылись возможности применения различных математических методов и теорий, статистики, комбинаторики, теории чисел и абстракной алгебры.
Но настоящий прорыв в криптографической науке произошел с появлением возможности представления любой информации в бинарном виде, разделенной на биты с помощью компьютеров, что позволило создавать шрифты с доселе невиданной криптографической стойкостью. Такие системы шифрования, конечно, могут быть подвергнуты взлому, но временные затраты на взлом себя в подавляющем большинстве случаев не оправдывают.
Сегодня можно говорить о значительных разработках в квантовой криптографии.
Литература
- Баричев С.Г., Гончаров В.В., Серов Р.Е. Основы современной криптографии. — М.: *Варфоломеев А. А., Жуков А. Е., Пудовкина М. А. Поточные криптосистемы. Основные свойства и методы анализа стойкости. М.: ПАИМС, 2000.
- Ященко В. В. Введение в криптографию. СПб.: Питер, 2001. ISBN 5-318-00443-1.
- ГОСТ 28147-89. Системы обработки информации. Защита криптографическая. Алгоритм криптографического преобразования. М.: ГК СССР по стандартам, 1989.
- ГОСТ Р 34.10-94.Информационная технология. Криптографическая защита информации. *ГОСТ Р 34.11-94. Информационная технология. Криптографическая защита информации. Функция хэширования. М., 1995.
- ГОСТ Р 34.10-2001 Информационная технология. Криптографическая защита информации. Процессы формирования и проверки электронной цифровой подписи. М., 2001.
- Нечаев В. И. Элементы криптографии (Основы теории защиты информации). М.: Высшая школа, 1999.
- Жельников В. Криптография от папируса до компьютера. М.: АВР,1996.
Ссылки
- Информационная безопасность и шифрование
- Криптографический ликбез
- Криптографический справочник
- Криптолог-блог
- Сборник статей по криптографии
К какой группе шифров относится шифр ecc
Криптографическая система с открытым ключом (также асимметричное шифрование, асимметричные шифры) — система шифрования и/или электронной цифровой подписи (ЭЦП), при которой открытый ключ передаётся по открытому (то есть незащищённому, доступному для наблюдения) каналу, и используется для проверки ЭЦП и для шифрования сообщения. Для генерации ЭЦП и для расшифрования сообщения используется секретный ключ. Криптографические системы с открытым ключом в настоящее время широко применяются в различных сетевых протоколах, в частности, в протоколах TLS и его предшественнике SSL (лежащих в основе HTTPS), в SSH. Также используется в PGP, S/MIME.
- Идея криптосистемы с открытым ключом
- Схема шифрования с открытым ключом
- Научная основа
- Основные принципы построения криптосистем с открытым ключом
- Криптография с несколькими открытыми ключами
- Криптоанализ алгоритмов с открытым ключом
- Особенности системы
- Распространенные алгоритмы
Идея криптографии с открытым ключом очень тесно связана с идеей односторонних функций, то есть таких функций f(x), что по известному x довольно просто найти значение f(x), тогда как определение x из f(x) сложно в смысле теории.
Но сама односторонняя функция бесполезна в применении: ею можно зашифровать сообщение, но расшифровать нельзя. Поэтому криптография с открытым ключом использует односторонние функции с лазейкой. Лазейка — это некий секрет, который помогает расшифровать. То есть существует такой y, что зная f(x), можно вычислить x. К примеру, если разобрать часы на множество составных частей, то очень сложно собрать вновь работающие часы. Но если есть инструкция по сборке (лазейка), то можно легко решить эту проблему.
Понять идеи и методы криптографии с открытым ключом помогает следующий пример — хранение паролей в компьютере. Каждый пользователь в сети имеет свой пароль. При входе, он указывает имя и вводит секретный пароль. Но если хранить пароль на диске компьютера, то кто-нибудь его может считать (особенно легко это сделать администратору этого компьютера) и получить доступ к секретной информации. Для решения задачи используется односторонняя функция. При создании секретного пароля в компьютере сохраняется не сам пароль, а результат вычисления функции от этого пароля и имени пользователя. Например, пользователь Алиса придумала пароль «Гладиолус». При сохранении этих данных вычисляется результат функции f(ГЛАДИОЛУС), пусть результатом будет строка РОМАШКА, которая и будет сохранена в системе. В результате файл паролей примет следующий вид:

Вход в систему теперь выглядит так:

Когда Алиса вводит «секретный» пароль, компьютер проверяет, даёт или нет функция, применяемая к ГЛАДИОЛУС, правильный результат РОМАШКА, хранящийся на диске компьютера. Стоит изменить хотя бы одну букву в имени или в пароле, и результат функции будет совершенно другим. «Секретный» пароль не хранится в компьютере ни в каком виде. Файл паролей может быть теперь просмотрен другими пользователями без потери секретности, так как функция практически необратимая.
В предыдущем примере используется односторонняя функция без лазейки, поскольку не требуется по зашифрованному сообщению получить исходное. В следующем примере рассматривается схема с возможностью восстановить исходное сообщение с помощью «лазейки», то есть труднодоступной информации. Для шифрования текста можно взять большой абонентский справочник, состоящий из нескольких толстых томов (по нему очень легко найти номер любого жителя города, но почти невозможно по известному номеру найти абонента). Для каждой буквы из шифруемого сообщения выбирается имя, начинающееся на ту же букву. Таким образом букве ставится в соответствие номер телефона абонента. Отправляемое сообщение, например «КОРОБКА», будет зашифровано следующим образом:

Криптотекстом будет являться цепочка номеров, записанных в порядке их выбора в справочнике. Чтобы затруднить расшифровку, следует выбирать случайные имена, начинающиеся на нужную букву. Таким образом исходное сообщение может быть зашифровано множеством различных списков номеров (криптотекстов).
Примеры таких криптотекстов:

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

Пусть K — пространство ключей, а e и d — ключи шифрования и расшифрования соответственно. Ee — функция шифрования для произвольного ключа eK, такая что:
Здесь c C, где C — пространство шифротекстов, а m M, где M — пространство сообщений.
Dd — функция расшифрования, с помощью которой можно найти исходное сообщение m, зная шифротекст c:
Ee: e
K> — набор шифрования, а Dd: d
K> — соответствующий набор для расшифрования. Каждая пара (E,D) имеет свойство: зная Ee, невозможно решить уравнение Ee(m) = c, то есть для данного произвольного шифротекста c
C, невозможно найти сообщение m
M. Это значит, что по данному e невозможно определить соответствующий ключ расшифрования d. Ee является односторонней функцией, а d — лазейкой.Ниже показана схема передачи информации лицом А лицу В. Они могут быть как физическими лицами, так и организациями и так далее. Но для более лёгкого восприятия принято участников передачи отождествлять с людьми, чаще всего именуемыми Алиса и Боб. Участника, который стремится перехватить и расшифровать сообщения Алисы и Боба, чаще всего называют Евой.

- Боб выбирает пару (e,d) и шлёт ключ шифрования e (открытый ключ) Алисе по открытому каналу, а ключ расшифрования d (закрытый ключ) защищён и секретен (он не должен передаваться по открытому каналу, либо его подлинность должна быть гарантирована некоторым сертифицирующим органом).
- Чтобы послать сообщение m Бобу, Алиса применяет функцию шифрования, определённую открытым ключом e: Ee(m) = c, c — полученный шифротекст.
- Боб расшифровывает шифротекст c, применяя обратное преобразование Dd, однозначно определённое значением d.
Начало асимметричным шифрам было положено в работе «Новые направления в современной криптографии» Уитфилда Диффи и Мартина Хеллмана, опубликованной в 1976 году. Находясь под влиянием работы Ральфа Меркле (Ralph Merkle) о распространении открытого ключа, они предложили метод получения секретных ключей, используя открытый канал. Этот метод экспоненциального обмена ключей, который стал известен как обмен ключами Диффи-Хеллмана, был первым опубликованным практичным методом для установления разделения секретного ключа между заверенными пользователями канала. В 2002 году Хеллман предложил называть данный алгоритм «Диффи — Хеллмана — Меркле», признавая вклад Меркле в изобретение криптографии с открытым ключом. Эта же схема была разработана Малькольмом Вильямсоном в 1970-х, но держалась в секрете до 1997 года. Метод Меркле по распространению открытого ключа был изобретён в 1974 году и опубликован в 1978, его также называют загадкой Меркле.
В 1977 году учёными Рональдом Ривестом (Ronald Linn Rivest), Ади Шамиром (Adi Shamir) и Леонардом Адлеманом (Leonard Adleman) из Массачусетского Технологического Института (MIT) был разработан алгоритм шифрования, основанный на проблеме о разложении на множители. Система была названа по первым буквам их фамилий. Эта же система была изобретена Клиффордом Коксом (Clifford Cocks) в 1973 году, работавшим в центре правительственной связи (GCHQ). Но эта работа хранилась лишь во внутренних документах центра, поэтому о её существовании было не известно до 1977 года. RSA стал первым алгоритмом, пригодным и для шифрования, и для цифровой подписи.
Вообще, в основу известных асимметричных криптосистем кладётся одна из сложных математических проблем, которая позволяет строить односторонние функции и функции-лазейки. Например, криптосистемы Меркля — Хеллмана и Хора — Ривеста опираются на так называемую задачу об укладке рюкзака.
- Начинаем с трудной задачи P. Она должна решаться сложно в смысле теории: не должно быть алгоритма, с помощью которого можно было бы перебрать все варианты решения задачи P за полиномиальное время относительно размера задачи. Более правильно сказать: не должно быть известного полиномиального алгоритма, решающего данную задачу — так как ни для одной задачи ещё пока не доказано, что для неё подходящего алгоритма нет в принципе.
- Можно выделить легкую подзадачу P’ из P. Она должна решаться за полиномиальное время, лучше, если за линейное.
- «Перетасовываем и взбалтываем» P’, чтобы получить задачу P», совершенно не похожую на первоначальную. Задача P», по крайней мере, должна выглядеть как оригинальная труднорешаемая задача P.
- P» открывается с описанием, как она может быть использована в роли ключа зашифрования. Как из P» получить P’, держится в секрете как секретная лазейка.
- Криптосистема организована так, что алгоритмы расшифрования для легального пользователя и криптоаналитика существенно различны. В то время как второй решает P» задачу, первый использует секретную лазейку и решает P’ задачу.
- В следующем примере показана схема, в которой Алиса шифрует сообщение так, что только Боб может прочитать его, и наоборот, Боб шифрует сообщение так, что только Алиса может расшифровать его.
Пусть есть 3 ключа KA, KB, KC, распределенные так, как показано в таблице.

Тогда Алиса может зашифровать сообщение ключом KA, а Эллен расшифровать ключами KB, KC, Кэрол — зашифровать ключом KC, а Дэйв расшифровать ключами KA, KB. Если Дэйв зашифрует сообщение ключом KA, то сообщение сможет прочитать Эллен, если ключом KB, то его сможет прочитать Франк, если же обоими ключами KA и KB, то сообщение прочитает Кэрол. По аналогии действуют и другие участники. Таким образом, если используется одно подмножество ключей для шифрования, то для расшифрования требуются оставшиеся ключи множества. Такую схему можно использовать для n ключей.

- Теперь можно посылать сообщения группам агентов, не зная заранее состав группы.
Рассмотрим для начала множество, состоящее из трех агентов: Алисы, Боба и Кэрол. Алисе выдаются ключи KA и KB, Бобу — KB и KC, Кэрол — KA и KC. Теперь, если отправляемое сообщение зашифровано ключом KC, то его сможет прочитать только Алиса, последовательно применяя ключи KA и KB. Если нужно отправить сообщение Бобу, сообщение шифруется ключом KA, Кэрол — ключом KB. Если нужно отправить сообщение и Алисе и Кэрол, то для шифрования используются ключи KB и KC.
Преимущество этой схемы заключается в том, что для её реализации нужно только одно сообщение и n ключей (в схеме с n агентами). Если передаются индивидуальные сообщения, то есть используются отдельные ключи для каждого агента (всего n ключей) и каждого сообщения, то для передачи сообщений всем различным подмножествам требуется 2 n — 2 ключей.
Недостатком такой схемы является то, что необходимо также широковещательно передавать подмножество агентов (список имён может быть внушительным), которым нужно передать сообщение. Иначе каждому из них придется перебирать все комбинации ключей в поисках подходящей. Также агентам придется хранить немалый объём информации о ключах.
Казалось бы, что криптосистема с открытым ключом — идеальная система, не требующая безопасного канала для передачи ключа шифрования. Это подразумевало бы, что два легальных пользователя могли бы общаться по открытому каналу, не встречаясь, чтобы обменяться ключами. К сожалению, это не так. Рисунок иллюстрирует, как Ева, выполняющая роль активного перехватчика, может захватить систему (расшифровать сообщение, предназначенное Бобу) без взламывания системы шифрования.

В этой модели Ева перехватывает открытый ключ e, посланный Бобом Алисе. Затем создает пару ключей e’ и d’, «маскируется» под Боба, посылая Алисе открытый ключ e’, который, как думает Алиса, открытый ключ, посланный ей Бобом. Ева перехватывает зашифрованные сообщения от Алисы к Бобу, расшифровывает их с помощью секретного ключа d’, заново зашифровывает открытым ключом e Боба и отправляет сообщение Бобу. Таким образом, никто из участников не догадывается, что есть третье лицо, которое может как просто перехватить сообщение m, так и подменить его на ложное сообщение m’. Это подчеркивает необходимость аутентификации открытых ключей. Для этого обычно используют сертификаты. Распределённое управление ключами в PGP решает возникшую проблему с помощью поручителей.
Еще одна форма атаки — вычисление закрытого ключа, зная открытый (рисунок ниже). Криптоаналитик знает алгоритм шифрования Ee, анализируя его, пытается найти Dd. Этот процесс упрощается, если криптоаналитик перехватил несколько криптотекстов с, посланных лицом A лицу B.

Большинство криптосистем с открытым ключом основаны на проблеме факторизации больших чисел. К примеру, RSA использует в качестве открытого ключа n произведение двух больших чисел. Сложность взлома такого алгоритма состоит в трудности разложения числа n на множители. Но эту задачу решить реально. И с каждым годом процесс разложения становится все быстрее. Ниже приведены данные разложения на множители с помощью алгоритма «Квадратичное решето».

Также задачу разложения потенциально можно решить с помощью Алгоритма Шора при использовании достаточно мощного квантового компьютера.
Для многих методов несимметричного шифрования криптостойкость, полученная в результате криптоанализа, существенно отличается от величин, заявляемых разработчиками алгоритмов на основании теоретических оценок. Поэтому во многих странах вопрос применения алгоритмов шифрования данных находится в поле законодательного регулирования. В частности, в России к использованию в государственных и коммерческих организациях разрешены только те программные средства шифрования данных, которые прошли государственную сертификацию в административных органах, в частности, в ФСБ, ФСТЭК.
Алгоритмы криптосистемы с открытым ключом можно использовать
- Как самостоятельные средства для защиты передаваемой и хранимой информации.
- Как средства распределения ключей. Обычно с помощью алгоритмов криптосистем с открытым ключом распределяют ключи, малые по объёму. А саму передачу больших информационных потоков осуществляют с помощью других алгоритмов.
- Как средства аутентификации пользователей.
- Преимущество асимметричных шифров перед симметричными шифрами состоит в отсутствии необходимости предварительной передачи секретного ключа по надёжному каналу.
- В симметричной криптографии ключ держится в секрете для обеих сторон, а в асимметричной криптосистеме только один секретный.
- При симметричном шифровании необходимо обновлять ключ после каждого факта передачи, тогда как в асимметричных криптосистемах пару (E,D) можно не менять значительное время.
- В больших сетях число ключей в асимметричной криптосистеме значительно меньше, чем в симметричной.

- Преимущество алгоритма симметричного шифрования над несимметричным заключается в том, что в первый относительно легко внести изменения.
- Хотя сообщения надежно шифруются, но «засвечиваются» получатель и отправитель самим фактом пересылки шифрованного сообщения.
- Несимметричные алгоритмы используют более длинные ключи, чем симметричные. Ниже приведена таблица, сопоставляющая длину ключа симметричного алгоритма с длиной ключа несимметричного алгоритма с аналогичной криптостойкостью:
- Процесс шифрования-расшифрования с использованием пары ключей проходит на два-три порядка медленнее, чем шифрование-расшифрование того же текста симметричным алгоритмом.
- В чистом виде асимметричные криптосистемы требуют существенно больших вычислительных ресурсов, потому на практике используются в сочетании с другими алгоритмами.
- Для ЭЦП сообщение предварительно подвергается хешированию, а с помощью асимметричного ключа подписывается лишь относительно небольшой результат хеш-функции.
- Для шифрования они используются в форме гибридных криптосистем, где большие объёмы данных шифруются симметричным шифром на сеансовом ключе, а с помощью асимметричного шифра передаётся только сам сеансовый ключ.
- RSA (Rivest-Shamir-Adleman, Ривест — Шамир — Адлеман)
- DSA (Digital Signature Algorithm)
- Elgamal (Шифросистема Эль-Гамаля)
- Diffie-Hellman (Обмен ключами Диффи — Хелмана)
- ECC (Elliptic Curve Cryptography, криптография эллиптической кривой)
- ГОСТ Р 34.10-2001
- Rabin
- Luc
- McEliece
- Williams System (Криптосистема Уильямса)
Хеширование, шифрование и цифровая подпись с использованием CryptoAPI и .NET
Криптография, как прикладная дисциплина, существует уже очень давно. Один из простейших шифров, шифр алфавитной замены, использовался еще во времена Цезаря. Но настоящий расцвет криптографии произошел только в последние несколько столетий, когда к задачам шифрования был применен математический аппарат. Эта статья дает обзор криптографических алгоритмов, предоставляемых MS CryptoAPI 2.0 и .NET Framework, и содержит примеры их использования на языках C++ (CryptoAPI) и C# (.NET). Также вкратце описывается набор замечательных ошибок, обнаруженных автором в реализации класса RSACryptoServiceProvider библиотеки .NET Framework.
Симметричные и асимметричные шифры
Основное назначение любого шифра – обеспечение возможности передачи сообщения по незащищенным каналам (не обязательно сетевым) с защитой этого сообщения от прочтения посторонними лицами. Посмотрим, что же такое шифры и с чем их едят.
Сначала дадим краткое определение криптографических функций шифрования и дешифрования.
Пусть есть две функции E(M1,K1) и D(M2,K2), зависящие от сообщений M1 и M2 и ключей K1 и K2, такие, что D(E(M,K1),K2)=M для некоторой пары ключей K1 и K2 и любого M, тогда E(.) и D(.) – функции шифрования и дешифрования, соответственно. Результат C=E(M,K1) называется криптограммой (или шифрограммой).
К функциям E(.) и D(.) предъявляются следующие требования:
- Они должны быть легко вычислимы для любых M, если известны K1 и K2.
- Вычисление D(M,?) – тяжелая задача при неизвестном ключе K2 (т.е., не зная ключа дешифрования, мы не можем вычислить исходное сообщение по криптограмме).
- Вычисление ключей K1 и K2 – тяжелая задача при наличии некоторого набора пар (имея набор криптограмм и исходных сообщений, мы не можем вычислить ключи).
- Вычисление K2 (в случае K2 отличного от K1) при известном K1 – также должно быть трудной задачей (это требование относится к асимметричным шифрам. Для цифровой подписи K2 и K1 меняются ролями).
Надежность шифра определяется именно по его соответствию вышеперечисленным требованиям, при этом считается, что алгоритмы вычисления E(.) и D(.) известны всем (есть еще вариант так называемой Security by obscurity, т.е. защиты из-за неизвестности алгоритма, но он при оценке стойкости шифров не рассматривается).
Если K1=K2, то шифр называется симметричным, в противном случае – асимметричным. Примеры известных симметричных шифров – DES, IDEA, Blowfish, ГОСТ, асимметричных – RSA, ECC.
Шифры также бывают блочными и потоковыми. Блочный шифр работает с сообщениями фиксированного размера (например, 64 бита), а поточный – шифрует весь поток данных посимвольно (например, побайтно). Известные блочные шифры – DES, IDEA, Blowfish, потоковые – RC4. Блочность шифра не означает невозможность шифрования им сообщений, превышающих по длине размер блока.
Существуют следующие распространенные варианты использования блочных шифров для шифрования длинных сообщений:
- ECB (Electronic CodeBook) – режим электронной кодовой книги. В этом режиме каждый блок шифруется независимо от других. Этот режим удобен для шифрования частей файла, записей в базе данных и т.п., однако при этом одинаковые фрагменты исходного сообщения порождают одинаковые фрагменты криптограммы, так что, зная часть исходного сообщения, злоумышленник может легко восстановить совпадающие фрагменты.
- CBC (Cipher Block Chaining) – режим сцепления блоков шифра. Это самый распространенный режим. В этом режиме шифруется не сам блок исходного сообщения, а его XOR с результатом шифрования предыдущего блока (это верно для всех блоков, кроме первого). Т.е. C(i)=E(M(i) xor C(i-1)), для всех i>0, C(0)=E(M(0) xor I), где I – это начальный вектор инициализации (он может передаваться вместе с шифрограммой в открытом виде).
- CFB (Cipher FeedBack) – режим обратной связи по шифру. Этот режим фактически превращает блочный шифр в потоковый. Для шифрования используется регистр R с размером, равным размеру блока. В начале он заполняется инициализационным вектором I. На каждом шаге регистр шифруется, и над n битами исходного сообщения (шифрование может идти как побитно, так и блоками по n=2, 4, … бита) выполняется XOR со старшими (левыми) битами E(R). Результат этого XOR и является частью шифрограммы. Затем R сдвигается на n бит влево, а результат XOR записывается в младшие (правые) разряды R.
- OFB (Output FeedBack) – режим выходной обратной связи. Этот режим очень похож на CFB, но вместо битов шифрограммы в регистр R вдвигаются старшие биты результата E(R), тем самым состояние сдвигового регистра вообще не зависит ни от исходного сообщения, ни от криптограммы.
Потоковые шифры в этой статье не рассматриваются. Я также не буду приводить деталей реализации конкретных блочных шифров, т.к. это выходит за рамки данной статьи, и существуют хорошие книги по криптографии, где эти алгоритмы рассматриваются в деталях (например, [1]).
Однако стоит немного остановиться на асимметричных шифрах, а точнее на популярной их разновидности – шифрах с открытым ключом. Шифр с открытым ключом имеет два ключа – открытый (public), который можно свободно распространять, и закрытый (private), который держится в секрете. Зашифровать сообщение может кто угодно, но расшифровать его сможет только владелец закрытого ключа. Системы шифрования с открытым ключом, как правило, основываются на сложности разрешения какой-либо математической задачи. Например, популярный алгоритм RSA основан на сложности разложения на множители произведения двух больших простых чисел. Рассмотрим этот алгоритм поподробнее, т.к. понимание основ его работы нам пригодится в дальнейшем.
Алгоритм RSA
Для генерации ключевой пары выбираются два больших (по современным требованиям надежности не менее 512 бит) простых числа (некоторые популярные алгоритмы их генерации рассмотрены в [1]) p и q . Затем вычисляется их произведение n = p * q и выбирается случайное число e , так что e взаимно просто с ( p -1)*( q -1). Также вычисляется число d , такое, что d * e =1 mod ( p -1)*( q -1) (эта операция делается с помощью расширенного алгоритма Евклида, см. [1]). Это означает, что
d * e =1+k*( p -1)*( q -1), где k – некое целое число. Открытым ключом является пара e и n , закрытым – d и n . Алгоритм позволяет шифровать сообщения m меньшие, либо равные n (как целые неотрицательные числа). Большие сообщения следует разбивать на части.
Шифрование осуществляется следующим способом:
c =m^ e mod n (возведение m в степень e по модулю n ),
а дешифрование производится так:
Гарантию того, что получится верный результат, дает малая теорема Ферма. Для любого a меньше, либо равного n:
a^ phi(n) =1 mod n , где phi(n) – число целых положительных чисел меньших n и взаимно простых с ним. Для n = p * q , phi(n)= ( p -1)*( q -1) и
(m^ e )^ d mod n = m^(1+k* phi(n) ) mod n=m.
Хеши
Основное предназначение криптографических хешей – контроль подлинности данных путем вычисления от них некоторой функции H(.), дающей результат фиксированной (и обычно небольшой длины). Функция H(.) должна удовлетворять следующим требованиям:
Для любых сообщений m, h=H(m) легко вычисляема.
Задача нахождения такого u (отличного от m), чтобы H(u)=h, должна являться трудной при неизвестном m.
Задача нахождения такого u, что H(u)=H(m) является трудной при известном m.
Большинство популярных хеш-функций генерируют хеш длиной 128 бит и более. Примерами наиболее распространенных хеш-функций являются MD5 и SHA. Значения хеш-функций часто используются в системах электронной цифровой подписи для генерации дайджеста сообщения, который затем и подписывается тем или иным алгоритмом. Также хеш-функции применяются в системах аутентификации для проверки паролей – открытый пароль пользователя не должен храниться в системе, вместо него хранится его хеш, который затем и сравнивается с хешем от пароля, вводимого пользователем при входе в систему.
Цифровая подпись
Электронная цифровая подпись (ЭЦП), как и обычная, позволяет установить некую отметку, указывающую на принадлежность электронного сообщения конкретному автору. Алгоритмы цифровой подписи тесно связаны с асимметричными шифрами. Например, алгоритм цифровой подписи RSA – это практически шифр RSA, но шифруется не само сообщение, а его дайджест, и шифрование производится не на открытом ключе, а на закрытом. В этом случае любой получатель, имеющий открытый ключ автора, может расшифровать дайджест и проверить его правильность.
Обмен ключами
Хорошо, у нас есть работающий шифр (или система ЭЦП), который мы хотим использовать для защищенной передачи данных. Однако остается одна проблема – обмен ключами. Симметричному алгоритму нужен один и тот же ключ как на шифрующей, так и на дешифрующей стороне. Требуется надежный способ генерации одинаковых сеансовых ключей на обеих сторонах или передачи ключа шифрующей стороной дешифрующей стороне (в качестве такого способа может выступать надежный курьер с дискеткой). Существуют специальные алгоритмы генерации совпадающих сеансовых ключей, но мы их рассматривать не будем, т.к. в CryptoAPI и .NET они не используются. Рассмотрим, как можно передать сгенерированный на шифрующей стороне сеансовый ключ другой стороне. Самый простой вариант – использовать шифр с открытым ключом. Имея открытый ключ получателя, мы шифруем на нем сеансовый ключ и передаем результат получателю вместе с зашифрованными данными. Теперь получатель может расшифровать сеансовый ключ и сами данные. Казалось бы, все хорошо, однако тут кроется еще одна проблема, связанная с распределением открытых ключей. В самом деле, где гарантия того, что полученный открытый ключ действительно принадлежит конкретному получателю? Если злоумышленник перехватил оригинальный открытый ключ и подсунул вместо него свой, то зашифрованный сеансовый ключ получит именно он, а не требуемый получатель. В дальнейшем злоумышленник может выдать себя за получателя и перехватить передаваемое сообщение. Для предотвращения такой возможности вводят различные сети доверия (trusted network) и авторитетные источники (trusted authority), которые берут на себя ответственность за подлинность открытого ключа (ключ подписывается собственной подписью центра, которой все безоговорочно доверяют).
Работа с CryptoAPI
Криптопровайдеры, инициализация и деинициализация
Любой сеанс работы с CryptoAPI начинается с инициализации (получения контекста). Инициализация выполняется при помощи функции CryptAcquireContext . В качестве параметров эта функция принимает имя контейнера ключей, имя криптопровайдера, тип провайдера и флаги, определяющие тип и действия с контейнером ключей и режим работы криптопровайдера:
BOOL WINAPI CryptAcquireContext(HCRYPTPROV* phProv,LPCTSTR pszContainer, LPCTSTR pszProvider,DWORD dwProvType,DWORD dwFlags);
Криптопровайдер – это сущность (обычно библиотека), реализующая определенный набор криптографических алгоритмов и обеспечивающая работу с ними. Существует около семи стандартных провайдеров, предустановленных в системе. Нам для примеров понадобятся два из них – Microsoft Base Cryptographic Provider (MS_DEF_PROV) и Microsoft Enhanced Cryptographic Provider (MS_ENHANCED_PROV) .
ПРИМЕЧАНИЕ
Заметим, что Enhanced-провайдер присутствует только на тех машинах, где установлена поддержка 128-битного шифрования (она автоматически устанавливается вместе с Internet Explorer 6.0).
Каждый криптопровайдер относится к определенному типу. Это позволяет, перебрав все установленные на машине провайдеры, выбрать те, которые поддерживают нужные алгоритмы. Два упомянутых провайдера имеют тип PROV_RSA_FULL .
Криптопровайдер поддерживает защищенные области, называемые контейнерами ключей. Контейнеры позволяют приложениям сохранять и использовать в дальнейшем сгенерированные один раз ключи, обеспечивая защиту самого ключа от злоумышленника.
ПРИМЕЧАНИЕ
Стандартные криптопровайдеры хранят ключи на диске, в зашифрованном виде. Однако существует потенциальная возможность, что злоумышленник, укравший компьютер или жесткий диск, сможет расшифровать сохраненные ключи.
Контейнеры бывают двух типов – пользовательские (этот тип используется по умолчанию) и машинные ( CRYPT_MACHINE_KEYSET ). Пользовательский контейнер доступен только приложениям, выполняемым от имени владельца контейнера. Приложение может использовать такой контейнер для сохранения персональных ключей. Доступ к машинным контейнерам разрешен только администраторам. В них обычно сохраняются ключи, используемые сервисами и системными программами. Тип контейнера задается флагом при получении контекста.
Для первоначального создания контейнера нужно вызвать CryptAcquireContext с флагом CRYPT_NEWKEYSET . Для удаления контейнера требуется указать флаг CRYPT_DELETEKEYSET .
Если приложению не требуется доступ к контейнеру ключей (например, приложение вычисляет хеш MD5), то стоит вызывать CryptAcquireContext с флагом CRYPT_VERIFYCONTEXT , передавая NULL вместо имени контейнера.
Следующий пример демонстрирует инициализацию CryptoAPI для последующего вычисления хеша MD5:
HCRYPTPROV hProv; if(!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) < MessageBoxA("Failed to acquire cryptographic context", "Error", MB_OK|MB_ICONERROR); return; > //здесь что-то делаем //. CryptReleaseContext(hProv,0);
Деинициализация CryptoAPI выполняется с помощью функции CryptReleaseContext , единственным значащим параметром которой является полученный ранее хэндл криптографического контекста.
Генерация ключей и обмен ключами
Для генерации ключей в CryptoAPI предусмотрены две функции – CryptGenKey и CryptDeriveKey . Первая из них генерирует ключи случайным образом, а вторая – на основе пользовательских данных. При этом гарантируется, что для одних и тех же входных данных CryptDeriveKey всегда выдает один и тот же результат. Это способ генерации ключей может быть полезен для создания симметричного ключа шифрования на базе пароля. Мы же более подробно остановимся на функции CryptGenKey , которая используется чаще всего. Эта функция имеет прототип:
BOOL WINAPI CryptGenKey(HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY* phKey);
Первый и четвертый параметры говорят сами за себя. Вторым параметром передается идентификатор алгоритма шифрования, для которого генерируется ключ (например, CALG_3DES ). При генерации ключевых пар RSA для шифрования и подписи используются специальные значения AT_KEYEXCHANGE и AT_SIGNATURE . Третий параметр задает различные опции ключа, которые зависят от алгоритма и провайдера. Например, старшие 16 битов этого параметра могут задавать размер ключа для алгоритма RSA. Подробное описание всех флагов можно найти в MSDN. Здесь я упомяну только один флаг — CRYPT_EXPORTABLE, который позволяет экспортировать закрытые ключи RSA из контейнера (по умолчанию это запрещено). Для других ключей этот параметр смысла не имеет – открытые ключи являются свободно экспортируемыми, а сессионные ключи вообще не хранятся внутри контейнера, так что их обязательно нужно экспортировать.
Параметры, которые нельзя задать при генерации ключа (например, инициализационные векторы), можно установить уже после его создания с помощью функции CryptSetKeyParam . Ее рассмотрение, однако, выходит за рамки этой статьи.
Обмен ключами в CryptoAPI реализуется с помощью функций CryptExportKey и CryptImportKey , имеющих следующие прототипы:
BOOL WINAPI CryptExportKey(HCRYPTKEY hKey,HCRYPTKEY hExpKey,DWORD dwBlobType,DWORD dwFlags,BYTE* pbData,DWORD* pdwDataLen); BOOL WINAPI CryptImportKey(HCRYPTPROV hProv,BYTE* pbData,DWORD dwDataLen,HCRYPTKEY hImpKey,DWORD dwFlags,HCRYPTKEY* phKey);
В качестве ключей экспорта/импорта могут использоваться либо ключевая пара RSA (с типом AT_KEYEXCHANGE), либо симметричный сеансовый ключ. Параметр dwBlobType зависит от того, какой ключ экспортируется (импортируется), и задает тип структуры, в которую помещается экспортируемый ключ. Для открытого ключа это PUBLICKEYBLOB, и ключ экспорта/импорта при этом лишен смысла и должен быть нулем. Для закрытого ключа это PRIVATEKEYBLOB , и в качестве ключа экспорта может использоваться сеансовый ключ. Для сеансового ключа это обычно SIMPLEBLOB (бывает еще OPAQUEKEYBLOB и SYMMETRICWRAPKEYBLOB , но мы их рассматривать не будем), а экспортируется он, как правило, на открытом ключе получателя.
Описание флагов можно найти в MSDN. Я выделю среди них флаг CRYPT_OAEP, который заставляет криптопровайдера использовать формат PKCS #1 версии 2 при сохранении сессионного ключа с шифрованием RSA. Ключ, сохраненный в этом формате, затем может быть расшифрован другими системами шифрования (например, я так передавал ключ в библиотеку Crypto++). Если же этот флаг не указан, то ключ сохраняется в каком-то ведомом только CryptoAPI формате, и использовать его где-либо еще вряд ли удастся.
И, наконец, параметры pbData и pdwDataLen задают адрес и размер буфера под структуру экспортируемого ключа. Если размер структуры не известен при написании программы, то можно определить требуемый размер буфера, установив в pbData ноль. В этом случае нужный размер возвращается в pdwDataLen .
После окончания работы с ключом, его нужно уничтожить вызовом CryptDestroyKey .
ПРИМЕЧАНИЕ
При этом закрытый ключ сохраняется в контейнере (если, конечно, не использовался режим CRYPT_VERIFYCONTEXT), а сессионные ключи уничтожаются совсем.
В качестве примера рассмотрим создание и экспорт пары ключей для шифрования RSA и симметричного ключа 3DES:
//создание и экспорт пары ключей RSA if(CryptGenKey(hProv,AT_KEYEXCHANGE,1024<<16,&hKey)) //генерируем 1024-битный ключ < RSAPubKey1024 key; //эта структура описана в файле tools.h в примере rsakg DWORD dwLen=sizeof(RSAPubKey1024); if(CryptExportKey(hKey,NULL,PUBLICKEYBLOB,0,(BYTE *)&key,&dwLen)) //экспортируем ключ < //. тут что-то делаем > CryptDestroyKey(hKey); //уничтожаем ключ > //генерация и экспорт ключа 3DES if(::CryptGenKey(hProv,CALG_3DES,CRYPT_EXPORTABLE,&hKey)) //генерируем ключ для 3DES < RSA1024KeyExchBLOB kb; //описание см. в tools.h dwLen=sizeof(RSA1024KeyExchBLOB); if(::CryptExportKey(hKey,hPubKey,SIMPLEBLOB,0,(BYTE *)&kb,&dwLen)) //экспортируем ключ 3DES на публичном ключе RSA < //. > >
Рабочие примеры генерации и импорта/экспорта ключей приведены в демонстрационных проектах rsakg и encfile.
Симметричные шифры DES и 3DES
Это одни из немногих симметричных шифров, предоставляемых стандартными криптопровайдерами CryptoAPI. Поскольку DES и 3DES – это практически один и тот же алгоритм (3DES – это DES, применяемый 3 раза подряд), то мы ограничимся примером использования алгоритма 3DES.
ПРИМЕЧАНИЕ
Однако заметим, что для использования алгоритма 3DES требуется Enhanced провайдер, а для DES вполне достаточно Base. Впрочем, DES уже не является стойким по современным меркам алгоритмом, поэтому использовать его стоит лишь там, где надежность шифрования не очень критична.
Алгоритм 3DES использует разные ключи DES для каждой из своих итераций. Поэтому размер его ключа равен тройному размеру ключа DES, т.е. 192 (64*3) бита. Реально размер ключа 3DES – 168 (56*3) бит, т.к. в DES один байт ключа является контрольным для основных семи. Шифрование и дешифрование выполняются с помощью функций:
BOOL WINAPI CryptEncrypt(HCRYPTKEY hKey,HCRYPTHASH hHash,BOOL Final,DWORD dwFlags,BYTE* pbData,DWORD* pdwDataLen,DWORD dwBufLen); BOOL WINAPI CryptDecrypt(HCRYPTKEY hKey,HCRYPTHASH hHash,BOOL Final,DWORD dwFlags,BYTE* pbData,DWORD* pdwDataLen);
Параметр hHash позволяет параллельно с шифрованием/дешифрованием проводить хеширование данных для последующей электронной подписи или ее проверки. Флаг Final определяет, является ли шифруемый блок данных последним. Он необходим, поскольку данные можно шифровать по кускам, но для последнего блока всегда выполняется определенная деинициализация алгоритма (освобождаются внутренние структуры), и многие алгоритмы производят добавление (и проверку корректности при дешифровании) заполнителя (padding) после основных данных. Параметры pbData и pdwDataLen задают адрес буфера и размер шифруемых данных. Для не последнего блока данных ( Final =FALSE) размер данных должен быть всегда кратен размеру шифруемого алгоритмом блока (для 3DES и DES этот размер равен 64 битам). Для последнего блока допускается нарушение этого условия.
ПРИМЕЧАНИЕ
Заметим, что зашифрованные данные помещаются в тот же самый буфер поверх исходных.
Последний параметр функции CryptEncrypt – dwBufLen может показаться странным. Зачем нам размер буфера, если мы и так знаем размер входных данных? Однако на самом деле он необходим. Как я уже упомянул, многие алгоритмы добавляют заполнитель в последний блок после основных данных. В этом случае размер зашифрованных данных может оказаться больше, чем размер исходных данных. И результат может попросту не вместиться в буфер! Поэтому стоит заранее указать размер буфера, превышающий максимальный размер помещаемых в него открытых данных. Для DES и 3DES максимально возможный довесок составляет 64 бита, т.е. 8 байт (это я установил опытным путем).
В качестве примера шифрования приведу выдержку из демонстрационного проекта encfile:
BYTE buf[BUFFER_SIZE+8]; //8 - запас на padding while(fSize) < if(. ReadFile(hInFile,buf,BUFFER_SIZE,&dwLen,NULL)) //читаем блок данных break; dwSzLow=dwLen; if(. CryptEncrypt(hKey,hHash,fSizesizeof(buf))) //шифруем и хешируем его break; if(. WriteFile(hOutFile,buf,dwSzLow,&dwSzLow,NULL)) break; fSize-=dwLen; >
Асимметричный шифр RSA
Начиная с Windows 2000 расширенный (Enhanced) криптопровайдер поддерживает прямое шифрование данных по алгоритму RSA. Максимальный размер данных, которые можно зашифровать за один вызов CryptEncrypt , равен размеру ключа минус 11 байт. Дело в том, что при шифровании добавляется обязательный заполнитель (padding), который впоследствии проверяется при дешифрации. Соответственно, использование шифра RSA может быть целесообразно только при небольших объемах шифруемых данных (например, при обмене ключами) из-за существенного увеличения объема шифрованного текста и относительно медленной работе алгоритма RSA по сравнению с блочными шифрами.
Хеши MD5 и SHA
Хеш создается вызовом функции CryptCreateHash , принимающей на входе контекст криптопровайдера, идентификатор алгоритма ( CALG_MD5 или CALG_SHA) и хендл ключа (для хешей с ключем типа MAC и HMAC). После этого хеш можно вычислять как явно, используя функцию CryptHashData , так и неявно, передавая хэндл хеша в функцию CryptEncrypt . Использование CryptEncrypt обсуждалось в разделе про DES, поэтому остановимся на функции CryptHashData . Ее вызов может выглядеть следующим образом:
CryptHashData(hHash,(BYTE *)&data,dwLen,0);
Вычисление хеша (также как и шифрование) можно производить по частям (например, читая данные в буфер и хешируя содержимое буфера в цикле). После окончания хеширования можно либо подписать хеш (см. ниже), либо получить его значение вызовом:
CryptGetHashParam(hHash,HP_HASHVAL,(BYTE *)&buf,&dwLen,0);
Размер хеша MD5 равен 128 бит или 16 байтов. Для SHA это 160 бит или 20 байтов. После получения значения хеш использовать уже нельзя. Его нужно разрушить вызовом CryptDestroyHash . Проверка хеша производится точно также, как и его создание – нужно вычислить хеш и сверить полученное значение с сохраненным:
HCRYPTHASH hHash; ::CryptCreateHash(hProv,CALG_MD5,0,0,&hHash); ::CryptHashData(hHash,(BYTE *)&data,dwLen,0); BYTE newHash[16]; dwLen=16; ::CryptGetHashParam(hHash,HP_HASHVAL,newHash,&dwLen,0); if(!memcmp(newHash,oldHash,16)) < //хеш верен > else < //хеш не верен > ::CryptDestroyHash(hHash);
Алгоритмы цифровой подписи RSA и DSS
Позволяют установить корректность данных (точнее, их хеша) и принадлежность подписи владельцу закрытого ключа. Функции CryptoAPI позволяют подписывать только хеши, но не сами данные. Хеш предварительно должен быть вычислен (см. предыдущую главу), а затем подписан с помощью функции CryptSignHash на закрытом ключе для подписи (AT_KEYEXCHANGE) находящейся в контейнере криптопровайдера! Проверка подписи осуществляется на открытом ключе, который нужно предварительно импортировать:
//Вычисление подписи ::CryptSignHash(hHash,AT_SIGNATURE,NULL,0,buf,&dwLen); // Проверка подписи if(::CryptVerifySignature(hHash,buf,1024/8,hPubKey,NULL,0)) < // Верная подпись > else < // Неверная подпись или хеш > Размер подписи равняется размеру ключа RSA или DSS, соответственно.
Практический пример применения подписи можно увидеть в демонстрационном проекте encfile. Вычисление/проверка подписи RSA и DSS выполняется одинаково, однако для работы с подписью DSS нужно использовать Microsoft DSS Cryptographic Provider ( MS_DEF_DSS_PROV ,тип PROV_DSS ). Кроме того, подпись DSS работает только с алгоритмом хеширования SHA.
Криптографические классы в .NET
Большая часть криптографических классов (не абстрактных) .NET базируется на криптопровайдерах CryptoAPI. Однако имеются и исключения (например, SHA256Managed). В принципе, иерархия классов .NET позволяет абстрагироваться от конкретной реализации алгоритма, что может обеспечить простой переход на не привязанные к CryptoAPI классы в будущем. К сожалению, документация .NET по криптографическим классам, мягко говоря, оставляет желать лучшего. Поэтому часть из написанного далее следует воспринимать как собственные мысли и догадки автора (иногда полученные в ходе активного наступания на грабли).
Симметричные шифры DES, 3DES, Rijndael
Симметричные блочные шифры представлены в .NET классами DESCryptoServiceProvider , TripleDESCryptoServiceProvider , RijndaelManaged . Все эти классы являются потомками абстрактного класса SymmetricAlgorithm, описывающего все семейство блочных алгоритмов с симметричными ключами. Класс описывает свойства, позволяющие манипулировать основными параметрами алгоритма: размером блока, режимом работы, инициализационным вектором, ключом и другими. И методы CreateEncryptor и CreateDecryptor , возвращающие контексты (интерфейс ICryptoTransform ) для криптографических трансформаций данных. Также имеются методы GenerateKey и GenerateIV для генерации ключей и инициализационных векторов. Конкретные реализации наследуются от этого класса (возможно, через другие абстрактные классы – например, DESCryptoServiceProvider наследуется от класса DES , унаследованного от SymmetricAlgorithm ). Использование симметричных шифров демонстрируется в примере symmetric. Собственно шифрование выполняется следующим кодом:
private SymmetricAlgorithm alg; alg=(SymmetricAlgorithm)RijndaelManaged.Create(); //пример создания класса RijndaelManaged PasswordDeriveBytes pdb=new PasswordDeriveBytes(Password.Text,null); //класс, позволяющий генерировать ключи на базе паролей pdb.HashName="SHA512"; //будем использовать SHA512 int keylen=(int)KeySize.SelectedItem; //получаем размер ключа из ComboBox’а alg.KeySize=keylen; //устанавливаем размер ключа alg.Key=pdb.GetBytes(keylen>>3); //получаем ключ из пароля alg.Mode=CipherMode.CBC; //используем режим CBC alg.IV=new Byte[alg.BlockSize>>3]; //и пустой инициализационный вектор ICryptoTransform tr=alg.CreateEncryptor(); //создаем encryptor FileStream instream=new FileStream(inFile.Text,FileMode.Open,FileAccess.Read,FileShare.Read); FileStream outstream=new FileStream(outFile.Text,FileMode.Create,FileAccess.Write,FileShare.None); int buflen=((2<<16)/alg.BlockSize)*alg.BlockSize; byte []inbuf=new byte[buflen]; byte []outbuf=new byte[buflen]; int len; while((len=instream.Read(inbuf,0,buflen))==buflen) < int enclen=tr.TransformBlock(inbuf,0,buflen,outbuf,0); //собственно шифруем outstream.Write(outbuf,0,enclen); > instream.Close(); outbuf=tr.TransformFinalBlock(inbuf,0,len); //шифруем финальный блок outstream.Write(outbuf,0,outbuf.Length); outstream.Close(); alg.Clear(); //осуществляем зачистку
Как можно видеть, ничего сложного в процессе шифрования/дешифрования нет. Использование базового класса SymmetricAlgorithm позволяет свести всю привязку к конкретному алгоритму к одной строчке – созданию экземпляра класса нужного алгоритма.
Стоит, однако, обратить внимание на необходимость явного задания инициализационного вектора ( IV ), поскольку, в отличие от CryptoAPI, он не инициализируется нулем по умолчанию, а выбирается случайно.
На вторые возможные грабли я наступил в коде дешифрования. Размер расшифрованных данных для не финального блока может быть меньше размера шифротекста. Ни с чем подобным в CryptoAPI я не сталкивался.
Наряду с самостоятельным чтением файла и шифрованием его по блокам, возможен еще вариант с использованием стрима CryptoStream . При этом вы создаете CryptoStream , передавая ему на входе стрим для записи и интерфейс трансформации, а затем просто пишете в этот стрим свои данные. Этот вариант описан в документации по .NET Framework, поэтому я не буду подробно на нем останавливаться.
Асимметричные шифры и цифровая подпись: RSA и DSA
Аналогично симметричным шифрам, все классы асимметричных шифров в .NET унаследованы от абстрактного базового класса AsymmetricAlgorithm . Конкретная реализация представлена классами RSACryptoServiceProvider и DSACryptoServiceProvider . Увы, здесь базовый класс уже не обеспечивает стандартных механизмов шифрования/дешифрования и ЭЦП, так что приходится иметь дело с конкретной реализацией. И тут дело опять не обошлось без сюрпризов. Первым сюрпризом является то, что нет стандартного способа сохранить приватный ключ RSA в файл. Мне пришлось самому организовывать шифрование ключа по паролю. Вторым, гораздо более неприятным, сюрпризом оказывается факт, что
Заявленные в классах RSACryptoServiceProvider и DSACryptoServiceProvider методы SignHash не работают. Вообще! При попытке передать в них хеш, сформированный с помощью MD5CryptoServiceProvider или SHA1CryptoServiceProvider , всегда вываливается исключение.
Поэтому приходится использовать классы RSAPKCS1SignatureFormatter и DSASignatureFormatter .
Третий (но не последний) веселый сюрприз – в описании метода Encrypt класса RSACryptoServiceProvider можно найти упоминания о максимальном размере куска данных, который можно зашифровать. Там утверждается, что для Win2k с установленным 128-битным шифрованием этот размер равен /8-11 байтов.
ПРЕДУПРЕЖДЕНИЕ
Не верьте этому! При попытке подсунуть блок данных длиной в 117 байт при длине ключа 1024 бита вы получите исключение. У меня получилось, что максимальный размер блока данных при таком размере ключа равен 87 байтам, т.е. на 30 байт меньше заявленного.
Последние два сюрприза чуть не повергли меня в состояние глубокой депрессии, т.к. я уже почти решил, что класс RSACryptoServiceProvider неработоспособен в принципе. Вот эти два перла из коллекции ошибок класса RSACryptoServiceProvider .
Метод ImportParameters , принимающий на входе структуру RSAParameters , содержащую публичный или приватный ключ, модифицирует эту структуру, хотя по нормальной человеческой логике и по документации он не имеет права этого делать.
Метод Decrypt , обратный методу Encrypt , не может расшифровать зашифрованный блок данных, если его первоначальный размер был больше 86 байтов (для 1024-битных ключей). Т.е. вы можете зашифровать блок из 87 байтов, но потом вы не сможете его расшифровать.
В общем, по моему нескромному мнению, классу RSACryptoServiceProvider нужно присудить заслуженную премию, как самому кривому из всех классов .NET. Тем не менее, хорошо то, что хорошо кончается. Я все-таки сумел найти и обойти все эти ошибки, и на свет все-таки родился пример (см. Asymmetric.zip), демонстрирующий прямое шифрование RSA, цифровую подпись RSA и DSA и хеширование в .NET.
Чтобы закончить рассмотрение асимметричных шифров в .NET, рассмотрим куски кода, отвечающие за генерацию ключей, шифрование, дешифрацию и цифровую подпись:
//генерация ключей: новый ключ генерируется автоматически при создании экземпляра класса RSACryptoServiceProvider rsa=new RSACryptoServiceProvider(1024); //1024-битный ключ //Экспорт ключа RSAParameters rp=rsa.ExportParameters(true); //экспорт закрытого ключа. Для открытого нужно передавать false //Импорт ключа rsa.ImportParameters(rp); //будьте внимательны. Этот вызов портит значение rp //шифрование блока byte []enc=rsa.Encrypt(buf,true); //шифрование RSA/OAEP //дешифрование блока rsa.Decrypt(enc,true); //дешифрация RSA/OAEP //создание цифровой подписи RSA AsymmetricSignatureFormatter sf; sf=(AsymmetricSignatureFormatter)new RSAPKCS1SignatureFormatter(rsa); //создаем форматер sf.SetHashAlgorithm("MD5"); //выбираем алгоритм хеширования sig=sf.CreateSignature(Hash); //создаем подпись (хеш должен быть уже посчитан ранее) //проверка цифровой подписи RSA AsymmetricSignatureDeformatter df; df=(AsymmetricSignatureDeformatter)new RSAPKCS1SignatureDeformatter(rsa); //создаем деформатер df.SetHashAlgorithm("MD5"); if(df.VerifySignature(Hash,sig)) //проверяем подпись < //подпись верна > else < //подпись неверна >
В качестве еще одного замечания стоит упомянуть, что хранить закрытые ключи RSA вне контейнеров CryptoAPI, пусть даже и временно, плохо. Их может перехватить злоумышленник. Также не стоит брать пример с моего кода сериализации закрытых ключей в файл – он был написан только для демонстрации, и сохраняет в файл много ненужной информации о типах данных, которая, теоретически, может упростить задачу дешифрование файла с ключом для злоумышленника.
Обмен симметричными ключами
За обмен сессионными ключами в .NET отвечают классы RSAOAEPKeyExchangeFormatter/Deformatter и RSAPKCS1KeyExchangeFormatter/Deformatter . Они унаследованы от базовых классов AsymmetricKeyExchangeFormatter/Deformatter , предоставляющих методы CreateKeyExchange и DecryptKeyExchange для шифрования и дешифрации сессионных ключей, соответственно. Рассмотрим передачу сессионного ключа на небольшом примере:
RSACryptoServiceProvider rsa1=new RSACryptoServiceProvider(1024); //получатель ключа RSAParameters rp=rsa1.ExportParameters(false); Console.WriteLine("Passing public key to sender. "); //передаем открытый ключ отправителю //.. RSACryptoServiceProvider rsa2=new RSACryptoServiceProvider(1024); //отправитель ключа Console.WriteLine("Importing receiver's public key. "); //импортируем открытый ключ получателя rsa2.ImportParameters(rp); AsymmetricKeyExchangeFormatter kf=(AsymmetricKeyExchangeFormatter)new RSAOAEPKeyExchangeFormatter(rsa2); byte []key=new Byte[16]; //128-битный ключ byte []enckey=kf.CreateKeyExchange(key); Console.WriteLine("Sending encrypted session key to receiver. "); //передаем зашифрованный сессионный ключ получателю //. AsymmetricKeyExchangeDeformatter kd=(AsymmetricKeyExchangeDeformatter)new RSAOAEPKeyExchangeDeformatter(rsa1); //Расшифровываем ключ byte []deckey=kd.DecryptKeyExchange(enckey); for(uint i=0;i<16;i++) if(deckey[i]!=key[i]) < Console.WriteLine("Key exchange failed"); return; > Console.WriteLine("Key exchange succeeded");
Как можно видеть, здесь нет ничего сложного. Самым проблемным, пожалуй, является передача публичного ключа от получателя отправителю и зашифрованного сессионного ключа в обратную сторону.
Хеши
Все классы хешей MD5CryptoServiceProvider , SHA1CryptoServiceProvider , SHA1Managed , и т. д. в .NET унаследованы от базового класса HashAlgorithm , предоставляющего два различных пути для вычисления хеша – метод ComputeHash , вычисляющий хеш блока данных или потока за один раз, и методы TransformBlock и TransformFinalBlock , позволяющие вычислить хеш, разбивая данные на части. Вычисление хеша при помощи ComputeHash выглядит следующим образом:
HashAlgorithm ha=(HashAlgorithm)new MD5CryptoServiceProvider(); byte []hash=md5.ComputeHash(data,0,data.Length); //считаем хеш
Вариант с TransformBlock хорошо подходит для хеширования с параллельным шифрованием. Пример такого хеширования можно найти в примере Asymmetric. Вычисление хеша этим способом производится в цикле, причем на последней итерации нужно вызвать TransformFinalBlock :
ha=(HashAlgorithm)new SHA1CryptoServiceProvider(); while((len=ins.Read(inbuf,0,MaxRSABlockSize))==MaxRSABlockSize) //читаем файл поблочно < ha.TransformBlock(inbuf,0,MaxRSABlockSize,outbuf,0); //считаем хеш от блока данных > byte []hash=ha.TransformFinalBlock(inbuf,0,len); //досчитываем хеш от последнего куска
Можно считать хеш целиком внутри цикла, а TransformFinalBlock вызвать для массива нулевой длины.
Цифровая подпись
Ввиду неработоспособности метода SignHash классов RSACryptoServiceProvider и DSACryptoServiceProvider, пары классов RSAPKCS1SignatureFormatter/Deformatter и DSASignatureFormatter/Deformatter , похоже, являются единственным вариантом создания цифровой подписи. Обе пары классов унаследованы от классов AsymmetricSignatureFormatter/Deformatter , предоставляющих стандартный интерфейс создания и верификации цифровой подписи – методы CreateSignature и VerifySignature . Перед вычислением или проверкой цифровой подписи нужно обязательно установить алгоритм хеширования, который будет использоваться в процессе работы, с помощью вызова SetHashAlgorithm . RSAPKCS1SignatureFormatter понимает два алгоритма хеширования – MD5 и SHA1, а DSASignatureFormatter — только SHA1. Пример создания и проверки подписи уже был приведен в разделе, посвященном асимметричным шифрам в .NET, и повторять его здесь я не буду.
Заключение
И CryptoAPI, и .NET предоставляют богатый набор средств шифрования, позволяющих организовать собственную систему защиты данных без использования сторонних средств. В .NET, правда, эти средства пока плохо отлажены и документированы, но использовать их все равно можно. Основными препятствиями на пути использования средств CryptoAPI и .NET могут стать отсутствие на платформах ниже Windows 2000 поддержки “сильной” криптографии и требования, налагаемые Российским законодательством на средства шифрования, используемые в коммерческой деятельности. По Российскому законодательству эти средства обязательно должны быть сертифицированы ФАПСИ. Но ни один из алгоритмов, реализованных в CryptoAPI и .NET, не является сертифицированным. Правда, это не мешает разработчикам shareware-программ использовать алгоритмы типа RSA для защиты своих продуктов.
Ссылки
- Bruce Schneier, Applied Cryptography 2 nd edition.
- MSDN, раздел Cryptography
Эта статья опубликована в журнале RSDN Magazine #1. Информацию о журнале можно найти здесь

