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

C/C++ Source: KeyFromNode.cpp

#include <stdio.h>
#import <msxml5.dll>
using namespace MSXML2;

#define DSIGNS "xmlns:ds='http://www.w3.org/2000/09/xmldsig#'"

IXMLDOMDocument3Ptr xmldoc = NULL;
IXMLDigitalSignaturePtr xmldsig = NULL;
VARIANT_BOOL objectsAreInitialized = VARIANT_FALSE;

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

   printf("\nInput signature element:\n\n%s\n", (LPCSTR)xmldoc->xml);

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

   return VARIANT_TRUE;

}

/////////////////////////////////////////////
// Verify signature with a key created from createKeyFromNode method.
//
VARIANT_BOOL VerifyXML()
{
   IXMLDOMNodePtr pKeyInfo;
   IXMLDSigKeyPtr pKey, pKeyOut;

   pKeyInfo = xmldoc->selectSingleNode(".//ds:KeyInfo/ds:KeyValue");
   if (pKeyInfo == NULL) {
      printf("Invalid <ds:KeyInfo/KeyValue>\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("The signature has been verified.\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;
   objectsAreInitialized = VARIANT_TRUE;

   return VARIANT_TRUE;
}

////////////////////////////////
// Helper function to release dom and dsig objects:
//
void cleanObjects()
{
   if (xmldoc) xmldoc.Release();
   if (xmldsig) xmldsig.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("signature.dsa.xml")) {
      if (VARIANT_TRUE != VerifyXML()) {
         printf("exit with failure.\n");
      }
   }

   cleanObjects();
   CoUninitialize();
}

Try It!

  1. Ensure that you have completed all the procedures in Getting Started with XML Digital Signatures.
  2. Start Visual C++.
  3. From the File menu, select New. On the Projects tab of the New dialog box that appears, select Win32 Console Application in the left pane. Then type "KeyFromNodeProj" in the Project name field. For the project Location field, either accept the default setting or choose another location. Click OK.
  4. The Win32 Console Application property page will appear. For the type of Console Application, select An empty project and click Finish. When the New Project Information box displays, click OK.
  5. Select FileView on the project browser, and highlight KeyFromNodeProj files. From the File menu, select New.
  6. On the Files tab of the New dialog box, highlight C++ Source File. Then type "signature.dsa.xml" in the File name text box.
  7. Click OK.
  8. Copy the XML signature resource file, and paste it into the text file you just created.
  9. Repeat steps 5-8 for the C++ file above (KeyFromNode.cpp).
  10. Build the sample by selecting Build KeyFromNodeProj.exe from the Build menu.
  11. Execute the sample application by selecting !Execute KeyFromNodeProj.exe from the Build menu.
  12. Verify that your output is the same as that listed in the Output topic.