6

I am developing a C++ application, and I need to check the thumbprint of a certificate.

I found this solution check for a specific signature, using CryptQueryObject(). but I still can't find a way to retrieve the Thumprint.

In C# I can use the method GetCertHashString to get the hash (which is what I need) or use the property X509Certificate.Thumbprint

I know I need to get the hash value of the public key, but I don't know how to retrieve the public key..

How do I do that in C++? is there a method for that?

Community
  • 1
  • 1
user844541
  • 2,868
  • 5
  • 32
  • 60

2 Answers2

12

Found how to do it.

you should use CryptHashCertificate

Like that:

DWORD* thumbPrintSize;
BYTE* thumbPrint;   
if (!CryptHashCertificate(0, hashAlg, 0,pCertContext->pbCertEncoded,
     pCertContext->cbCertEncoded, thumbPrint, thumbPrintSize)) {
        return false;
}

Where pCertContext is the certificate, and hashAlg is the hashing algorithm (usually sha-1)

user844541
  • 2,868
  • 5
  • 32
  • 60
  • Does it calculate or retrieve it from certificate? – Mustafa Chelik Dec 18 '16 at 21:30
  • 1
    @MustafaChelik It calculates the thumbprint, because the thumbprint is not stored in the certificate. – X. Liu May 10 '17 at 21:20
  • CryptHashCertificate is deprecated, however CryptHashCertificate2 is pretty similar. However, my thumbprint doesn't seem to match the thumbprint seen using the DigitalSignature tab in properties. – NiteRain Feb 09 '18 at 16:37
0

This is once again necromancing a thread, but I'd like to also point out that another approach is to use CertGetCertificateContextProperty with the CERT_HASH_PROP_ID flag, which will return the SHA1 hash of the certificate, or calculate it using CryptHashCertificate (presumably with SHA1 as the hashing algorithm) where it doesn't.

If you're after thumbprints in a different algorithm than SHA1 of course this probably won't be what you're after, but from everything I've seen in windows at least, SHA1 seems to be what everything still uses.

// most current hashing algorithms top out at about 64 bytes,
// usually much less (20 bytes is very common):
byte thumb[64] = { 0 };
DWORD thumbsz = sizeof(thumb);
if (!CertGetCertificateContextProperty(pCertContext, CERT_HASH_PROP_ID, thumb, &thumbsz))
    return false;

I've tested the above and confirmed it matches everything I can see in certmgr.msc, though I am by no means a wincrypt expert so please feel free to correct me or comment below if there are good reasons not to use this approach.

Jon Marnock
  • 3,155
  • 1
  • 20
  • 15