Public Key Cryptography: осваиваем открытые ключи на практике — «Хакер»

Xml-подпись

Реализация целостности и невозможность отказа обеспечиваются посредством цифровых XML -подписей ( XML-Signature ). XML -подпись служит для проверки целостности принятых сообщений и полной либо частичной аутентификацииXML -документов. Стандарт цифровой подписиXML-SignatureSyntax and Processing (сокращенно XMLDSIG от eXtensible Markup LanguageDigital SIGnature specification ) разработан консорциумом W3C в 2002 году [11.1].

Он определяет синтаксис представления цифровых подписей и правила их обработки, а также сервисы, обеспечивающие целостность данных (в том числе документов XML в передаваемом сообщении или вне его), установление подлинности сообщения и подписавшего его лица.

Для реализации функциональности, связанной с XML -подписью, .NET Framework предоставляет набор готовых классов, расположенных в пространстве имен System.Security.Cryptography.Xml.

Применительно к XML -документам этот стандарт не является чем-то принципиально новым. Его специфика состоит в описании того, как цифровые подписи могут быть использованы внутри XML -документов.

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

От других подобных стандартов XML-Signature отличается возможностью распространения не на весь документ, а только на его часть. Разделение подписи на части обеспечивает гибкость работы с документами с долгой историей, на протяжении которой отдельные части могли создаваться и подписываться независимо.

Данные, заверенные подписью, могут содержаться внутри самого документа XML или размещаться в других документах. На рис. 11.1 схематически показаны три различных способа реализации XML -подписи [11.2]:

  1. «Изолированная» подпись ( Detachedsignature ) вычисляется по объекту данных, который является внешним по отношению к элементу XMLSignature. Элемент Signature и «подписанный» объект могут физически располагаться либо в разных XML -документах, либо внутри различных тэгов одного документа;
  2. «Охватывающая» подпись ( Enveloping signature, Wrappedsignature ) вычисляется по элементу Object, расположенному внутри элемента Signature ;
  3. «Встроенная» подпись ( Envelopedsignature, Embeddedsignature ) вычисляется по XML -контенту, содержащему элемент Signature.

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

С его помощью получатель может проверить полученную подпись. Перед подписанием XML -документ приводится к канонической форме, определенной правилами разработанной W3C рекомендации «CanonicalXML» [11.6].

Генераторы псевдослучайных чисел

Качественный ключ, предназначенный для использования в рамках симметричной криптосистемы, представляет собой случайный двоичный набор. Если требуется ключразрядностью n, в процессе его генерации с одинаковой вероятностью должен получаться любой из 2^nГенерация ключей для асимметричных криптосистем — процедура более сложная, т.к. ключи, применяемые в таких системах, должны обладать определенными математическими свойствами. Например, в случае системы RSAмодульшифрования представляет собой произведение двух больших простых чисел.

Генераторы случайных чисел — место, в котором часто ломаются криптографические системы [10.8]. Это означает, что, если для генерации ключей используется криптографический слабый алгоритм, независимо от используемого шифра вся система будет нестойкой.

Рассмотрим понятие криптографически стойкого генератора псевдослучайных кодов, или, для краткости, псевдослучайного генератора, которое было введено Блюмом и Микали [10.10]. Пусть g : {0, 1}^n to {0,1}^{q(n)} функция, вычислимая за полиномиальное от n время, q(n) полином. Такая функция называется генератором. Генераторgпсевдослучайным [10.9], если порождаемые им последовательности неотличимы никаким полиномиальным вероятностным алгоритмом от случайных последовательностей той же длины q(n) 10.13] и Хостад [10.12] доказали, что псевдослучайные генераторы существуют тогда и только тогда, когда существуют односторонние функции.

Лучший способ генерации множества случайных битов — извлечение их из естественно случайных событий реального мира [10.14]. Генераторы псевдослучайных чисел . NET Framework используют в качестве начальной информации для генерации криптографически стойкой последовательности набор случайных значений, получаемых из разных частей операционной системы (см. [10.5]).

Более высокое качество формирования псевдослучайных последовательностей обеспечивает наличие специальной аппаратуры, использующей события физической природы для получения случайных величин. В настоящее время некоторые процессоры имеют встроенные микросхемы, предназначенные для генерации случайных битов; псевдослучайные генераторы .NET Framework обеспечивают возможность использования таких аппаратных средств для повышения качества генерируемых последовательностей.

В объектной модели .NET Framework классы, реализующие функциональность генераторов псевдослучайных чисел, наследуются от класса RandomNumberGenerator. По умолчанию в качестве реализации класса RandomNumberGenerator используется классRNGCryptoServiceProvider, который является оболочкой псевдослучайного генератора, предоставляемого WindowsпоCryptoAPI [10.15].

В отличие от класса System.Random в .NET Framework или функций rand () и random () в библиотеке языка C, псевдослучайный генераторCryptoAPI не создает воспроизводимых последовательностей.

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

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

Читайте также:  Как установить сертификат ЭЦП на компьютер: инструкция по установке электронной подписи

Например, классPasswordDeriveBytes.NET Framework реализует алгоритм, который является расширением алгоритма PBKDF 1, описанного в стандарте PKCS #5 v2.0 [10.16].

Этот алгоритм принимает на вход 4 параметра — пароль, значениеSalt, количество итераций и тип алгоритма хеширования (термин Salt связан в основном с процессом хеширования — это некое случайное число, которое добавляется к хешируемому тексту, чтобы повысить надёжность хеша и предотвратить атаки по словарю). Алгоритм вычисляет хеш-функцию от комбинации пароля и значения Salt и в результате возвращает последовательность байтов, пройдя указанное количество итераций.

Картина мира

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

Информация, необходимая для работы PKI, содержится в сертификате X.509. В PKI участвуют как минимум три стороны: Алиса, Боб и удостоверяющий центр (УЦ). У Алисы и Боба есть сертификаты с закрытым ключом, подписанные так называемым корневым сертификатом УЦ.

Упрощенная структура PKI
Упрощенная структура PKI

Проверка подписи и декодирование

А теперь, дорогой читатель, представь, что ты большой начальник и должен принять важное стратегическое решение на основе отчета, который тебе прислал сотрудник по электронной почте. Для твоего удобства отчет был подписан открепленной подписью. Открыв почту и скачав отчет, ты, как опытный, знающий жизнь человек, не спешишь принимать на веру содержимое отчета и проверяешь подпись.

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

Если пользователь прислал тебе отчет в виде прикрепленной подписи, тебе для чтения придется его декодировать:

public bool VerifyAttached(byte[] dataToVerify) {
    try {
        var cms = new SignedCms();
        cms.Decode(dataToVerify);
        foreach (var signer in cms.SignerInfos) {
            signer.CheckSignature(true);
        }
        return true;
    }
    catch (CryptographicException) {
        return false;
    }
}

public byte[] Decode(byte[] signedCms) {
    var cms = new SignedCms();
    cms.Decode(signedCms);
    return cms.ContentInfo.Content;
}

Нетрудно догадаться, что и тут разработчики .NET Framework подложили нам свинью. Не можем мы проверить подпись большого файла! По той же самой причине — OutOfMemoryException. Но и эту проблему несложно решить, обратившись к магии MS Crypto API. Так как код поточной проверки подписи достаточно длинный, остановлюсь на основных моментах:

Пространство имен cryptography в .net framework

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

Криптографическая объектная модель.NET Framework разработана с учетом этих требований. .NET Framework включает набор криптографических сервисов, расширяющих аналогичные сервисы Windows через CryptoAPI. Пространство именSystem.Security.Cryptography общеязыковой исполняющей среды ( common language runtime, CLR ) в Microsoft .

NET открывает программный доступ к самым разнообразным криптографическим сервисам, с помощью которых приложения могут шифровать и дешифровать данные, обеспечивать их целостность, а также обрабатывать цифровые подписи и сертификаты [10.1].

Некоторые из таких сервисов применяются непосредственно в самой .NET Framework (например, для поддержки аутентификации в ASP.

NET ). Пространство именSystem.Security.Cryptography разделено между двумя сборками — mscorlib.dll и System.Security.dll, причем сборкаmscorlib.dll неявно подключается по умолчанию и предоставляет классы с алгоритмами таких операций, как шифрование и создание хешей, а дополнительно подключаемая сборкаSystem.Security.dll позволяет получить доступ к функциональности, связанной с XML -подписью, модификацией ACL (списков управления доступом в Windows ), использованием интерфейса DPAPI, созданием кодов аутентификации на основе хешированных ключей ( HMAC ) и др.

Пространство именSystem.Security.Cryptography включает дочерние пространства имен ( Xml, X509Certificates, PKCS ) и на самом высоком уровне может быть разбито на пять основных частей (табл. 10.1) [10.2].

Главное предназначение этого пространства — предоставлять классы с алгоритмами таких операций, как шифрование и создание хешей. Категория алгоритмов реализуется на основе расширяемого шаблона ( pattern ) [10.

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

От базового абстрактного класса наследуется абстрактный класс второго уровня, предоставляющий открытый интерфейс для использования данного алгоритма. Например, SHA1 ( Secure Hash Algorithm ) представляет собой производный от HashAlgorithmкласс и содержит методы и свойства, специфичные для алгоритма SHA1.

Наконец, сама реализация алгоритма является производной от класса второго уровня; именно ее экземпляр создается и используется клиентским приложением. Криптографические библиотеки, прилагаемые к .NET Framework 2.0 и 3.

Читайте также:  ЭЦП для росреестра, электронная подпись быстро в г. Москва, Россия

0, предоставляют множество управляемых реализаций алгоритмов, а также классы-«обертки» для встроенных реализаций из CryptoAPI. К именам неуправляемых реализаций обычно добавляется суффикс » CryptoServiceProvider » (например, SHAlCryptoServiceProvider ), указывающий на то, что данная реализация на самом деле предоставляется криптопровайдером.

В имена управляемых реализаций включается суффикс » Managed » (например, SHAlManaged ). Такие реализации не опираются на CryptoAPI и содержат исключительно управляемый код.

Наличие общего абстрактного класса позволяет унифицировать доступ к свойствам и методам, специфичным для каждого типа алгоритмов. Например, для класса Rijndael свойство LegalKeySizes вернет значения 128, 192, и 256, соответствующие разрядности ключей, для которых определен данный криптоалгоритм; метод IsWeakKeyабстрактного классаTripleDES позволяет получить информацию о криптостойкости потенциального ключа, сверяя его со списком известных слабых ключей.

Таблица
10.1.
Основные элементы пространства имен Cryptography
КатегорияОписание
Алгоритм шифрованияНабор классов, применяемых для реализации алгоритмов симметричного и асимметричного шифрования, а также хеширования
Вспомогательные классыКлассы, обеспечивающие генерацию криптографически стойких последовательностей псевдослучайных чисел, выполнение преобразований, взаимодействие с хранилищем CryptoAPI и шифрование на основе потоковой модели
Сертификаты X.509Классы, определенные в пространстве имен System.Security.Cryptography.X509Certificates и предоставляющие цифровые сертификаты и (начиная с . NET 2.0 ) классы для доступа к хранилищу сертификатовWindows
Цифровые подписи XMLКлассы, определенные в пространстве имен System.Cryptography.Xml и предоставляющие цифровые подписи в XML -документах в соответствии со стандартами, опубликованными консорциумом W3C
CMS / PKCS#7Начиная с версии .NET 2.0, осуществляется управляемая поддержка упакованных CMS / PKCS сообщений непосредственно от вызовов неуправляемого кода. ( CMSCryptographicMessageSyntax — синтаксис криптографических сообщений, PKCSPublic-Key CryptographyStandard — стандарт шифрования с открытым ключом [10.3, 10.6])

Расширения криптографической объектной модели могут быть двух типов [10.5]:

Чтобы добавить поддержку нового типа алгоритмов, необходимо создать новый абстрактный класс. Родительским классом для него может быть один из классов SymmetricAlgorithm, AsymmetricAlgorithm или HashAlgorithm.

Затем нужно определить набор свойств и методов, общих для всех реализаций алгоритмов. Добавить новую реализацию в .NET Framework просто — для этого нужно создать класс-наследник абстрактного класса алгоритмов определенной категории, содержащий конкретную реализацию абстрактных методовродительского класса.

Работа с потоками

CLR использует модель программирования, основанную на потоках [10.1]. Распространенным сценарием является необходимость криптографического преобразования бинарного потока данных перед записью на диск или передаче по сетевому соединению. .NET Framework позволяет реализовать такие преобразования с использованием класса CryptoStream и объектов, реализующих интерфейсICryptoTransform. КлассCryptoStream унаследован от System.IO.Stream.

Модель ICryptoTransform представлена на рис. 10.2.ICryptoTransform соответствует математическому преобразованию над блоком данных фиксированной длины — например, шифрованию секретным ключом.

Все классы криптоалгоритмов включают методы для создания объектов, реализующих интерфейсICryptoTransform. В частности, SymmetricAlgorithm имеет два метода — CreateEncryptor () и CreateDecryptor (), которые позволяют создать объектICryptoTransform на базе ключевого материала, вектораинициализации и режима работы, указанного для данного экземпляра класса криптоалгоритма.

Преобразование реализуется посредством «заворачивания» входного потока в ICryptoTransform с использованием класса CryptoStream. На рис. 10.3 [10.

5] представлен поток данных, который в реальном времени читается из CryptoStream. CryptoStream сам по себе является потоком, но его содержимое генерируется путем последовательного применения ICryptoTransform к блокам данных. CryptoStream использует буферизованный доступ, позволяя выполнять шифрование, не заботясь о размере блока для конкретного алгоритма.

Расшифрование

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

Сертификаты x.509

Так повелось, что основным «активом» в PKI является сертификат X.509. Сертификат — это что-то вроде паспорта, он содержит информацию, позволяющую идентифицировать субъект, которому выдан сертификат (поле Subject), указывает, кем он был выпущен (поле Issuer), серийный номер сертификата и многое другое. В Windows управлять сертификатами можно с помощью оснастки «Сертификаты» (run->certmgr.msc).

Менеджер сертификатов
Менеджер сертификатов

Сертификаты хранятся в хранилищах («Личное», «Доверенные центры сертификации», «Доверенные лица»…).

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

Сертификаты удостоверяющих центров (УЦ) должны быть установлены в хранилище «Доверенные корневые центры сертификации». При установке сертификата система предлагает два варианта: выбрать хранилище автоматически либо указать вручную. Рекомендую использовать второй вариант, так как автоматика иногда устанавливает сертификат не в то хранилище.

Закрытый ключ для сертификата
Закрытый ключ для сертификата

Самое интересное о сертификате мы можем узнать на вкладке «Состав».

Состав сертификата
Состав сертификата

Обрати внимание на поля «Алгоритм подписи», «Алгоритм хеширования подписи» и «Открытый ключ». Если хочешь использовать сертификат для осуществления транзакций в России, во всех этих полях ты должен видеть слово «ГОСТ». Также следует обратить внимание на значение поля «Использование ключа» и поля «Действителен с» и «Действителен по»: первое позволит понять, возможно ли использование сертификата для выполнения нужной нам операции (шифрование, подпись), а второе и третье — возможно ли использовать данный сертификат в указанный момент времени.

Читайте также:  Каково назначение сертификата ключа ЭЦП?
Состояние сертификата
Состояние сертификата

Цель лекции

  1. Рассмотреть круг задач, на решение которых ориентирована XMLкриптография
  2. Изучить возможности XML -криптографии:
  3. Сравнить различные типы XML -подписей

Цифровая подпись

Представь, дорогой читатель, что ты занимаешься некой очень ответственной работой. И результаты своей работы отправляешь в виде отчетов, от которых в конечном итоге зависят чьи-то конкретные судьбы и жизни. Получатели твоих отчетов принимают на их основе очень важные решения, и, если ты напортачишь, вполне можешь получить срок.

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

Подпись гарантирует, что твой отчет отправлен именно тобой, а не уборщицей или сторожем. С другой стороны, ты не сможешь отказаться от авторства (это называется «неотрекаемость») и, если накосячишь в своем суперважном документе, на сторожа свалить вину не получится.

Электронная подпись применяется не только в спецслужбах и органах, но и в бизнесе. Например, для перевода пенсионных накоплений в НПФ: мы генерируем запрос на сертификат, отправляем его в удостоверяющий центр (УЦ). УЦ выпускает сертификат, мы подписываем сертификатом заявление на перевод пенсионных накоплений, отправляем — и вуаля.

Для программирования подписи необходимо ознакомиться с несколькими классами .NET Framework:

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

X509Chain certificateChain = new X509Chain {
    ChainPolicy = {
        RevocationMode = X509RevocationMode.Online,
        VerificationFlags = X509VerificationFlags.IgnoreNotTimeValid,
        RevocationFlag = X509RevocationFlag.ExcludeRoot
    }
};

bool chainOk = certificateChain.Build(certificate);
bool certNotExpired = (certificate.NotAfter >= DateTime.Now) && (certificate.NotBefore <= DateTime.Now);

Мы проверили сертификат и убедились, что он в порядке. Переходим непосредственно к подписыванию данных. Подпись бывает двух видов: прикрепленная и открепленная.

Прикрепленная и открепленная подписи
Прикрепленная и открепленная подписи

Результатом прикрепленной подписи будет CMS (Cryptography Message Syntax) — сообщение, содержащее как подписываемые данные, так и саму подпись. Открепленная подпись содержит только саму подпись. Рекомендую использовать именно открепленную подпись, потому что с ней намного меньше мороки.

В нее проще поставить метку времени, она меньше весит, так как не содержит подписываемые данные. Подписываемые данные легко открыть, посмотреть. В случае прикрепленной подписи для того, чтобы просмотреть подписанные данные, CMS-сообщение необходимо сначала декодировать.

В общем, прикрепленной подписи я рекомендую избегать всеми силами. Если потребуется передавать подпись и контент вместе, рассмотри вариант архивирования (вместо использования прикрепленной подписи используй открепленную, просто заархивируй подписываемый файл и открепленную подпись). Посмотрим на код подписи (С#):

Шифрование

Зачем нужно шифрование, все уже знают. PKI нам дает полезную плюшку: мы можем зашифровать один документ так, что расшифровать его смогут несколько получателей. Это очень удобно. Для этого нам нужно иметь сертификаты получателей.

public byte[] Encrypt(byte[] dataToEncrypt, params X509Certificate2[] recepients) {
    var contentInfo = new ContentInfo(dataToEncrypt);
    var recipientsCertificates = new X509Certificate2Collection(recepients);
    var recipients = new CmsRecipientCollection(SubjectIdentifierType.IssuerAndSerialNumber, recipientsCertificates);
    var cms = new EnvelopedCms(contentInfo);
    cms.Encrypt(recipients);
    return cms.Encode();
}

Заключение

В статье не удалось охватить все аспекты PKI, так как их очень много. Тем не менее закодить основные операции ты теперь сможешь без проблем. Разработчикам, которые умеют писать на C#, рекомендую освоить C хотя бы на базовом уровне. Это очень пригодится, когда придется работать с нативными функциями.

А до многих возможностей ОС по-другому и не добраться, так как .NET реализует весьма ограниченный набор возможностей. Например, .NET не имеет полной поддержки MS Crypto API и CNG (cryptography next geberation), поэтому тебе придется писать тонны P/invoke-кода на С# либо значительно меньше на C .

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

Краткие итоги

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector