http://stackoverflow.com/questions/1231178/load-an-x509-pem-file-into-windows-cryptoapi
I discovered the "magic" sequence of calls to import a RSA public key in PEM format. Here you go:
- decode the key into a binary blob with CryptStringToBinary; pass CRYPT_STRING_BASE64HEADER in dwFlags
- decode the binary key blob into a CERT_PUBLIC_KEY_INFO with CryptDecodeObjectEx; pass X509_ASN_ENCODING in dwCertEncodingType and X509_PUBLIC_KEY_INFO in lpszStructType
- decode the PublicKey blob from the CERT_PUBLIC_KEY_INFO into a RSA key blob with CryptDecodeObjectEx; pass X509_ASN_ENCODING in dwCertEncodingType and RSA_CSP_PUBLICKEYBLOB in lpszStructType
- import the RSA key blob with CryptImportKey
This sequence really helped me understand what's going on, but it didn't work for me as-is. The second call to
CryptDecodeObjectEx
gave me an error: "ASN.1 bad tag value met". After many attempts at understanding Microsoft documentation, I finally realized that the output of the fist decode cannot be decoded as ASN again, and that it is actually ready for import. With this understanding I found the answer in the following link:http://www.ms-news.net/f2748/problem-importing-public-key-4052577.html
int main() { char pemPubKey[2048]; int readLen; char derPubKey[2048]; size_t derPubKeyLen = 2048; CERT_PUBLIC_KEY_INFO *publicKeyInfo; int publicKeyInfoLen; HANDLE hFile; HCRYPTPROV hProv = 0; HCRYPTKEY hKey = 0; /* * Read the public key cert from the file */ hFile = CreateFileA( "c:\pub.pem", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if ( hFile == INVALID_HANDLE_VALUE ) { fprintf( stderr, "Failed to open file. error: %d ", GetLastError() ); } if ( !ReadFile( hFile, pemPubKey, 2048, &readLen, NULL ) ) { fprintf( stderr, "Failed to read file. error: %d ", GetLastError() ); } /* * Convert from PEM format to DER format - removes header and footer and decodes from base64 */ if ( !CryptStringToBinaryA( pemPubKey, 0, CRYPT_STRING_BASE64HEADER, derPubKey, &derPubKeyLen, NULL, NULL ) ) { fprintf( stderr, "CryptStringToBinary failed. Err: %d ", GetLastError() ); } /* * Decode from DER format to CERT_PUBLIC_KEY_INFO */ if ( !CryptDecodeObjectEx( X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, derPubKey, derPubKeyLen, CRYPT_ENCODE_ALLOC_FLAG, NULL, &publicKeyInfo, &publicKeyInfoLen ) ) { fprintf( stderr, "CryptDecodeObjectEx 1 failed. Err: %p ", GetLastError() ); return -1; } /* * Acquire context */ if( !CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) ) { { printf( "CryptAcquireContext failed - err=0x%x. ", GetLastError() ); return -1; } } /* * Import the public key using the context */ if ( !CryptImportPublicKeyInfo( hProv, X509_ASN_ENCODING, publicKeyInfo, &hKey ) ) { fprintf( stderr, "CryptImportPublicKeyInfo failed. error: %d ", GetLastError() ); return -1; } LocalFree( publicKeyInfo ); /* * Now use hKey to encrypt whatever you need. */ return 0; }