为什么证书库中的证书没有私钥 属性
Why cert in certificate store doesn't have private key property
我试图通过 CNG API 从证书库中的证书中获取 EC 私钥。首先,我调用 CertGetCertificateContextProperty()
以 CERT_KEY_CONTEXT_PROP_ID
属性 获取私钥句柄,但它总是 return 错误。我确定证书有私钥。
代码:
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");
}
然后,我尝试执行相同的步骤,但从 this page 之类的 .pfx 文件中读取。 return true 成功获取私钥。为什么证书库中的证书没有 CERT_KEY_CONTEXT_PROP_ID
属性?
证书是签名的 public 密钥,它们不包含私钥。大多数混淆源于不正确理解密码学的人偶然误用和混淆术语和概念。
例如,.cert
.cer
.crt
可以包含 keys and/or certificates.但是,严格来说 certificate
是 签名的 public 密钥 .
根据我的经验,如果证书 UI 表明您有私钥,那么您应该能够打开并使用该密钥。它不算出口。你试过了吗CryptAcquireCertificatePrivateKey
?
正如 Woodstock 所写,私钥不是证书的一部分,甚至不与证书存储在一起。私钥存储在别处。然而,public密钥是证书的一部分,代码可以扫描本地密钥库寻找与证书具有相同算法的私钥,并且匹配证书中的 public 密钥。
其中的一个问题是 "strong key protection" 标志。如果已设置,任何尝试获取私钥的尝试都会弹出提示。这就是为什么 CryptAcquireCertificatePrivateKey
有一个父 window 句柄参数,还有一个 "silent" 标志。据我所知,除非重新创建密钥,否则无法删除它。
我试图通过 CNG API 从证书库中的证书中获取 EC 私钥。首先,我调用 CertGetCertificateContextProperty()
以 CERT_KEY_CONTEXT_PROP_ID
属性 获取私钥句柄,但它总是 return 错误。我确定证书有私钥。
代码:
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");
}
然后,我尝试执行相同的步骤,但从 this page 之类的 .pfx 文件中读取。 return true 成功获取私钥。为什么证书库中的证书没有 CERT_KEY_CONTEXT_PROP_ID
属性?
证书是签名的 public 密钥,它们不包含私钥。大多数混淆源于不正确理解密码学的人偶然误用和混淆术语和概念。
例如,.cert
.cer
.crt
可以包含 keys and/or certificates.但是,严格来说 certificate
是 签名的 public 密钥 .
根据我的经验,如果证书 UI 表明您有私钥,那么您应该能够打开并使用该密钥。它不算出口。你试过了吗CryptAcquireCertificatePrivateKey
?
正如 Woodstock 所写,私钥不是证书的一部分,甚至不与证书存储在一起。私钥存储在别处。然而,public密钥是证书的一部分,代码可以扫描本地密钥库寻找与证书具有相同算法的私钥,并且匹配证书中的 public 密钥。
其中的一个问题是 "strong key protection" 标志。如果已设置,任何尝试获取私钥的尝试都会弹出提示。这就是为什么 CryptAcquireCertificatePrivateKey
有一个父 window 句柄参数,还有一个 "silent" 标志。据我所知,除非重新创建密钥,否则无法删除它。