0

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?

barneyAgumble
  • 167
  • 1
  • 7
  • yoi need call `CryptImportPublicKeyInfo` in place `CryptDecodeObjectEx(PKCS_7_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB` or, if use CNG - `CryptDecodeObjectEx` with `CNG_RSA_PUBLIC_KEY_BLOB` instead `RSA_CSP_PUBLICKEYBLOB` – RbMm May 24 '21 at 02:34
  • Why did you close this question? I've done by research and that does not answer the question. Re-open it. – barneyAgumble May 24 '21 at 02:35
  • but because answer exist - how i say - replace `RSA_CSP_PUBLICKEYBLOB` to `CNG_RSA_PUBLIC_KEY_BLOB` and use cng api. or call `CryptImportPublicKeyInfo`. or look for https://stackoverflow.com/a/3803333/6401656 or [this](https://github.com/rbmm/PEM/blob/main/legacy_pem.cpp#L22) or [this](https://github.com/rbmm/PEM/blob/main/pem.cpp#L172) – RbMm May 24 '21 at 02:38
  • CryptImportPublicKeyInfo is deprecated! RSA_CSP_PUBLICKEYBLOB is the second step after getting the key info. You have to get the key info first before using RSA_CSP_PUBLICKEYBLOB. – barneyAgumble May 24 '21 at 02:41
  • `CryptImportPublicKeyInfo` and so what ? all legacy crypto api is depredecated. your `RSA_CSP_PUBLICKEYBLOB` also depredetacated. use in this case `CNG_RSA_PUBLIC_KEY_BLOB` – RbMm May 24 '21 at 02:44
  • replace `CryptDecodeObjectEx(PKCS_7_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB, cpki->PublicKey.pbData, cpki->PublicKey.cbData,...)` to `CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, CNG_RSA_PUBLIC_KEY_BLOB, cpki->PublicKey.pbData, cpki->PublicKey.cbData..)` – RbMm May 24 '21 at 02:47
  • `PCERT_PUBLIC_KEY_INFO cpki` in your code. and direct used in `CryptImportPublicKeyInfo` or use `CNG_RSA_PUBLIC_KEY_BLOB`. *CRYPT_E_ASN1_BADTAG* because it formatted not as `RSA_CSP_PUBLICKEYBLOB` but as `CNG_RSA_PUBLIC_KEY_BLOB` - replace code as in my previous comment - erros is gone ? – RbMm May 24 '21 at 02:53
  • No. You have to read X509_PUBLIC_KEY_INFO BEFORE you read the BLOB. The error is at X509_PUBLIC_KEY_INFO. – barneyAgumble May 24 '21 at 02:57
  • you at begin must say - which exactly api call is fail - you not do this – RbMm May 24 '21 at 06:53
  • if you have certificate - you need use `X509_CERT_TO_BE_SIGNED` instead `X509_PUBLIC_KEY_INFO` as i point you [here](https://stackoverflow.com/questions/67665721/cryptdecodeobjectex-fails-with-crypt-e-asn1-badtag#comment119603082_67665721) - look again for [this](https://github.com/rbmm/PEM/blob/main/legacy_pem.cpp#L22) or [this](https://github.com/rbmm/PEM/blob/main/pem.cpp#L172) – RbMm May 24 '21 at 06:58
  • *I'm assuming CryptStringToBinaryA is not processing the certificate string properly but still returning TRUE* of course this is wrong. and look like you here have not certificate but PFX - so need use `PFXImportCertStore` (and check with `PFXIsPFXBlob`) – RbMm May 24 '21 at 08:15

0 Answers0