I need to use CNG to verify a message signature (RSA). The only problem is how to get the CNG key handle (NCRYPT_KEY_HANDLE or BCRYPT_KEY_HANDLE) if I have the public certificate stored in windows certs (Cert:\CurrentUser\My). I am using a
NCryptOpenStorageProvider({out}hProv, MS_KEY_STORAGE_PROVIDER, 0)
and I tried to get the public key handle using
NCryptOpenKey(hProv, {out}hKey, PWideChar('my.test.com'), AT_KEYEXCHANGE, 0)
but it seems that NCryptOpenKey() can only open the certificates that also have private keys.
I was also looking at BCryptImportKeyPair() but this requires to have the public key in BCRYPT_RSAKEY_BLOB structure which I don't know how to achieve.
The last function I was looking at was NCryptImportKey() but this again only works with private keys.
Anyone knows how to get the public key handle using CNG?
I have the public key in a file (cer/pem) and I imported it to windows Cert:
store but if you know how to load it directly from a file to CNG key handle I would be happy as well.
NCrypt* functions works with persisted key pairs which stored at Key Storage Provider. If you import certificate in certificate store and this certificate does not contain private key then public key will not save in KSP.
You can use function CryptImportPublicKeyInfoEx2 to acquire BCRYPT_KEY_HANDLE.
Sample code in C:
HCERTSTORE hStore = nullptr;
PCCERT_CONTEXT pCert = nullptr;
BCRYPT_KEY_HANDLE hKey = nullptr;
/* Open MY certificate store */
hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER, L"MY");
if (!hStore) {
goto Exit;
}
/* Find your certificate in store. For example search by subject name */
pCert = CertFindCertificateInStore(hStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR, L"subject name", nullptr);
if (!pCert) {
goto Exit;
}
/* Or if you want to load certificate from file (assuming you read file to cert_data):
pCert = CertCreateCertificateContext(X509_ASN_ENCODING, cert_data, cert_size);
*/
/* Now you can create BCRYPTKEY_HANDLE from your public key */
if (!CryptImportPublicKeyInfoEx2(X509_ASN_ENCODING, &pCert->pCertInfo->SubjectPublicKeyInfo, 0, nullptr, &hKey)) {
goto Exit;
}
/* Now you can verify signature with BCryptVerifySignature(hKey...) */
Exit:
/* Don't forget to free handle after use */
if (hKey) {
BCryptDestroyKey(hKey);
}
if (pCert) {
CertFreeCertificateContext(pCert);
}
if (hStore) {
CertCloseStore(hStore, 0);
}
return 0;