#windows #winapi #cryptography #cryptoapi #mscapi
#Windows #winapi #криптография #cryptoapi #mscapi
Вопрос:
Я написал программу, которая должна сохранять и восстанавливать сертификаты пользователей с использованием 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.
ОБНОВЛЕНО: Функции очень распространены. Конечно, вы не можете экспортировать сертификаты со смарт-карты или другие неэкспортируемые сертификаты. БЛОГ в функции — это не что иное, как содержимое файла PFX. Например, импорт сертификата из файла PFX должен выполнить следующее:
- Откройте файл PFX и прочитайте полное содержимое в памяти. Вы, конечно, можете использовать сопоставление файлов вместо этого.
- При желании вы можете использовать
PFXIsPFXBlob
функцию для проверки того, что файл действительно содержит то, что соответствует файлу PFX. - Вы используете
PFXImportCertStore
для открытия большого двоичного объекта (PFX) в качестве хранилища сертификатов источника. - Вы используете
CertOpenStore
или какую-либо другую функцию, чтобы открыть хранилище сертификатов назначения, в котором вы хотите сохранить сертификаты из файла PFX. - Используется
CertEnumCertificatesInStore
для перечисления сертификатов из исходного хранилища сертификатов (PFX) и для всех сертификатов используетсяCertAddCertificateContextToStore
для добавления сертификата из хранилища сертификатов источника в хранилище сертификатов назначения. Сертификаты, имеющие закрытый ключ, будут импортированы вместе с закрытым ключом. - Вы используете
CertCloseStore
для закрытия обоих открытых хранилищ.
Комментарии:
1. Хм, выглядит многообещающе, будет ли эта функция работать для всех типов сертификатов / cert store?
2. @Benj: Я обновил свой ответ информацией из одной моей старой рабочей программы. Я надеюсь, что этого будет достаточно для вас, чтобы написать свою собственную программу. Экспорт очень прост, но импорт немного сложнее, поэтому я описал импорт более подробно.
3. Кажется, это работает блестяще. Теперь моя программа успешно сохраняет / восстанавливает все сертификаты, включая закрытые ключи.. Большое спасибо!