Сохранение / восстановление сертификатов с помощью 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 должен сделать следующее:

  1. Откройте файл PFX и прочитайте полное содержание в памяти. Вместо этого вы можете использовать, конечно, отображение файлов.
  2. При желании вы можете использовать PFXIsPFXBlob функция для проверки того, что файл действительно содержит файл, соответствующий файлу PFX.
  3. Ты используешь PFXImportCertStore открыть BLOB (PFX) в качестве хранилища сертификатов источника.
  4. Ты используешь CertOpenStore или какую-то другую функцию, чтобы открыть хранилище сертификатов назначения, где вы хотите сохранить сертификаты из файла PFX.
  5. Ты используешь CertEnumCertificatesInStore перечислить сертификаты из исходного хранилища сертификатов (PFX) и для всего использования сертификата CertAddCertificateContextToStore добавить сертификат из хранилища сертификатов источника в хранилище сертификатов назначения. Сертификаты, имеющие закрытый ключ, будут импортированы с закрытым ключом.
  6. Ты используешь CertCloseStore закрыть оба открытых магазина.
Другие вопросы по тегам