Использование примитивной функции с ключом, хранящимся в Microsoft KSP

Мой вопрос касается варианта использования с CNG API и провайдерами Microsoft. Я не пишу пример кода, потому что я прошу вашей помощи о том, как лучше использовать CNG API в моем приложении по сравнению с CSP API.

Я построил приложение, которое использует симметричные ключи, хранящиеся с помощью этих шагов:

  • перечислять сертификаты в магазине «Мой», используя CertFindCertificateInStore
  • для каждого найденного сертификата, запрашивая информацию о секретном ключе, используя CertGetCertificateContextProperty
  • для каждой найденной информации личного ключа, сохраняя имя провайдера pwszProvName и название контейнера pwszContainerName

Затем, когда ключ найден, мое приложение выполняет функцию подписи, используя закрытый ключ, найденный с помощью CSP API:

  • Инициализируйте работу провайдера, используя CryptAcquireContext с pwszProvName а также pwszContainerName
  • Вычислить подпись с использованием функций CSP: CryptCreateHash, CryptHashData а также CryptSignHash

Все в порядке с функцией CSP.

Теперь я пробую подпись с использованием CNG API:

  • Инициализируйте работу провайдера, используя NCryptOpenStorageProvider с pwszProvName
  • Открытый поставщик алгоритма с использованием функции CNG BCryptOpenAlgorithmProvider не удается с STATUS_NOT_FOUND

Эта ошибка возникает, когда закрытый ключ хранится в Microsoft Software Key Storage Provider.
Читая документацию Microsoft, я понимаю, что тип провайдера — провайдер KSP, и он работает только с управлением ключами. Вот почему это не помогает, когда я пытаюсь примитивную функцию, мне нужно использовать «Primitive Provider».

Я нашел способ использовать поставщика CNG, выполнив следующие действия:

  • Windows Server 2008: создайте шаблон сертификата с требованием поставщика (на вкладке «шифрование»). И единственный доступный поставщик — это «Поставщик хранилища ключей программного обеспечения Microsoft».
  • Windows 7: пользователь запрашивает генерацию ключа, ключ хранится в Microsoft KSP.

Итак, вот мои вопросы:

  • Это нормально, я не могу выполнить примитивную функцию с «Microsoft Software Key Storage Provider»?

  • Если я не могу выполнять примитивные функции (подпись, шифрование, дешифрование, хеширование) с Microsoft KSP (который является поставщиком KSP), как я могу сохранить свой закрытый ключ и управлять им в Microsoft Primitive Provider?

Моя проблема здесь в том, что с CSP API поставщик Microsoft CSP по умолчанию выполняет функцию подписи (и расшифровки, шифрования и т. Д.). Но с CNG API поставщик по умолчанию выполняет только управление хранилищем ключей.

2

Решение

Для асимметричных ключей функциональность, поддерживаемая поставщиком хранилища ключей CNG, сравнима с функциональностью примитивного поставщика, за исключением того факта, что KSP (поставщик хранилища ключей) позволяет сохранять и загружать ключи.

Фактически, вызовы KSP API для выполнения криптографических операций выглядят почти так же, как и примитивные, за исключением того, что KSP начинаются с N и примитивные начинаются с B,

Например:

Какие является в KSP отсутствует симметричная функциональность (включая хеширование), и это может быть причиной возникновения путаницы. По сравнению с CAPI (CSP / Crypto API) функции подписи CNG немного более низкоуровневые — сначала вы хэшируете данные отдельно, а затем передаете этот хеш-байт в NCryptSignHash (без дескриптора хеш-объекта, как в CAPI).

Чтобы повторить, поскольку это является источником путаницы для людей, приходящих из CAPI, вы можете хэшировать с любым примитивным провайдером, MS_PRIMITIVE_PROVIDER или стороннего поставщика, а затем передать результат любому поставщику хранилища ключей NCryptSignHashпотому что это просто байты данных, не имеет значения, кто сделал хеширование. NCRYPT_KEY_HANDLE перешел к NCryptSignHash определяет, какой KSP используется для подписания; нет эквивалента СПГ HCRYPTHASH перешел к NCryptSignHash,

Таким образом, если вы хотите подписать с KSP, вы должны хешировать сообщение, которое будет подписано сначала примитивным провайдером (используя BCryptCreateHash/BCryptHashData/BCryptFinishHash) и передать результат NCryptSignHash,

1

Другие решения