#import <msxml5.dll> using namespace MSXML2; #include <stdio.h> #include <wincrypt.h> #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.setStoreHandle.rsa.xml"
IXMLDOMDocument3Ptr xmldoc = NULL;
IXMLDigitalSignatureExPtr xmldsig = NULL;
VARIANT_BOOL objectsAreInitialized = VARIANT_FALSE;
HCERTSTORE hCertStore = NULL;
// Method that loads a source xml file:
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;
}
// Method that signs a signature document:
VARIANT_BOOL SignXML(XMLDSIG_WRITEKEYINFO fwWriteKeyInfo)
{
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;
}
IXMLDSigKeyPtr pKeyOut = xmldsig->sign(pKey, fwWriteKeyInfo);
if (NULL == pKeyOut) {
printf("sign failed.\n");
return false;
}
printf("The specified data was signed successfully.\n");
printf("Resultant signature:\n");
printf((LPCSTR)xmldoc->xml);
printf("\n");
return true;
}
//
// Initialize the project: creating DOM and opening the "MY" certificate store.
//
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;
if(hCertStore = CertOpenSystemStore(0, "MY"))
{
printf("The MY system store is open. Continue.\n");
}
else
{
printf("The MY system setStoreHandle did not open.\n");
return VARIANT_FALSE;
}
objectsAreInitialized = VARIANT_TRUE;
return VARIANT_TRUE;
}
void cleanObjects()
{
if (xmldoc) xmldoc.Release();
if (xmldsig) xmldsig.Release();
if (hCertStore) CertCloseStore(hCertStore, 0);
}
void main()
{
HRESULT hr;
if ( CoInitialize(NULL) == E_FAIL) {
printf("can't initialize COM Lib\n");
exit(-1);
}
if (!initObjects()) {
cleanObjects();
exit(-1);
}
if (VARIANT_TRUE == LoadXML(INFILE)) {
// First sign without setting a store handle.
printf("Sign with fwWriteKeyInfo = CERTIFICATES:\n");
SignXML(CERTIFICATES);
if (hCertStore) {
hr = xmldsig->setStoreHandle((void*)hCertStore);
printf("the store is set on xmldsig.\n");
}
else {
printf("invalid certstore\n");
}
// Then sign with setting a store handle.
printf("Sign with fwWriteKeyInfo = CERTIFICATES:\n");
SignXML(XMLDSIG_WRITEKEYINFO(CERTIFICATES|PURGE));
}
cleanObjects();
CoUninitialize();
}
Try It!