I tried to get EC private key from cert which in certificate store by CNG API. First, I call CertGetCertificateContextProperty()
to get private key handle with CERT_KEY_CONTEXT_PROP_ID
property, but it always return false. I'm sure that the cert has private key.
Code:
wchar_t wMY_CERT_NAME[100];
HCERTSTORE hCertStore = NULL;
PCCERT_CONTEXT pSignerCert = NULL;
NCRYPT_KEY_HANDLE hKey = NULL;
const int buffsize = 4999;
DWORD len = buffsize;
char buff[buffsize];
// Open the certificate store.
if (!(hCertStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
CERT_STORE_NAME)))
{
MyHandleError(const_cast<LPTSTR>("The MY store could not be opened."));
}
swprintf(wMY_CERT_NAME, 100, L"%hs", MY_CERT_NAME);
if (pSignerCert = CertFindCertificateInStore(
hCertStore,
MY_ENCODING_TYPE,
0,
CERT_FIND_SUBJECT_STR,
wMY_CERT_NAME,
NULL))
{
//continue
}
if (CertGetCertificateContextProperty(
pSignerCert,
CERT_KEY_CONTEXT_PROP_ID,
buff,
&len))
{
auto ckc = (CERT_KEY_CONTEXT *)buff;
hKey = ckc->hNCryptKey;
}
else {
wprintf(L"**** GetCertContextProperty failed.\n");
}
Then, I tried to do the same step but read from a .pfx file like this page. It return true and get private key successfully. Why cert in certificate store doesn't have CERT_KEY_CONTEXT_PROP_ID
property?
Certificates are signed public keys, they don't contain the private key. Most of the confusion stems from casual mis-use and conflation of terminology and concepts by people who don't understand cryptography properly.
For example, .cert
.cer
.crt
can contain keys and/or certificates. However, strictly a certificate
is a signed public key.