#include <stdio.h> #import <msxml5.dll> using namespace MSXML2; #define DSIGNS "xmlns:ds='http://www.w3.org/2000/09/xmldsig#'" // Change this key container name to your own if necessary. #define RSA_KEY "MyRSAFullKeys" #define INFILE "signature_template.setRef.rsa.xml" #define OUTFILE1 "signature.setRef.rsa.obj1.xml" #define OUTFILE2 "signature.setRef.rsa.obj2.xml" _bstr_t infile, outfile; 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; } 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; } VARIANT_BOOL SignXML(_bstr_t objID) { if (xmldsig->signature == NULL) { printf("Invalid signature template\n"); return false; } IXMLDSigKeyPtr pKey = xmldsig->createKeyFromCSP( PROV_RSA_FULL, "", RSA_KEY, 0); if (pKey==NULL) { printf("Invalid key\n"); return false; } _bstr_t xpath =".//ds:Object[@Id='"+ objID +"']"; IXMLDOMNodePtr pNode = xmldoc->selectSingleNode(xpath); if (pNode == NULL) { printf("Can't select node\n"); return false; } HRESULT hr = xmldsig->setReferenceData("#obj2", pNode); if (FAILED(hr)) { printf("Can't set reference data\n"); return false; } IXMLDSigKeyPtr pKeyOut = xmldsig->sign(pKey, KEYVALUE); if (NULL == pKeyOut) { printf("sign failed.\n"); return false; } printf("The specified data was signed successfully.\n"); printf("Resultant signature:\n\n"); printf((LPCSTR)xmldoc->xml); printf("\n"); hr = xmldoc->save(outfile); if (FAILED(hr)) { printf("can't save the signed signature file.\n"); return false; } return true; } VARIANT_BOOL VerifyXML(_bstr_t objID) { IXMLDOMNodePtr pKeyInfo, pNode; IXMLDSigKeyPtr pKey, pKeyOut; pKeyInfo = xmldoc->selectSingleNode(".//ds:KeyInfo/ds:KeyValue"); 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; } _bstr_t xpath = ".//ds:Object[@Id='"+ objID +"']"; pNode = xmldoc->selectSingleNode(xpath); HRESULT hr =xmldsig->setReferenceData("#obj2", pNode); if (FAILED(hr)) { printf("Can't set Reference data source\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"); 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); } infile = INFILE; printf("Attempting to sign the object of 'obj1'\n\n"); outfile = OUTFILE1; if (VARIANT_TRUE == LoadXML(infile)) { SignXML("obj1"); } if(VARIANT_TRUE == LoadXML(outfile)) { VerifyXML("obj1"); } printf("Attempting to sign the object of 'obj2'\n\n"); outfile = OUTFILE2; if (VARIANT_TRUE == LoadXML(infile)) { SignXML("obj2"); } if(VARIANT_TRUE == LoadXML(outfile)) { VerifyXML("obj2"); } cleanObjects(); CoUninitialize(); }
Try It!
Note You can also copy the file into the project's main directory using Windows Explorer (or a command prompt).