I'm trying to output the original base64 form of an imported RSA public key using Windows CryptoAPI functions. Using CryptBinaryToString with the CRYPT_STRING_BASE64HEADER flag, the output header reads "BEGIN CERTIFICATE" instead of expected "BEGIN PUBLIC KEY".
(EDIT: I didn't highlight this part of my problem) Furthermore, the resulting public key appears to be different than the original.
Will this become problematic if I were to export the output and reimport it? If so, what am I doing wrong?
Here's how the public key was imported.
Public key is stored in file pubkey.pem in the following PEM format:
-----BEGIN PUBLIC KEY-----
[REDACTED]
-----END PUBLIC KEY-----
File is read into a buffer with CreateFile/ReadFile. PEM converted to binary using CryptStringToBinaryA. Binary is decoded to X509_PUBLIC_KEY_INFO using CryptDecodeObjectEx. PubKeyInfo struct is decoded to RSA_CSP_PUBLICKEYBLOB (same function as above).
This part works just fine (can import the key and encrypt data with CryptImportKey, CryptEncrypt, etc).
Here's the code that I've put together to try and bring the raw blob back to base64 PEM format. I've removed most error-checking to save headaches.
pbTmp and cbTmp are the temp buffer to hold output and size respectively. pBinaryKey is the raw public key blob (imported from earlier) pBuffer is the output buffer (assumed to be the correct size) ulDataLen is the output buffer size
CryptEncodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB, pBinaryKey, 0, NULL, NULL, &cbTmp)
pbTmp = malloc(cbTmp);
CryptEncodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB, pBinaryKey, 0, NULL, pbTmp, &cbTmp)
CryptBinaryToStringA(pbTmp, cbTmp, CRYPT_STRING_BASE64HEADER, NULL, &ulDataLen)
CryptBinaryToStringA(pbTmp, cbTmp, CRYPT_STRING_BASE64HEADER, pBuffer, &ulDataLen)
The resulting buffer ends up with this:
-----BEGIN CERTIFICATE-----
[REDACTED; DIFFERENT FROM ORIGINAL PUBLIC KEY]
-----END CERTIFICATE-----
CERTIFICATE
,CERTIFICATE REQUEST
andX509 CRL
. Whether it matters or not depends on the program that's going to be interpret the data. You can always use theCRYPT_STRING_BASE64
flag to encode without headers and then add the correct header yourself. – Jonathan Potter