CAPICOM и КриптоПро CSP
Опубликовано Станислав Королев on 2015-07-15 11:06

Подходит ли CAPICOM для шифрования с открытым ключом, используя КриптоПро CSP? Если да, то можно ли найти примеры?

Объекты для шифрования сообщений

На нашем сайте есть ссылка на страницу Microsoft, где лежит CAPICOM. В состав дистрибутива входят примеры использования. Для шифрования нужно пользовать объект EnvelopedData. Объект EncryptedData работать с ГОСТами не будет, т.к. шифрует на пароле, алгоритмы шифрования зафиксированы в коде. Поведение объекта EvelopedData аналогично CryptEncryptMessage из CryptoAPI, и на выходе формируется сообщений формата PKCS#7 EnvelopedData.

Отсутствие сертификата подписчика в подписанном сообщении

CAPICOM в первую очередь ориентирован на работу с сертификатами и всем, что с ними связано (хранилища, списки отзыва), а не с ключами или ключевыми контейнерами. Поэтому и класс CAPICOM.SignedData спроектирован и функционирует так, что сертификат подписчика всегда ищется в подписанном сообщении. При его отсутствии выдается соответствующая ошибка «The signer is not found in the signed message (0x80880251)». Никак обойти это ограничение нельзя – SignedData не принимает в качестве параметров сертификат (а тем более коллекцию сертификатов или хранилище), который нужно использовать для проверки. Самое простое решение – добавлять сертификат на этапе формирования подписи. CAPICOM сам всегда так поступает, а в CryptoAPI несложно передать сертификат в качестве параметра подписывающей функции.

Подпись текста в кодировке ANSI, строки нечётной длины

Строковые параметры методов COM объектов, работающих через IDispatch, являются, по сути своей, юникодными строками UCS-2 LE – на каждый символ строки приходится 2 байта памяти. Поэтому, при передаче параметры явно или неявно преобразовываются к такому виду. Если в системе только одна сторона использует CAPICOM а вторая использует, например, CryptoAPI, то может возникнуть проблема несовпадения исходного документа для подписи и проверки.

Пример – одна сторона подписывает файл размером 3 байта, содержащий строку «123», с помощью ПО, написанного на Visual Basic 6 с использованием CAPICOM и отправляет его для проверки с неприсоединенной подписью. Вторая сторона для проверки использует ПО, написанное на C++ с использованием CryptoAPI (например, утилиту коммандной строки) и при проверке подписи получает ошибку NTE_BAD_SIGNATURE (0x80090006), хотя исходный документ не менялся. Причина ошибки в том, что в VB при чтении файла а затем при передаче параметров строка «123» была преобразована к юникоду, т.е. реально было подписано 6 байт «00 31 00 32 00 33», а проверено – 3 «31 32 33». Локализовать эту проблему можно, создав присоединенную подпись и проверив ее с помощью утилиты csptest (входит в состав КриптоПро CSP) – csptest –sfsign –verify –in <файл с подписанным сообщением> -out data.txt –base64 и затем сравнив содержимое полученного файла data.txt с исходным документом.

Решение этой проблемы – при необходимости в языках, которые делают неявное преобразование (как VB, .NET) всегда преобразовывать подписываемый и проверяемый текст к ANSI, если в системе строго не оговорено обратное. В VB для этого можно использовать функцию StrConv или написать свою для побайтного преобразования с использованием метода ByteArrayToBinaryString класса Utilities библиотеки CAPICOM. В .NET подобное преобразование сделать сложнее, и для этого не подойдёт метод ByteArrayToBinaryString, поскольку возвращаемое этим методом значение будет преобразовано в .NET-тип System.String, заточенный под юникодные строки. Ошибка преобразования возникнет, если в исходном массиве содержится нечётное число байт. Возможным решением проблемы является написание специального маршалера для передачи таких строк из .NET в CAPICOM и обратно. Пример интероп-ассембли для CAPICOM, в которой реализован такой маршалер, а в интерфейсе методов, подверженных описанной ошибке преобразования, тип System.String заменён на System.Byte[], можно взять здесь. Для использования этой интероп-ассембли необходимо в проекте явно сослаться на неё вместо CAPICOM.

(2 плюсик(ов))
Класс!
Не очень :(

Коментарии (0)