#include <stdio.h> #include <windows.h> #include <wincrypt.h> #import <msxml5.dll> using namespace MSXML2; #define DSIGNS "xmlns:ds='http://www.w3.org/2000/09/xmldsig#'" #define SIG_IN "signature_template.rsa.xml" IXMLDOMDocument3Ptr xmldoc = NULL; IXMLDigitalSignatureExPtr xmldsig = NULL; VARIANT_BOOL objectsAreInitialized = VARIANT_FALSE; // Get the first certifcate context from the "MY" system store. PCCERT_CONTEXT GetCertContext() { HCERTSTORE hCertStore=NULL; PCCERT_CONTEXT pCert=NULL; #define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING) hCertStore = CertOpenSystemStore(0, "MY"); if (!hCertStore) { printf("failed to open store\n"); return NULL; } pCert = CertFindCertificateInStore( hCertStore, MY_ENCODING_TYPE, 0, CERT_FIND_ANY, NULL, NULL); if (!pCert) { printf("Failed to find certificate in store\n"); return NULL; } CertCloseStore(hCertStore, CERT_CLOSE_STORE_CHECK_FLAG); return pCert; } // Load an XML file (a signature template), sigFile, as a DOM 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); xmldsig->signature = xmldoc->selectSingleNode(".//ds:Signature"); if (xmldsig->signature == NULL) { printf("Failed to set the signature property.\n"); return VARIANT_FALSE; } return VARIANT_TRUE; } // Sign the XML data embedded in the signature template. VARIANT_BOOL SignXML() { IXMLDSigKeyPtr pKey, pKeyOut; if (xmldsig->signature == NULL) { printf("Invalid signature template.\n"); return VARIANT_FALSE; } PCCERT_CONTEXT pCertContext = GetCertContext(); pKey = xmldsig->createKeyFromCertContext((void*)pCertContext); if (pKey== NULL) { printf("Invalid key from CertContext\n"); return VARIANT_FALSE; } pKeyOut = xmldsig->sign(pKey, KEYVALUE); if (pKeyOut== NULL) { printf("Invalid signature.\n"); return VARIANT_FALSE; } CertFreeCertificateContext(pCertContext); printf("The data referenced in the signature template was signed "); printf("successfully.\nResultant signature:\n\n%s\n",(LPCSTR)xmldoc->xml); return VARIANT_TRUE; } // Helper function that creates and initiates required DOM 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; xmldoc->resolveExternals = VARIANT_FALSE; objectsAreInitialized = VARIANT_TRUE; return VARIANT_TRUE; } // Helper function that releases objects of the application scope: 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); } if(VARIANT_TRUE == LoadXML(SIG_IN)) { if (VARIANT_TRUE != SignXML()) { printf("exit with failure.\n"); } } cleanObjects(); CoUninitialize(); }
Try It!
Note You can also copy the file into the project's main directory using Windows Explorer (or a command prompt).