Экспорт RSA_CSP_PUBLICKEYBLOB как DER / PEM с использованием Windows Crypto API - PullRequest
1 голос
/ 23 июня 2019

Я пытаюсь использовать Windows Crypto API для генерации пары ключей RSA, а затем экспортировать открытый ключ в DER или PEM. У меня работает код и я могу успешно экспортировать закрытый ключ, но я не понял, как сделать то же самое с открытым ключом. Моя конечная цель - передать открытый ключ openssl для проверки подписи.

Я видел этот вопрос: Microsoft CryptoAPI: как конвертировать PUBLICKEYBLOB в DER / PEM?

Но я не нашел решения. Как сохранить открытый ключ в допустимом формате PEM, используя только встроенные функции Windows Crypto API? Что мне не хватает? Спасибо!

Вот соответствующие фрагменты кода и мой порядок вызовов API для того, как я экспортирую закрытый ключ как DER / PEM:

HCRYPTPROV hProv = NULL;
CryptAcquireContext(&hProv, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, 0)
HCRYPTKEY hPrivateKey = NULL;
CryptGenKey(hProv, AT_KEYEXCHANGE, CRYPT_ARCHIVABLE, &hPrivateKey);
CryptExportKey(hPrivateKey, 0, PRIVATEKEYBLOB, 0, 0, &size);
BYTE* pPrivKeyBlob = (BYTE *)malloc(size);
CryptExportKey(hPrivateKey, 0, PRIVATEKEYBLOB, 0, pPrivKeyBlob, &size);
CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, pPrivKeyBlob, 0, NULL, NULL, &size);
BYTE* pPrivDer = (BYTE *)malloc(size);
CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, pPrivKeyBlob, 0, NULL, pPrivDer, &size);

Это работает, а pPrivDer содержит закрытый ключ в формате DER. Я не могу отформатировать это в PEM:

DWORD pemSize = 0;
CryptBinaryToStringA(pPrivDer, size, CRYPT_STRING_BASE64HEADER, NULL, &pemSize);
LPSTR pPrivPEM = (LPSTR)malloc(pemSize);
CryptBinaryToStringA(pPrivDer, size, CRYPT_STRING_BASE64HEADER, pPrivPEM, &pemSize);
printf("%s", pPrivPEM);

Это прекрасно работает, и ключ имеет правильный формат (изменение заголовка позволяет openssl читать / анализировать его)

Однако я не могу на всю жизнь понять, как сохранить открытый ключ в DER / PEM. Вот что я пытаюсь:

//export public key
CryptExportKey(hPrivateKey, 0, PUBLICKEYBLOB, 0, 0, &size);
BYTE* pPubKeyBlob = (BYTE *)malloc(size);
CryptExportKey(hPrivateKey, 0, PUBLICKEYBLOB, 0, pPubKeyBlob, &size);
CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB, mypubkey, 0, NULL, NULL, &size);
BYTE* pPubDer = (BYTE *)malloc(size);
CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB, mypubkey, 0, NULL, pPubDer, &size);
DWORD pPubPEMSize = 0;
CryptBinaryToStringA(pPubDer, size, CRYPT_STRING_BASE64, NULL, &pPubPEMSize);
LPSTR pPubPEM = (LPSTR)malloc(pPubPEMSize);
CryptBinaryToStringA(pPubDer, size, CRYPT_STRING_BASE64, pPubPEM, &pPubPEMSize);
printf("-----BEGIN PUBLIC KEY-----\n%s-----END PUBLIC KEY-----\n\n", pPubPEM);

Это не вызывает ошибок, но экспортированный DER и напечатанный PEM для открытого ключа не распознаются openssl и, похоже, имеют неправильный формат.

...