Цитата:Чтобы запомнить пароль доступа к конейнеру
открываю контекст контейнера
CryptAcquireContext( CRYPT_SILENT )
устанваливаю пароль
CryptSetProvParam( PP_KEYEXCHANGE_PIN )
Этот код только запоминает пароль внутри контекста, проверки пароля не происходит. Поэтому, если Вы хотите закешировать контейнер (а кешируется именно полностью контейнер, а не пароль), то лучше еще загрузить ключ: подписать что-то, например, или вызвать специальную функцию
Код:DWORD intprov; CryptGetProvParam(PP_HCRYPTPROV, (BYTE*)&intprov, 4)
. Контейнер остается закешированным до тех пор, пока он открыт хотя бы раз. Это поведение не зависит от флага SILENT, сервис/не сервис, включенности кеширования, но только для пользовательских ключей (ключи MACHINE_KEYSET ведут себя чуть по другому).
Цитата:Контекст не освобождаю, до тех пор пока нужен доступ к контейнеру.
В данном процессе в реестре создаются ветки, например
HKEY_LOCAL_MACHINE\SOFTWARE\Crypto Pro\Settings\Users\S-1-5-21-1268367499-517865807-3063332009-1003\KeyDevices\passwords\00011457
где 00011457 - ключевой контейнер (находится на смарт карте)
Интересно, что если не использовать SILENT режим и устанавливать в окошке ввода PIN кода "запомнить пароль" ветки создаются примерно такие
...KeyDevices\passwords\SCARD...
то есть используется уникальное наименование контейнера
1) В чем разница? Правильно ли запоминаю пароль в SILENT режиме?
в ветке HKEY_LOCAL_MACHINE\SOFTWARE\Crypto Pro\Settings\Users\SID_пользователя\passwords сохраняется два типа информации: shortcut и пароль.
Shortcut - это соответствие между именем контейнера и уникальным именем контейнера. Shortcut ускоряет поиск контейнера, если контейнер не был уже открыт (если был, то контейнер закеширован и shortcut не участвует). В Вашем случае, поиск будет происходить только на считывателях смарт картах (не будет обращений, например к дисководу), только на карте с заданным сериным номером (он указан в уникальном номере контейнера), только в Application карты, который так же присутствует в уникальном номере.
Password сохраняется HKEY_LOCAL_MACHINE\SOFTWARE\Crypto Pro\Settings\Users\SID_пользователя\passwords\ТИП_носителя\уникальный_номер_контейнера\уникальный_номер_приложения\passwd
при установке галочки "запомнить пароль". При доступе к ключу (если контейнер не закеширован), если требуется пароль, и он не установлен при помощи PP_KEYEXCHANGEPIN (PP_SIGNATUREPIN)? и он есть в приведенном выше ключе реестра, используется именно он. В SILENT режиме при неправильно установленном пароле (PIN) функция вернет ошибке, а в оконном режиме, попросит ввести правильный.
Цитата:Далее про удаление запомненного пароля
CryptSetProvParam( PP_KEYEXCHANGE_PIN, NULL )
то есть вместо пароля передаю NULL и освобождаю контекст
CryptReleaseContext()
Пароль забывается, но ветки в реестре остаются
Правильно.
Цитата:2) Как правильно удалять запомненные пароли?
Удалением соответствующих веток реестра; можно только shortcut, можно только пароль; можно по контейнерам, можно все сразу.
Цитата:И еще интересен такой нюанс
Запоминаю пароль доступа к контейнеру
Сохраняю сертификат с карты со ссылкой на закрытый ключ в локальное хранилище пользователя
Далее вытаскиваю карту из считывателя
Делаю ЭЦП с использованием CAPICOM и сертификата
Подпись выполняется успешно! При этом обращения к считывателю не происходит
3) Это как так получается?
Вариант 1. Остался открытым контейнер.
Вариант 2. Установлено хранение ключей в сервисе и включено кеширование.