#include <stdio.h>
#import <msxml5.dll>
using namespace MSXML2;
#import <capicom.dll>
using namespace CAPICOM;
#define DSIGNS "xmlns:ds='http://www.w3.org/2000/09/xmldsig#'"
#define INFILE "signature_signed.rsa.cert.xml"
IXMLDOMDocument3Ptr xmldoc = NULL;
IXMLDigitalSignaturePtr xmldsig = NULL;
VARIANT_BOOL objectsAreInitialized = VARIANT_FALSE;
VARIANT_BOOL LoadXML(_bstr_t sigFile)
{
if (!objectsAreInitialized) {
printf("Must initialize objects before loading signature.\n");
return VARIANT_FALSE;
}
if (xmldoc->load(sigFile) == VARIANT_FALSE) {
printf("Can't load %s\n", (LPCSTR)sigFile);
return VARIANT_FALSE;
}
_bstr_t ns= DSIGNS;
xmldoc->setProperty("SelectionNamespaces", ns);
// Set the signature property to a <ds:Signature> DOM node.
xmldsig->signature = xmldoc->selectSingleNode(".//ds:Signature");
if (xmldsig->signature == NULL) {
printf("Failed to set the signature property.\n");
return VARIANT_FALSE;
}
return VARIANT_TRUE;
}
VARIANT_BOOL IsCertificateValid(IXMLDSigKeyPtr pKey)
{
if (pKey == NULL) {
printf("invalid key object.\n");
return VARIANT_FALSE;
}
// Retrieve the ceritificate from the verifying key.
ICertificatePtr pCert=NULL;
pCert = pKey->getVerifyingCertificate();
if (pCert == NULL) {
printf ("Can't get verifying certificate\n");
return VARIANT_FALSE;
}
// Build and walk through the certificate's trust chain.
IChain2Ptr pChain = NULL;
HRESULT hr = pChain.CreateInstance(__uuidof(Chain));
if (FAILED(hr)) {
printf("Can't instantiate a trust chain.\n");
return VARIANT_FALSE;
}
if (VARIANT_FALSE == pChain->Build(pCert)) {
printf("broken trust chain.\n");
return VARIANT_FALSE;
}
printf("Examining certificate chain:\n");
long count = pChain->Certificates->Count;
for (long i=1; i<=count; i++) {
printf(" Certificate No. %d:\n", i);
if (pCert) {
pCert.Release();
pCert=NULL;
}
pCert = pChain->Certificates->Item[i];
if (pCert == NULL) {
printf("Can't get the %d-th certificate.\n",i);
return VARIANT_FALSE;
}
printf(" subject: %s\n",(LPSTR)pCert->SubjectName);
printf(" issuer: %s\n\n",(LPSTR)pCert->IssuerName);
}
// Examine the root certificate in the chain.
if (pCert) {
pCert.Release();
pCert=NULL;
}
pCert = pChain->Certificates->Item[count];
if (pCert == NULL) {
printf("Can't get root certificate.\n");
return VARIANT_FALSE;
}
printf("Display the Root certificate:\n");
printf(" subject: %s\n",(LPSTR)pCert->SubjectName);
printf(" issuer: %s\n\n",(LPSTR)pCert->IssuerName);
if (pCert) pCert.Release();
if (pChain) pChain.Release();
return VARIANT_TRUE;
}
VARIANT_BOOL VerifyXML(XMLDSIG_WRITEKEYINFO fWriteKeyInfo)
{
IXMLDOMNodePtr pKeyInfo, pNode;
IXMLDSigKeyPtr pKey, pKeyOut;
if (xmldsig->signature == NULL) {
printf("Invalid signature.\n");
return VARIANT_FALSE;
}
switch (fWriteKeyInfo & CERTIFICATES)
{
case CERTIFICATES:
pKeyInfo = xmldoc->selectSingleNode(
".//ds:KeyInfo/ds:X509Data");
break;
case KEYVALUE:
pKeyInfo = xmldoc->selectSingleNode(
".//ds:KeyInfo/ds:KeyValue");
break;
}
if (pKeyInfo == NULL) {
printf("Invalid <ds:KeyInfo>\n");
return VARIANT_FALSE;
}
pKey = xmldsig->createKeyFromNode(pKeyInfo);
if (pKey== NULL) {
printf("Invalid key from <ds:KeyInfo>\n");
return VARIANT_FALSE;
}
pKeyOut = xmldsig->verify(pKey);
if (pKeyOut== NULL) {
printf("Invalid signature.\n");
return VARIANT_FALSE;
}
printf("Signature verified on the data.\n\n");
if ( (fWriteKeyInfo & CERTIFICATES) == CERTIFICATES) {
if (IsCertificateValid(pKeyOut)) {
printf("Certificate used is valid.\n");
}
}
return VARIANT_TRUE;
}
VARIANT_BOOL initObjects()
{
if (FAILED(xmldsig.CreateInstance(__uuidof(MXDigitalSignature50)) )) {
printf("Installation of msxml5 is required to run this app.\n");
return VARIANT_FALSE;
}
if (FAILED(xmldoc.CreateInstance(__uuidof(DOMDocument50)) )) {
printf("Installation of msxml5 is required to run this app.\n");
return VARIANT_FALSE;
}
xmldoc->async = VARIANT_FALSE;
xmldoc->validateOnParse = VARIANT_FALSE;
xmldoc->preserveWhiteSpace = VARIANT_TRUE;
xmldoc->resolveExternals = VARIANT_FALSE;
objectsAreInitialized = VARIANT_TRUE;
return VARIANT_TRUE;
}
void cleanObjects()
{
if (xmldoc) xmldoc.Release();
if (xmldsig) xmldsig.Release();
}
void main()
{
if ( CoInitialize(NULL) == E_FAIL) {
printf("can't initialize COM Lib\n");
exit(-1);
}
if (!initObjects()) {
cleanObjects();
exit(-1);
}
printf("Verifying %s\n\n", INFILE);
if (VARIANT_TRUE == LoadXML(INFILE)) {
VerifyXML(CERTIFICATES);
}
cleanObjects();
CoUninitialize();
}
Try It!
Note You can also copy the file into the project's main directory using Windows Explorer (or a command prompt).