Сохранение / восстановление сертификатов с помощью MS CryptoAPI делает недействительным прикрепленный закрытый ключ - PullRequest
1 голос
/ 21 апреля 2011

Я написал программу, которая должна сохранять и восстанавливать сертификаты пользователей, используя 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 Ответ

4 голосов
/ 21 апреля 2011

Вы используете неправильный CryptoAPI.Вместо этого следует использовать PFXExportCertStoreEx и PFXImportCertStore .

ОБНОВЛЕНО : функции очень распространены.Конечно, вы не можете экспортировать сертификаты со SmartCard или другие неэкспортируемые сертификаты.БЛОГ в функции - это не что иное, как содержимое файла PFX.Например, импорт сертификата из файла PFX должен выполнить следующее:

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