1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 /*
21  * XSEC
22  *
23  * SimpleHMAC := An application to generate an XML document (via Xerces) and sign it
24  *
25  * Author(s): Berin Lautenbach
26  *
27  * $ID$
28  *
29  * $LOG$
30  *
31  */
32 
33 #include "IOStreamOutputter.hpp"
34 
35 // Xerces
36 
37 #include <xercesc/util/PlatformUtils.hpp>
38 
39 // XML-Security-C (XSEC)
40 
41 #include <xsec/framework/XSECProvider.hpp>
42 #include <xsec/dsig/DSIGReference.hpp>
43 #include <xsec/framework/XSECException.hpp>
44 #include <xsec/utils/XSECPlatformUtils.hpp>
45 
46 #include "../utils/XSECDOMUtils.hpp"
47 
48 // Xalan
49 
50 #ifdef XSEC_HAVE_XALAN
51 #include <xalanc/XalanTransformer/XalanTransformer.hpp>
52 // If this isn't defined, we're on Xalan 1.12+ and require modern C++
53 #ifndef XALAN_USING_XALAN
54 # define XALAN_USING_XALAN(NAME) using xalanc :: NAME;
55 #endif
XALAN_USING_XALAN(XalanTransformer)56 XALAN_USING_XALAN(XalanTransformer)
57 #endif
58 
59 XERCES_CPP_NAMESPACE_USE
60 
61 DOMDocument *createLetter(DOMImplementation *impl) {
62 
63 	DOMDocument *doc = impl->createDocument(
64                 0,
65                 MAKE_UNICODE_STRING("Letter"),
66                 NULL);
67 
68     DOMElement *rootElem = doc->getDocumentElement();
69 
70 	// Add the ToAddress
71 
72 	DOMElement *addressElem = doc->createElement(MAKE_UNICODE_STRING("ToAddress"));
73 	rootElem->appendChild(doc->createTextNode(MAKE_UNICODE_STRING("\n")));
74 	rootElem->appendChild(addressElem);
75 	addressElem->appendChild(doc->createTextNode(
76 		MAKE_UNICODE_STRING("The address of the Recipient")));
77 
78 	// Add the FromAddress
79 	addressElem = doc->createElement(MAKE_UNICODE_STRING("FromAddress"));
80 	rootElem->appendChild(doc->createTextNode(MAKE_UNICODE_STRING("\n")));
81 	rootElem->appendChild(addressElem);
82 	addressElem->appendChild(doc->createTextNode(
83 		MAKE_UNICODE_STRING("The address of the Sender")));
84 
85 	// Add some text
86 	DOMElement *textElem = doc->createElement(MAKE_UNICODE_STRING("Text"));
87 	rootElem->appendChild(doc->createTextNode(MAKE_UNICODE_STRING("\n")));
88 	rootElem->appendChild(textElem);
89 	textElem->appendChild(doc->createTextNode(
90 		MAKE_UNICODE_STRING("\nTo whom it may concern\n\n...\n")));
91 
92 	return doc;
93 
94 }
95 
main(int argc,char ** argv)96 int main (int argc, char **argv) {
97 
98 	try {
99 		XMLPlatformUtils::Initialize();
100 #ifdef XSEC_HAVE_XALAN
101 		XalanTransformer::initialize();
102 #endif
103 		XSECPlatformUtils::Initialise();
104 	}
105 	catch (const XMLException &e) {
106 
107 		cerr << "Error during initialisation of Xerces" << endl;
108 		cerr << "Error Message = : "
109 		     << e.getMessage() << endl;
110 
111 	}
112 
113 	// Create a blank Document
114 
115     DOMImplementation *impl =
116 		DOMImplementationRegistry::getDOMImplementation(MAKE_UNICODE_STRING("Core"));
117 
118 	// Create a letter
119 	DOMDocument *doc = createLetter(impl);
120     DOMElement *rootElem = doc->getDocumentElement();
121 
122 	// The signature
123 
124 	XSECProvider prov;
125 	DSIGSignature *sig;
126 	DOMElement *sigNode;
127 
128 	try {
129 
130 		// Create a signature object
131 
132 		sig = prov.newSignature();
133 		sig->setDSIGNSPrefix(MAKE_UNICODE_STRING("ds"));
134 
135 		// Use it to create a blank signature DOM structure from the doc
136 
137 		sigNode = sig->createBlankSignature(doc,
138 				DSIGConstants::s_unicodeStrURIC14N_NOC,
139 				DSIGConstants::s_unicodeStrURIHMAC_SHA1);
140 
141 		// Inser the signature DOM nodes into the doc
142 
143 		rootElem->appendChild(doc->createTextNode(MAKE_UNICODE_STRING("\n")));
144 		rootElem->appendChild(sigNode);
145 		rootElem->appendChild(doc->createTextNode(MAKE_UNICODE_STRING("\n")));
146 
147 		// Create an envelope reference for the text to be signed
148 		DSIGReference * ref = sig->createReference(MAKE_UNICODE_STRING(""), DSIGConstants::s_unicodeStrURISHA1);
149 		ref->appendEnvelopedSignatureTransform();
150 
151 		// Set the HMAC Key to be the string "secret"
152 
153 		XSECCryptoKeyHMAC* hmacKey = XSECPlatformUtils::g_cryptoProvider->keyHMAC();
154 		hmacKey->setKey((unsigned char *) "secret", (unsigned int) strlen("secret"));
155 		sig->setSigningKey(hmacKey);
156 
157 		// Add a KeyInfo element
158 		sig->appendKeyName(MAKE_UNICODE_STRING("The secret key is \"secret\""));
159 
160 		// Sign
161 
162 		sig->sign();
163 	}
164 
165 	catch (const XSECException &e)
166 	{
167 		cerr << "An error occurred during a signature load\n   Message: "
168 		<< e.getMsg() << endl;
169 		exit(1);
170 
171 	}
172 
173 	// Output
174 
175 	docSetup(doc);
176 	cout << doc;
177 
178 	return 0;
179 
180 }
181