Crypto API

Добрый день ! Подскажите ,пожалуйста, как средствами CryptoApi открыть сертификат с RuToken ? Т.е. хочется сделать CertOpenStore, но чтобы она открыла именно токен, находящийся на данный момент в компьютере.

Re: Crypto API

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

Дело в том, что функция CertOpenStore работает с локальным хранилищем.
В рамках интерфейса CryptoAPI в драйверах Rutoken реализован интерфейс Cryptographic Service Provider (CSP), с помощью которого можно получить сертификат как свойство ключевой пары, и зарегестрировать его в локальном хранилище, в нужном разделе.
Кроме того, сертификаты регистрируются в локальном хранилище автоматически после подключения Rutoken по средствам Certificate Propogation Service.

Михаил Курский
Руководитель отдела разработки прикладного ПО Rutoken, Компания "Актив"

Re: Crypto API

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

Re: Crypto API

Может сохранять с зашифрованными данными открытые ключи и сравнивать его с экспортированным с токена посредствам Active CSP ?

Re: Crypto API

Это можно сделать по средствам CSP.
1. Перебрать доступные контейнеры с подключенного Rutoken:
    1.1 CryptAcquireContext(... CRYPT_VERIFYCONTEXT ...);
    1.2 CryptGetProvParam(... PP_ENUMCONTAINERS...);
    1.3 Для каждого контейнера получить хендл ключевой пары - CryptGetUserKey;
    1.4 Получить у ключа свойство сертификата - CryptGetKeyParam(... KP_CERTIFICATE...);
2. Создать контекст из данных сертификата - CertCreateCertificateContext.
3. Получить из контекста сертификата необходимые свойства - CertGetCertificateContextProperty, сравнить с имеющимися.
4. Расшифровать данные по средствам CryptAPI и CSP.

Единственно, не рекомендую Вам использовать открытый ключ ассиметричного алгоритма для шифрования конечных данных - это очень медленная операция по сравнению с симетричным шифрованием.
Эфективнее создать по средствам CSP сессионный ключ, зашифровать им данные, а потом выгрузить его из CSP в зашифрованном на открытом ключе RSA, и сохранить рядом с зашифрованными данными. И в открытом виде положить рядом информацию о владельце сертификата.
О использовании сессионных ключей лучше посмотреть здесь: http://msdn.microsoft.com/en-us/library … S.85).aspx

Михаил Курский
Руководитель отдела разработки прикладного ПО Rutoken, Компания "Актив"

Re: Crypto API

Спасибо большое, буду пробовать ! Я шифрую от 10 до 24 байт, так что нет смысла связываться с сессионными ключами.

Re: Crypto API

Все получилось, спасибо большое !

Re: Crypto API

Здравствуйте.

Я никак не могу получить хендл ключевой пары в CryptGetUserKey - что нужно указать в параметре dwKeySpec?
Что бы я не указывал, ответ один - NTE_NO_KEY (The key requested by the dwKeySpec parameter does not exist.)

Re: Crypto API

Это зависит от свойств ключевой пары в контейнере.
Тип ключевой пары контейнера задается на этапе его создания, либо указан в шаблоне сертификата.
Возможных варианта два: AT_KEYEXCHANGE и AT_SIGNATURE.
Если при обоих значениях выдается ошибка NTE_NO_KEY, значит в контейнере отсутствует ключевая пара - она либо не сгенерирована, либо не записана в контейнер.

Михаил Курский
Руководитель отдела разработки прикладного ПО Rutoken, Компания "Актив"

Re: Crypto API

Да, ошибка при обоих значениях AT_KEYEXCHANGE и AT_SIGNATURE.
Как тогда можно получить сертификат (имя ключевого контейнера известно)?

Re: Crypto API

Сертификат, в рамках CryptoAPI, это свойство ключевой пары - KP_CERTIFICATE.
Если в контейнере нет ключей, то контейнер пуст - в нем не может быть сертификата.
Это возможно только в том случае, если ключ либо не был сгенерирован, либо не был записан в контейнер.

Михаил Курский
Руководитель отдела разработки прикладного ПО Rutoken, Компания "Актив"

Re: Crypto API

Я на некоторое время оставил этот проект и уже не все помню, но, по моему, есть некоторые особенности использования  CryptAcquireContext(... CRYPT_VERIFYCONTEXT ...); в части использования параметра CRYPT_VERIFYCONTEXT. Я работал с сертификатами, созданными службой сертификации Windows

Re: Crypto API

Сертификат в контейнере есть, его можно посмотреть через консоль КриптоПро CSP

Re: Crypto API

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

В других CSP это может быть не так.

Михаил Курский
Руководитель отдела разработки прикладного ПО Rutoken, Компания "Актив"

Re: Crypto API

Да действительно дело было в параметре CRYPT_VERIFYCONTEXT. Без него в функции CryptAcquireContext все получилось.