C/C++ Source: KeyFromHMACSecret.cpp
#include <stdio.h>
#import <msxml5.dll>
using namespace MSXML2;
#define HMACSECRET "c2VjcmV0"
#define HMACLENGTH -1
#define DSIGNS "xmlns:ds='http://www.w3.org/2000/09/xmldsig#'"
#define SIG_IN "signature-template-enveloping-hmac-sha1.xml"
#define SIG_OUT "signature-enveloping-hmac-sha1.xml"
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);
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(char *secret, long length)
{
IXMLDSigKeyPtr pKey, pKeyOut;
if (xmldsig->signature == NULL)
{
printf("Invalid signature template.\n");
return VARIANT_FALSE;
}
pKey = xmldsig->createKeyFromHMACSecret(_bstr_t(secret), length);
if (pKey== NULL) {
printf("Invalid key from HMACsecret\n");
return VARIANT_FALSE;
}
// KEYVALUE is defined in XMLDSIG_WRITEKEYINFO enum.
pKeyOut = xmldsig->sign(pKey, KEYVALUE);
if (pKeyOut== NULL) {
printf("Invalid signature.\n");
return VARIANT_FALSE;
}
xmldoc->save(SIG_OUT);
printf("The data referenced in the signature template was signed ");
printf("successfully.\nResultant signature:\n\n%s\n",(LPCSTR)xmldoc->xml);
return VARIANT_TRUE;
}
VARIANT_BOOL VerifyXML(char* secret, long length)
{
IXMLDSigKeyPtr pKey, pKeyOut;
pKey = xmldsig->createKeyFromHMACSecret(_bstr_t(secret), length);
if (pKey== NULL) {
printf("Invalid key from HMACSecret\n");
return VARIANT_FALSE;
}
pKeyOut = xmldsig->verify(pKey);
if (pKeyOut== NULL) {
printf("Invalid signature.\n");
return VARIANT_FALSE;
}
printf("The data referenced in the signature object was verified successfully.\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;
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);
}
if(VARIANT_TRUE == LoadXML(SIG_IN)) {
if (VARIANT_TRUE != SignXML(HMACSECRET, HMACLENGTH)) {
printf("exit with failure.\n");
goto clean;
}
}
if(VARIANT_TRUE == LoadXML(SIG_OUT)) {
if (VARIANT_TRUE != VerifyXML(HMACSECRET, HMACLENGTH)) {
printf("exit with failure.\n");
goto clean;
}
}
clean:
cleanObjects();
CoUninitialize();
}
Try It!
- Ensure that you have completed all the procedures in Getting Started with XML Digital Signatures.
- Start Visual C++.
- 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 " KeyFromHMACSecretProj" in the Project name field. For the project Location field, either accept the default setting or choose another location. Click OK.
- 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.
- Select FileView on the project browser, and highlight KeyFromHMACSecretProj files. From the File menu, select New.
- On the Files tab of the New dialog box, highlight C++ Source File. Then type "signature-template-enveloping-hmac-sha1.xml" in the File name text box.
- Click OK.
- Copy the XML signature template file from Resource File, and paste it into the text file you just created.
- Repeat steps 5-8 for the C++ file above (KeyFromHMACSecret.cpp).
- From the Project menu, click Settings..., then click the Link tab.
- In Object/library modules, type "crypt32.lib". Insert this text either before or after the existing string that lists all objects and modules for the current project. Then click OK.
- Build the sample by selecting Build KeyFromHMACSecretProj.exe from the Build menu.
- Execute the sample application by selecting !Execute KeyFromHMACSecretProj.exe from the Build menu.
- Verify that your output is similar to that listed in the Output topic.
