I am trying to verify a HMAC but CryptDecodeObjectEx is returning an error.
First, I have exported a PEM from a PFX. I export via .NET using
pem = Convert.ToBase64String(x509Cert.Export(X509ContentType.Cert, password))
I write this to a file between '-----BEGIN CERTIFICATE-----' and "-----END CERTIFICATE-----"
Then I use CryptStringToBinaryA to load it into a binary buffer in order to pass it to CryptDecodeObjectEx to get the X509_PUBLIC_KEY_INFO.
But that is where it fails. It returns CRYPT_E_ASN1_BADTAG.
CHAR SIGN_KEY[] = "-----BEGIN CERTIFICATE-----\n"
"MIIFWjCCA..................\n"
"-----END CERTIFICATE-----\n";
if (CryptStringToBinaryA((LPCSTR)SIGN_KEY, sizeof(SIGN_KEY), CRYPT_STRING_BASE64HEADER, NULL, &out, NULL, NULL)) {
bin = (PBYTE)HALLOC(out);
if (bin) {
if (CryptStringToBinaryA((LPCSTR)SIGN_KEY, sizeof(SIGN_KEY), CRYPT_STRING_BASE64HEADER, bin, &out, NULL, NULL)) {
//This fails here with 0x8009310B (CRYPT_E_ASN1_BADTAG - ASN.1 bad tag value met)
//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
if (CryptDecodeObjectEx(PKCS_7_ASN_ENCODING, X509_PUBLIC_KEY_INFO, bin, out, CRYPT_ENCODE_ALLOC_FLAG, NULL, &cpki, &out)) {
if (CryptDecodeObjectEx(PKCS_7_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB, cpki->PublicKey.pbData, cpki->PublicKey.cbData, CRYPT_ENCODE_ALLOC_FLAG, NULL, *key, kl)) {
In VB.Net I can use the exact same certificate string and create a new X509 certificate which I then use with a RSACryptoServiceProvider in order to verify the signature. Pseudo code is as follows:
x509 = New X509Certificate2(System.Text.Encoding.ASCII.GetBytes(SIGN_KEY))
Dim rsa As New RSACryptoServiceProvider()
rsa.FromXmlString(x509.PublicKey.Key.ToXmlString(False))
Return rsa.VerifyData(MessageBytes, New SHA256CryptoServiceProvider(), SignatureBytes)
That works so I'm assuming CryptStringToBinaryA is not processing the certificate string properly but still returning TRUE.
Is there a special format for .NET exported PEMs to be imported into the C/C++ CryptApi?