Сохранение / восстановление сертификатов с помощью MS CryptoAPI делает недействительным прикрепленный закрытый ключ
Я написал программу, которая должна сохранять и восстанавливать сертификаты пользователей с помощью Windows Crypto API. У меня было впечатление, что он работает нормально, но теперь пользователь пожаловался, что закрытый ключ, который был прикреплен к сертификату, недействителен после восстановления сертификата.
Я сохранял сертификаты, используя:
HCERTSTORE hCertStore =
CertOpenStore(CERT_STORE_PROV_PHYSICAL_W,
0,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER |
CERT_STORE_OPEN_EXISTING_FLAG |
CERT_STORE_READONLY_FLAG |
CERT_STORE_UPDATE_KEYID_FLAG,
(PVOID) storeName.c_str());
А потом позже:
if (!CertSaveStore(hCertStore,
0,
CERT_STORE_SAVE_AS_STORE,
CERT_STORE_SAVE_TO_FILENAME,
(PVOID) saveFile.c_str(),
0))
Я понимаю, что флаг CERT_STORE_SAVE_AS_STORE должен означать, что весь сертификат должен быть сериализован, включая закрытый ключ. Хотя отмечу, что MSDN говорит:
"Свойство CERT_KEY_CONTEXT_PROP_ID и соответствующие значения CERT_KEY_PROV_HANDLE_PROP_ID и CERT_KEY_SPEC_PROP_ID не сохраняются в сериализованном хранилище".
... что я признаюсь, я не очень понимаю.
Когда я восстанавливаю сертификат, я использую CertFindCertificateInStore(), чтобы увидеть, существует ли сертификат, и только если его нет, я делаю:
bOK = CertAddCertificateContextToStore(
hDestinationStore,
pCertContext,
CERT_STORE_ADD_USE_EXISTING,
NULL);
Чтобы добавить сертификат обратно... Итак, мой вопрос: почему закрытый ключ не может быть сохранен? Я что-то пропустил?
1 ответ
Вы используете неправильный CryptoAPI. Вместо этого вы должны использовать PFXExportCertStoreEx и PFXImportCertStore.
ОБНОВЛЕНО: функции очень распространены. Конечно, вы не можете экспортировать сертификаты со SmartCard или другие неэкспортируемые сертификаты. БЛОГ в функции - это не что иное, как содержимое файла PFX. Например, импорт сертификата из файла PFX должен сделать следующее:
- Откройте файл PFX и прочитайте полное содержание в памяти. Вместо этого вы можете использовать, конечно, отображение файлов.
- При желании вы можете использовать
PFXIsPFXBlob
функция для проверки того, что файл действительно содержит файл, соответствующий файлу PFX. - Ты используешь
PFXImportCertStore
открыть BLOB (PFX) в качестве хранилища сертификатов источника. - Ты используешь
CertOpenStore
или какую-то другую функцию, чтобы открыть хранилище сертификатов назначения, где вы хотите сохранить сертификаты из файла PFX. - Ты используешь
CertEnumCertificatesInStore
перечислить сертификаты из исходного хранилища сертификатов (PFX) и для всего использования сертификатаCertAddCertificateContextToStore
добавить сертификат из хранилища сертификатов источника в хранилище сертификатов назначения. Сертификаты, имеющие закрытый ключ, будут импортированы с закрытым ключом. - Ты используешь
CertCloseStore
закрыть оба открытых магазина.