| ||||
| ||||
Не могу решить следующую задачу: есть PEM в котором сертификат и секретный ключ. c помощью openssl делаю из него PFX. Программно импортирую PFX во временное хранилище с флагом CRYPT_MACHINE_KEYSET и с помощью CertAddCertificateContextToStore добавляю единственный сертификат в "MY" с флагом CERT_SYSTEM_STORE_LOCAL_MACHINE. Теперь ставлю себе обратную задачу: получить PEM (причем только закрытого ключа). Открываю хранилище "MY" c флагом CERT_SYSTEM_STORE_LOCAL_MACHINE, получаю контекст установленного сертификата. Получаю для него CRYPT_KEY_PROV_INFO. Запрашиваю для этой структуры провайдела с помощью CryptAcquireContext. Получаю ключ AT_KEYEXCHANGE с помощью CryptGetUserKey. Пытаюсь получить PRIVATEKEYBLOB с помощью CryptExportKey, но как результат ошибка Key not valid for use in specified state Как же импортировать приватный ключ? Где ошибка в моих действиях? Key not valid for use in specified state. | ||||
Ответы: | ||||
| ||||
Когда программно импортируете, надо также указывать флаг CRYPT_EXPORTABLE, ибо If this flag is not used, calls to the CryptExportKey function with the key handle fail. | ||||
| ||||
да действительно импортируется, но после преобразование в PEM он не такой как оригинальный... может я неправильное его преобразовываю? так привожу к PFX openssl openssl pkcs12 -export -in file.pem -out file.fpx -passout pass: так устанавливаю сертификат с секретным ключем CRYPT_DATA_BLOB blob; //заполнен данными из файла HCERTSTORE hCetrStorePfx = ::PFXImportCertStore(&blob, L"", CRYPT_EXPORTABLE); HCERTSTORE hCertStore = ::CertOpenStore(CERT_STORE_PROV_SYSTEM, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"MY"); PCCERT_CONTEXT pCertContext = ::CertEnumCertificatesInStore(hCetrStorePfx, NULL); ::CertAddCertificateContextToStore(hCertStore, pCertContext, CERT_STORE_ADD_ALWAYS, NULL); так импортирую секретный ключ HCERTSTORE hCertStore = ::CertOpenStore(CERT_STORE_PROV_SYSTEM, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"MY"); PCCERT_CONTEXT pCertContext = ::CertEnumCertificatesInStore(hCertStore, NULL); //он там один DWORD cbData; ::CertGetCertificateContextProperty(pCertContext, CERT_KEY_PROV_INFO_PROP_ID, NULL, &cbData); CRYPT_KEY_PROV_INFO * pCryptKeyProvInfo = (CRYPT_KEY_PROV_INFO *)_alloca(cbData); ::CertGetCertificateContextProperty(pCertContext, CERT_KEY_PROV_INFO_PROP_ID, pCryptKeyProvInfo, &cbData); HCRYPTPROV hProv; ::CryptAcquireContextW(&hProv, pCryptKeyProvInfo->pwszContainerName, pCryptKeyProvInfo->pwszProvName, pCryptKeyProvInfo->dwProvType, CRYPT_MACHINE_KEYSET); HCRYPTKEY hKey; ::CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hKey); DWORD dwDataLen; ::CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, NULL, &dwDataLen); BYTE * pb = (BYTE *)_alloca(dwDataLen); ::CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, pb, &dwDataLen); DWORD cb; base64hdr_encode(&Base64PrivateKeyHdrs, pb, dwDataLen, NULL, &cb); BYTE * p = (BYTE *)_alloca(cb); base64hdr_encode(&Base64PrivateKeyHdrs, pb, dwDataLen, p, &cb); ofstream filePem("private_key.pem"); filePem.write((const char*)p, cb); filePem.close(); | ||||
| ||||
Может быть. А если экспорт сделать через PFXExportCertStoreEx а потом через openssl преобразовать в PEM - получится то что надо? | ||||