in xsec/tools/xtest/xtest.cpp [1228:1610]
void testSignature(DOMImplementation *impl) {
cerr << "Creating a known doc and signing (HMAC-SHA1)" << endl;
// Create a document
DOMDocument * doc = createTestDoc(impl);
// Check signature functions
XSECProvider prov;
DSIGSignature *sig;
DSIGReference *ref[10];
DOMElement *sigNode;
int refCount;
try {
/*
* Now we have a document, create a signature for it.
*/
sig = prov.newSignature();
sig->setDSIGNSPrefix(MAKE_UNICODE_STRING("ds"));
sig->setPrettyPrint(true);
sigNode = sig->createBlankSignature(doc,
DSIGConstants::s_unicodeStrURIC14N_COM,
DSIGConstants::s_unicodeStrURIHMAC_SHA1);
DOMElement * rootElem = doc->getDocumentElement();
DOMNode * prodElem = rootElem->getFirstChild();
rootElem->appendChild(doc->createTextNode(DSIGConstants::s_unicodeStrNL));
rootElem->insertBefore(doc->createComment(MAKE_UNICODE_STRING(" a comment ")), prodElem);
rootElem->appendChild(sigNode);
rootElem->insertBefore(doc->createTextNode(DSIGConstants::s_unicodeStrNL), prodElem);
/*
* Add some test references
*/
ref[0] = sig->createReference(MAKE_UNICODE_STRING(""),
DSIGConstants::s_unicodeStrURISHA1);
ref[0]->appendEnvelopedSignatureTransform();
ref[1] = sig->createReference(MAKE_UNICODE_STRING("#xpointer(/)"),
DSIGConstants::s_unicodeStrURISHA1);
ref[1]->appendEnvelopedSignatureTransform();
ref[1]->appendCanonicalizationTransform(DSIGConstants::s_unicodeStrURIC14N_NOC);
ref[2] = sig->createReference(MAKE_UNICODE_STRING("#xpointer(/)"),
DSIGConstants::s_unicodeStrURISHA1);
ref[2]->appendEnvelopedSignatureTransform();
ref[2]->appendCanonicalizationTransform(DSIGConstants::s_unicodeStrURIC14N_COM);
ref[3] = sig->createReference(MAKE_UNICODE_STRING("#xpointer(/)"),
DSIGConstants::s_unicodeStrURISHA1);
ref[3]->appendEnvelopedSignatureTransform();
ref[3]->appendCanonicalizationTransform(DSIGConstants::s_unicodeStrURIEXC_C14N_NOC);
ref[4] = sig->createReference(MAKE_UNICODE_STRING("#xpointer(/)"),
DSIGConstants::s_unicodeStrURISHA1);
ref[4]->appendEnvelopedSignatureTransform();
ref[4]->appendCanonicalizationTransform(DSIGConstants::s_unicodeStrURIEXC_C14N_COM);
ref[5] = sig->createReference(MAKE_UNICODE_STRING("#xpointer(/)"),
DSIGConstants::s_unicodeStrURISHA1);
ref[5]->appendEnvelopedSignatureTransform();
DSIGTransformC14n * ce = ref[5]->appendCanonicalizationTransform(
DSIGConstants::s_unicodeStrURIEXC_C14N_COM);
ce->addInclusiveNamespace("foo");
sig->setECNSPrefix(MAKE_UNICODE_STRING("ec"));
ref[6] = sig->createReference(MAKE_UNICODE_STRING("#xpointer(/)"),
DSIGConstants::s_unicodeStrURISHA1);
ref[6]->appendEnvelopedSignatureTransform();
ce = ref[6]->appendCanonicalizationTransform(
DSIGConstants::s_unicodeStrURIEXC_C14N_COM);
ce->addInclusiveNamespace("foo");
#ifndef XSEC_HAVE_XALAN
cerr << "WARNING : No testing of XPath being performed as Xalan not present" << endl;
refCount = 7;
#else
/*
* Create some XPath/XPathFilter references
*/
ref[7] = sig->createReference(MAKE_UNICODE_STRING(""),
DSIGConstants::s_unicodeStrURISHA1);
sig->setXPFNSPrefix(MAKE_UNICODE_STRING("xpf"));
DSIGTransformXPathFilter * xpf = ref[7]->appendXPathFilterTransform();
xpf->appendFilter(DSIGXPathFilterExpr::FILTER_INTERSECT, MAKE_UNICODE_STRING("//ADoc/category"));
ref[8] = sig->createReference(MAKE_UNICODE_STRING(""),
DSIGConstants::s_unicodeStrURISHA1);
/* ref[5]->appendXPathTransform("ancestor-or-self::dsig:Signature",
"xmlns:dsig=http://www.w3.org/2000/09/xmldsig#"); */
DSIGTransformXPath * x = ref[8]->appendXPathTransform("count(ancestor-or-self::dsig:Signature | \
here()/ancestor::dsig:Signature[1]) > \
count(ancestor-or-self::dsig:Signature)");
x->setNamespace("dsig", "http://www.w3.org/2000/09/xmldsig#");
refCount = 9;
#endif
/*
* Sign the document, using an HMAC algorithm and the key "secret"
*/
sig->appendKeyName(MAKE_UNICODE_STRING("The secret key is \"secret\""));
// Append a test DNames
DSIGKeyInfoX509 * x509 = sig->appendX509Data();
x509->setX509SubjectName(s_tstDName);
// Append a test PGPData element
sig->appendPGPData(s_tstPGPKeyID, s_tstPGPKeyPacket);
// Append an SPKIData element
DSIGKeyInfoSPKIData * spki = sig->appendSPKIData(s_tstSexp1);
spki->appendSexp(s_tstSexp2);
// Append a MgmtData element
sig->appendMgmtData(s_tstMgmtData);
sig->setSigningKey(createHMACKey((unsigned char *) "secret"));
sig->sign();
// Output the document post signature if necessary
outputDoc(impl, doc);
cerr << endl << "Doc signed OK - Checking values against Known Good" << endl;
unsigned char buf[128];
XMLSize_t len;
/*
* Validate the reference hash values from known good
*/
int i;
for (i = 0; i < refCount; ++i) {
cerr << "Calculating hash for reference " << i << " ... ";
len = (int) ref[i]->calculateHash(buf, 128);
cerr << " Done\nChecking -> ";
if (len != 20) {
cerr << "Bad (Length = " << len << ")" << endl;
exit (1);
}
for (int j = 0; j < 20; ++j) {
if (buf[j] != createdDocRefs[i][j]) {
cerr << "Bad at location " << j << endl;
exit (1);
}
}
cerr << "Good.\n";
}
/*
* Verify the signature check works
*/
cerr << "Running \"verifySignatureOnly()\" on calculated signature ... ";
if (sig->verifySignatureOnly()) {
cerr << "OK" << endl;
}
else {
cerr << "Failed" << endl;
char * e = XMLString::transcode(sig->getErrMsgs());
cout << e << endl;
XSEC_RELEASE_XMLCH(e);
exit(1);
}
/*
* Change the document and ensure the signature fails.
*/
cerr << "Setting incorrect key in Signature object" << endl;
sig->setSigningKey(createHMACKey((unsigned char *) "badsecret"));
cerr << "Running \"verifySignatureOnly()\" on calculated signature ... ";
if (!sig->verifySignatureOnly()) {
cerr << "OK (Signature bad)" << endl;
}
else {
cerr << "Failed (signature OK but should be bad)" << endl;
exit(1);
}
// Don't need the signature now the DOM structure is in place
prov.releaseSignature(sig);
/*
* Now serialise the document to memory so we can re-parse and check from scratch
*/
cerr << "Serialising the document to a memory buffer ... ";
MemBufFormatTarget *formatTarget = new MemBufFormatTarget();
DOMLSSerializer *theSerializer = ((DOMImplementationLS*)impl)->createLSSerializer();
// Get the config so we can set up pretty printing
DOMConfiguration *dc = theSerializer->getDomConfig();
dc->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, false);
// Now create an output object to format to UTF-8
DOMLSOutput *theOutput = ((DOMImplementationLS*)impl)->createLSOutput();
Janitor<DOMLSOutput> j_theOutput(theOutput);
theOutput->setEncoding(MAKE_UNICODE_STRING("UTF-8"));
theOutput->setByteStream(formatTarget);
theSerializer->write(doc,theOutput);
// Copy to a new buffer
len = formatTarget->getLen();
char * mbuf = new char [len + 1];
memcpy(mbuf, formatTarget->getRawBuffer(), len);
mbuf[len] = '\0';
#if 0
cout << mbuf << endl;
#endif
delete theSerializer;
delete formatTarget;
cerr << "done\nParsing memory buffer back to DOM ... ";
// Also release the document so that we can re-load from scratch
doc->release();
/*
* Re-parse
*/
XercesDOMParser parser;
parser.setDoNamespaces(true);
parser.setCreateEntityReferenceNodes(true);
MemBufInputSource* memIS = new MemBufInputSource ((const XMLByte*) mbuf,
len, "XSECMem");
parser.parse(*memIS);
doc = parser.adoptDocument();
delete(memIS);
delete[] mbuf;
cerr << "done\nValidating signature ...";
/*
* Validate signature
*/
sig = prov.newSignatureFromDOM(doc);
sig->load();
sig->setSigningKey(createHMACKey((unsigned char *) "secret"));
if (sig->verify()) {
cerr << "OK" << endl;
}
else {
cerr << "Failed\n" << endl;
char * e = XMLString::transcode(sig->getErrMsgs());
cerr << e << endl;
XSEC_RELEASE_XMLCH(e);
exit(1);
}
/*
* Ensure DNames are read back in and decoded properly
*/
DSIGKeyInfoList * kil = sig->getKeyInfoList();
int nki = (int) kil->getSize();
cerr << "Checking Distinguished name is decoded correctly ... ";
for (i = 0; i < nki; ++i) {
if (kil->item(i)->getKeyInfoType() == DSIGKeyInfo::KEYINFO_X509) {
if (strEquals(s_tstDName, ((DSIGKeyInfoX509 *) kil->item(i))->getX509SubjectName())) {
cerr << "yes" << endl;
}
else {
cerr << "decoded incorrectly" << endl;;
exit (1);
}
}
if (kil->item(i)->getKeyInfoType() == DSIGKeyInfo::KEYINFO_PGPDATA) {
cerr << "Validating PGPData read back OK ... ";
DSIGKeyInfoPGPData * p = (DSIGKeyInfoPGPData *)kil->item(i);
if (!(strEquals(p->getKeyID(), s_tstPGPKeyID) &&
strEquals(p->getKeyPacket(), s_tstPGPKeyPacket))) {
cerr << "no!";
exit(1);
}
cerr << "yes\n";
}
if (kil->item(i)->getKeyInfoType() == DSIGKeyInfo::KEYINFO_SPKIDATA) {
cerr << "Validating SPKIData read back OK ... ";
DSIGKeyInfoSPKIData * s = (DSIGKeyInfoSPKIData *)kil->item(i);
if (s->getSexpSize() != 2) {
cerr << "no - expected two S-expressions";
exit(1);
}
if (!(strEquals(s->getSexp(0), s_tstSexp1) &&
strEquals(s->getSexp(1), s_tstSexp2))) {
cerr << "no!";
exit(1);
}
cerr << "yes\n";
}
if (kil->item(i)->getKeyInfoType() == DSIGKeyInfo::KEYINFO_MGMTDATA) {
cerr << "Validating MgmtData read back OK ... ";
DSIGKeyInfoMgmtData * m = (DSIGKeyInfoMgmtData *)kil->item(i);
if (!strEquals(m->getData(), s_tstMgmtData)) {
cerr << "no!";
exit(1);
}
cerr << "yes\n";
}
}
}
catch (const XSECException &e)
{
cerr << "An error occurred during signature processing\n Message: ";
char * ce = XMLString::transcode(e.getMsg());
cerr << ce << endl;
delete ce;
exit(1);
}
catch (const XSECCryptoException &e)
{
cerr << "A cryptographic error occurred during signature processing\n Message: "
<< e.getMsg() << endl;
exit(1);
}
// Output the document post signature if necessary
outputDoc(impl, doc);
doc->release();
}