| ||||
| ||||
Возникла странная проблема при использовании функции CryptAcquireContext. С её помошью на дискете был создан контейнер, в нём создана пара ключей, для данных ключей создан сертификат в хранилище сертификатов в реестре. После этого дискету отформатировали. Теперь при вызове CryptAcquireContext с тем же именем контейнера и флагом CRYPT_NEWKEYSET возвращается NTE_EXISTS, несмотря на то, что установлена чистая дискета. Если же пытаться открыть контейнер без этого флага, либо с флагом CRYPT_DELETEKEYSET, выскакивает окошко "Вставьте ключевой носитель" с состоянием "Набор ключей не существует". Как быть в данной ситуации? Хотелось бы использовать данный контейнер повторно для создания другого ключа. Версия криптопровайдера - 2.0 Пример кода: //Пытаемся создать string conatinerName="\\\\.\\fat12_a\\abc"; if(!CryptAcquireContext(&m_hCryptProvCP,conatinerName.c_str(),CP_DEF_PROV,PROV_GOST_DH,CRYPT_NEWKEYSET/*CRYPT_SILENT*/)) { //Если уже есть if (GetLastError()==NTE_EXISTS) { if (::MessageBox(0,"Криптоконтейнер для хранения закрытого ключа КриптоПро для указанного конкурса уже существует.\n" "Хотите ли Вы удалить существующий контейнер (и хранящиеся в нем ключ) и создать новый?",0,MB_ICONQUESTION|MB_YESNO)==IDYES) { //Пытаемся удалить if(!CryptAcquireContext(&m_hCryptProvCP,/*"\\\\.\\fat12_a"*/conatinerName.c_str(),CP_DEF_PROV,PROV_GOST_DH,CRYPT_DELETEKEYSET/*|CRYPT_SILENT*/)) { HandleError("Невозможно удалить криптоконтейнер для хранения закрытого ключа КриптоПро\n"); return CCryptoService::csNotInitializedCantCreateKeyContainer; } //Пытаемся создать ещё раз if(!CryptAcquireContext(&m_hCryptProvCP,/*"\\\\.\\fat12_a"*/conatinerName.c_str(),CP_DEF_PROV,PROV_GOST_DH,CRYPT_NEWKEYSET/*|CRYPT_SILENT*/)) { HandleError("Невозможно создать новый криптоконтейнер для хранения закрытого ключа КриптоПро\n"); return CCryptoService::csNotInitializedCantCreateKeyContainer; } } else { HandleError("Невозможно создать новый криптоконтейнер для хранения закрытого ключа КриптоПро\n"); return CCryptoService::csNotInitializedCantCreateKeyContainer; } } else { HandleError("Невозможно создать новый криптоконтейнер для хранения закрытого ключа КриптоПро\n"); return CCryptoService::csNotInitializedCantCreateKeyContainer; } } | ||||
Ответы: | ||||
| ||||
Конечно, так и будет. Потому что удалять контейнер надо стандартными средствами - CryptAcquireContext(..CRYPT_DELETEKEYSET). Если же всё же хотите использовать то же имя повторно, то в разделе Сервис нашей контрольной панели (в версии 2.0) есть кнопочка "Удалить запомненные пароли", которая, в т.ч., очищает ссылки на существующие на съёмных носителях контейнеры. | ||||
| ||||
Если вы могли заметить, то в 13 строчке приведенного листига и вызывается CryptAcquireContext(..CRYPT_DELETEKEYSET). При этом на экран выводится окошко "Вставьте ключевой носитель" с состоянием "Набор ключей не существует". Поскольку данного носителя у меня нет (ну отформатировали его, испортили или потеряли), то и удалить контейнер не получается. Просто у меня имя контейнера привязано (содержит) к идентификатору пользователя. И новый ключ для него хотелось бы завести в контейнере со старым именем. А вот "удаление запомненных паролей" помогло. Отсюда вопрос - можно ли это сделать программным образом, чтобы не гонять пользователя в Контрол панель? | ||||
| ||||
1. Ну разумеется, удалить CryptAcquireContext-ом можно только при наличии носителя. 2. Очистить ссылку на конкретный контейнер пользователя можно, удалив раздел реестра, содержащий её, например, HKEY_LOCAL_MACHINE\SOFTWARE\Crypto Pro\Settings\USERS\S-1-5-21-1993962763-492894223-1202660629-2126\KeyDevices\passwords\b912cceb-5104-4949-b300-a9560174120c, где b912cceb-5104-4949-b300-a9560174120c - это имя контейнера. Алгоритм действий будет таким: поискать в HKEY_LOCAL_MACHINE\SOFTWARE\Crypto Pro\Settings\USERS подраздел с названием, равным имени контейнера и удалить его. | ||||
| ||||
Большое спасибо | ||||