Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

CryptVerifyCertificateSignature fails with NTE_BAD_SIGNATURE

179 views
Skip to first unread message

Robert Oeffner

unread,
Oct 13, 2005, 5:27:11 PM10/13/05
to
Hi,
I run a slightly modified example from the MSDN,
http://support.microsoft.com/default.aspx?scid=kb;en-us;323809, where I have
included a call to CryptVerifyCertificateSignature. The file I use for input
contains a valid signature.
Does anyone know why in the code snippet CryptVerifyCertificateSignature
fails with NTE_BAD_SIGNATURE? The original example works just fine. All I
want is to check whether a signed file has been tampered with but the
cryptoAPI is frustratingly poorly documented.

Thanks,

Rob

// Search for the signer certificate in the temporary
// certificate store.
CertInfo.Issuer = pSignerInfo->Issuer;
CertInfo.SerialNumber = pSignerInfo->SerialNumber;

pCertContext = CertFindCertificateInStore(hStore,
ENCODING,
0,
CERT_FIND_SUBJECT_CERT,
(PVOID)&CertInfo,
NULL);
if (!pCertContext)
{
_tprintf(_T("CertFindCertificateInStore failed with %x\n"),
GetLastError());
__leave;
}

// Print Signer certificate information.
_tprintf(_T("Signer Certificate:\n\n"));
PrintCertificateInfo(pCertContext);
_tprintf(_T("\n"));


if (!CryptVerifyCertificateSignature(NULL, X509_ASN_ENCODING |
PKCS_7_ASN_ENCODING,
(BYTE*)pCertContext->pbCertEncoded, pCertContext->cbCertEncoded,
&pCertContext->pCertInfo->SubjectPublicKeyInfo))
{
DWORD err= GetLastError();
}

--

Hao Zhuang [MSFT]

unread,
Oct 15, 2005, 2:31:04 AM10/15/05
to
you should use signer's public key to verify the signature. your code here is
to verify if the cert is self-signed. so it will fail if the cert is not
self-signed.

- hao

Robert Oeffner

unread,
Oct 15, 2005, 7:21:27 AM10/15/05
to
Thanks for the reply. How do I get the signers public key? I tried something
like

HCRYPTMSG hMsg=NULL;
PCCERT_CONTEXT pvercert;
DWORD dn = 0;
DWORD dwcontenttype = 0;
HCERTSTORE hCertStore = NULL;

if (!CryptQueryObject(CERT_QUERY_OBJECT_FILE, buffer,
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
CERT_QUERY_FORMAT_FLAG_BINARY,
0, NULL, &dwcontenttype, NULL, &hCertStore,
&hMsg, NULL))
{
btrusted = false;
err= GetLastError();
}

CryptMsgGetParam(hMsg, CMSG_SIGNER_CERT_INFO_PARAM, 0, NULL, &dn);
PCERT_INFO pSignerInfo = (PCERT_INFO)(new char[dn]);
CryptMsgGetParam(hMsg, CMSG_SIGNER_CERT_INFO_PARAM, 0, pSignerInfo, &dn);
err= GetLastError();

But the SubjectPublicKeyInfo member of the pSignerInfo struct is
uninitialised as are several other members. So supplying
CryptVerifyCertificateSignature with pSignerInfo->SubjectPublicKeyInfo as
the last argument is obviously no good.

If anyone knows how to obtain the public key from the signer's certificate
I'd be very grateful.


Thanks,

Rob


--


"Hao Zhuang [MSFT]" <HaoZhu...@discussions.microsoft.com> wrote in
message news:F8B70C27-DC3C-4E78...@microsoft.com...

Hao Zhuang [MSFT]

unread,
Oct 17, 2005, 1:11:02 AM10/17/05
to
now i see what you meant to do. but your code was simply retrieving the
signer certs of the signed file and verify whether these signer certs were
self-signed.

if you wish to verify the file signatures, your best bet would be
WinVerityTrust(). you can use many flags to prevent WVT from doing the things
you dont want it to do. i'm not the expert of code signing though.

if you wish to verify the validity of the signer certificates, which was
what i first thought you were doing from your initially posted code, you
should use the public key of the signer of the signer cert to call
CryptVerifyCertificateSignature().

hope this helps.

rob...@oeffner.net

unread,
Oct 17, 2005, 8:08:10 AM10/17/05
to
Thanks for the reply. I followed the examples on
http://groups.google.co.uk/group/microsoft.public.platformsdk.security/browse_thread/thread/faef4e6504a8144d/61a97cad2dc431c4?lnk=st&q=CryptVerifyMessageSignature+WinVerifyTrust&rnum=2&hl=en#61a97cad2dc431c4
and added the flags trust_data.dwProvFlags = WTD_HASH_ONLY_FLAG |
WTD_REVOCATION_CHECK_NONE to the WINTRUST_DATA struct. That seems to
kill off any network activity and WinVeriFyTrust returns immediately!
Would be good if MS included that example in the MSDN, I think.

Rob

0 new messages