Microsoft XML Core Services (MSXML) 5.0 for Microsoft Office - Digital Signatures

C/C++ Source: setDebugOutput.cpp

This is the main program for the setDebugOutput Method example. This code performs the following steps:

  1. Instantiates DBStream.
  2. Calls setDebugOutput.
  3. Calls on an XML DOM object that has loaded the signature.template.xml file.
  4. Calls verify on the signed signature document, signature.document.xml.
#include <stdio.h>
#import <msxml5.dll>
using namespace MSXML2;
#include "DBStream.h"

#define DSIGNS "xmlns:ds='http://www.w3.org/2000/09/xmldsig#'"
#define SIG_TEMP "signature.template.xml"
#define SIG_DOC  "signature.document.xml"
// Change this key container name to your own if necessary.
#define RSA_KEY "myRSAFullKeys"

IXMLDOMDocument3Ptr xmldoc = NULL;
IXMLDigitalSignatureExPtr xmldsig = NULL;
VARIANT_BOOL objectsAreInitialized = VARIANT_FALSE;
DBStream * dbStream = NULL;

//////////////////////////////////////////////////
// Load a signature document into dom and assign it to the xmldsig object.
//
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;
   }

   xmldoc->setProperty("SelectionNamespaces", DSIGNS);

   // 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;
   }

   printf("\n%s has been loaded into an XML DOM\n\n",(LPCSTR)sigFile);
   return VARIANT_TRUE;
}

/////////////////////////////////////////////
// Verify signature with a key embedded in the signature document.
//
VARIANT_BOOL VerifyXML()
{
   IXMLDSigKeyPtr  pKeyOut;

   pKeyOut = xmldsig->verify(NULL);
   if (pKeyOut== NULL) {
      printf("Invalid signature.\n");
      return VARIANT_FALSE;
   }

   printf("\nSignature verified.\n\n");
   return VARIANT_TRUE;
}


VARIANT_BOOL SignXML(XMLDSIG_WRITEKEYINFO fwWriteKeyInfo)
{
   if (xmldsig->signature == NULL) {
      printf("Invalid signature template\n");
      return VARIANT_FALSE;
   }

   IXMLDSigKeyPtr pKey = xmldsig->createKeyFromCSP(
            PROV_RSA_FULL, "", RSA_KEY, 0);
   if (pKey==NULL) {
      printf("Invalid key\n");
      return VARIANT_FALSE;
   }

   IXMLDSigKeyPtr pKeyOut = xmldsig->sign(pKey, fwWriteKeyInfo);
   if (NULL == pKeyOut) {
      printf("sign failed.\n");
      return VARIANT_FALSE;
   }

   printf("\nData signed.\n\n");

   return VARIANT_TRUE;
}


/////////////////////////////////
// Helper function to create dom and dsig objects:
//
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;
   
   dbStream = new DBStream();
   if (dbStream==NULL) {
      printf("Can't instantiate DBStream\n");
      return VARIANT_FALSE;
   }

   HRESULT hr = xmldsig->setDebugOutput(dbStream);
   if (FAILED(hr)) {
      printf("Can't setDebugOutput\n");
      return VARIANT_FALSE;
   }

   objectsAreInitialized = VARIANT_TRUE;
   return VARIANT_TRUE;
}

////////////////////////////////
// Helper function to release dom and dsig objects:
//
void cleanObjects()
{
   if (xmldoc) xmldoc.Release();
   if (xmldsig) xmldsig.Release();
   if (dbStream) dbStream->Release();
}

/////////////////////////////////
// Main function:
//
void main() 
{
   if ( CoInitialize(NULL) == E_FAIL) {
      printf("can't initialize COM Lib\n");
      exit(-1);
   }

   if (!initObjects()) {
      cleanObjects();
      exit(-1);
   }

   if(VARIANT_TRUE == LoadXML(SIG_TEMP)) {
      if (VARIANT_TRUE != SignXML(KEYVALUE)) {
         printf("exit with failure.\n");
      }
      xmldoc->save(SIG_DOC);
   }

   if(VARIANT_TRUE == LoadXML(SIG_DOC)) {
      if (VARIANT_TRUE != VerifyXML()) {
         printf("exit with failure.\n");
      }
   }

   cleanObjects();
   CoUninitialize();
}