这是设置
AD CS(Windows Server 2019 Hyper-V 虚拟机)
客户端(Windows 10 Hyper-V 虚拟机)
当我尝试使用以下代码导入私钥时,CertFindCertificateInStore() 返回错误 CRYPT_E_NO_KEY_PROPERTY。
HANDLE hFile = CreateFileA(pfxPath.c_str(), GENERIC_READ, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
if (hFile == INVALID_HANDLE_VALUE) {
HandleError("Unable to open PFX file");
}
DWORD fileSize = GetFileSize(hFile, nullptr);
std::vector<BYTE> fileData(fileSize);
DWORD bytesRead;
if (!ReadFile(hFile, fileData.data(), fileSize, &bytesRead, nullptr) || bytesRead != fileSize) {
HandleError("Unable to read PFX file");
}
CloseHandle(hFile);
CRYPT_DATA_BLOB pfxBlob = { static_cast<DWORD>(fileData.size()), fileData.data() };
if (!PFXIsPFXBlob(&pfxBlob)) {
HandleError("Invalid PFX file");
}
hStore = PFXImportCertStore(&pfxBlob, password.c_str(), CRYPT_EXPORTABLE);
if (!hStore) {
HandleError("Failed to import PFX certificate store");
}
certContext = CertFindCertificateInStore(hStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, nullptr, nullptr);
if (!certContext) {
HandleError("Failed to find certificate in PFX store");
}
if (!CryptAcquireCertificatePrivateKey(certContext, CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG, nullptr, &hCryptProvOrNCryptKey, &dwKeySpec, &fCallerFreeProvOrNCryptKey)) {
auto dw = GetLastError();
HandleError("Failed to acquire private key");
}
具有自签名证书,能够成功导入私钥并导出私钥。
我尝试传递 0 而不是 CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG,但仍然出现相同的错误。
感谢您的帮助。
返回错误CryptAcquireCertificatePrivateKey
。CRYPT_E_NO_KEY_PROPERTY
CryptAcquireCertificatePrivateKey
查找CERT_KEY_PROV_INFO_PROP_ID
,如果不存在,则返回此类错误。
在证书
PFXImportCertStore
上设置 CERT_KEY_PROV_INFO_PROP_ID
,以防 PKCS12_NO_PERSIST_KEY
未使用,或 CERT_KEY_CONTEXT_PROP_ID
,如果我们使用此标志。但这并不适用于 pfx 中的所有证书,而仅适用于与 pfx 中的私钥相对应的公钥的证书。但你:
导出时选择这些选项“将所有证书包含在 证书路径(如果可能)”
pfx 中有多个证书,并且只有一个包含
CERT_KEY_PROV_INFO_PROP_ID
或 CERT_KEY_CONTEXT_PROP_ID
属性。
所以
CertFindCertificateInStore
我们需要CertEnumCertificatesInStore
并检查存储中的每张证书,直到找到一个“好”。
在大多数情况下最好使用
PKCS12_NO_PERSIST_KEY
,否则私钥将存储在具有自动生成的随机名称的新密钥容器中。
代码可以是这样的:
CRYPT_DATA_BLOB PFX;
if (NOERROR ReadFromFile(pfxPath, &PFX.pbData, &PFX.cbData))
{
if (HCERTSTORE hStore = PFXImportCertStore(&PFX, password,
CRYPT_EXPORTABLE|PKCS12_ALWAYS_CNG_KSP|PKCS12_NO_PERSIST_KEY))
{
PCCERT_CONTEXT pCertContext = 0;
while(pCertContext = CertEnumCertificatesInStore(hStore, pCertContext))
{
CERT_KEY_CONTEXT ckc;
ULONG cb = sizeof(ckc);
if (CertGetCertificateContextProperty(pCertContext, CERT_KEY_CONTEXT_PROP_ID, &ckc, &cb))
{
// use ckc.hNCryptKey
// not need call NCryptFreeObject(ckc.hNCryptKey);
CertFreeCertificateContext(pCertContext);
break;
}
}
CertCloseStore(hStore, 0);
}
LocalFree(PFX.pbData);
}