void XMLSecurityTest::testValidate() { xml_schema::properties& props(XbeLibUtils::schema_properties()); try { // parse the xbe message std::auto_ptr<xbemsg::message_t> msg = xbemsg::message("resources/signed-message-1.xml", xml_schema::flags::dont_initialize | xml_schema::flags::keep_dom, props); // serialize to DOMDocument xml_schema::dom::auto_ptr< ::xercesc::DOMDocument > doc = xbemsg::message(*msg, XbeLibUtils::namespace_infomap()); XSECProvider prov; DSIGSignature *sig = prov.newSignatureFromDOM(doc.get()); sig->load(); // Set the HMAC Key to be the string "secret" OpenSSLCryptoProvider cryptoProvider; XSECCryptoKeyHMAC *hmacKey = cryptoProvider.keyHMAC(); hmacKey->setKey((unsigned char*)"secret", strlen("secret")); sig->setSigningKey(hmacKey); bool isValid(sig->verify()); char *errMsgs = XMLString::transcode(sig->getErrMsgs()); // Verify CPPUNIT_ASSERT_MESSAGE(errMsgs, isValid); XMLString::release(&errMsgs); prov.releaseSignature(sig); } catch (const std::exception& e) { CPPUNIT_ASSERT_MESSAGE(e.what(), false); } }
int main(int argc, char **argv) { XSECCryptoKey * key = NULL; DSIGKeyInfoX509 * keyInfoX509 = NULL; OpenSSLCryptoX509 * certs[128]; int certCount = 0; int paramCount; bool clearKeyInfo = false; // Initialise the XML system try { XMLPlatformUtils::Initialize(); #ifndef XSEC_NO_XALAN XPathEvaluator::initialize(); XalanTransformer::initialize(); #endif XSECPlatformUtils::Initialise(); } catch (const XMLException &e) { cerr << "Error during initialisation of Xerces" << endl; cerr << "Error Message = : " << e.getMessage() << endl; } // Initialise OpenSSL ERR_load_crypto_strings(); BIO * bio_err; if ((bio_err=BIO_new(BIO_s_file())) != NULL) BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); if (argc < 2) { printUsage(); exit (1); } paramCount = 1; while (paramCount < argc - 1) { // Run through all parameters if (stricmp(argv[paramCount], "--dsakey") == 0 || stricmp(argv[paramCount], "-d") == 0 || stricmp(argv[paramCount], "--rsakey") == 0 || stricmp(argv[paramCount], "-r") == 0) { // DSA or RSA Key if (paramCount + 3 >= argc) { printUsage(); exit (1); } if (key != 0) { cerr << "\nError loading RSA or DSA key - another key already loaded\n\n"; printUsage(); exit(1); } // Load the signing key // For now just read a particular file BIO * bioKey; if ((bioKey = BIO_new(BIO_s_file())) == NULL) { cerr << "Error opening private key file\n\n"; exit (1); } if (BIO_read_filename(bioKey, argv[paramCount + 1]) <= 0) { cerr << "Error opening private key file\n\n"; exit (1); } EVP_PKEY * pkey; pkey = PEM_read_bio_PrivateKey(bioKey,NULL,NULL,argv[paramCount + 2]); if (pkey == NULL) { cerr << "Error loading private key\n\n"; ERR_print_errors(bio_err); exit (1); } if (stricmp(argv[paramCount], "--dsakey") == 0 || stricmp(argv[paramCount], "-d") == 0) { // Check type is correct if (pkey->type != EVP_PKEY_DSA) { cerr << "DSA Key requested, but OpenSSL loaded something else\n"; exit (1); } // Create the XSEC OpenSSL interface key = new OpenSSLCryptoKeyDSA(pkey); } else { if (pkey->type != EVP_PKEY_RSA) { cerr << "RSA Key requested, but OpenSSL loaded something else\n"; exit (1); } key = new OpenSSLCryptoKeyRSA(pkey); } EVP_PKEY_free(pkey); BIO_free(bioKey); paramCount += 3; } /* argv[1] = "dsa/rsa" */ else if (stricmp(argv[paramCount], "--x509cert") == 0 || stricmp(argv[paramCount], "-x") == 0) { // X509Data keyInfo if (paramCount + 2 >= argc) { printUsage(); exit (1); } // Load the signing key // For now just read a particular file BIO * bioX509; if ((bioX509 = BIO_new(BIO_s_file())) == NULL) { cerr << "Error opening file\n\n"; exit (1); } if (BIO_read_filename(bioX509, argv[paramCount + 1]) <= 0) { cerr << "Error opening X509 Certificate " << argv[paramCount + 1] << "\n\n"; exit (1); } X509 * x ; x = PEM_read_bio_X509_AUX(bioX509,NULL,NULL,NULL); if (x == NULL) { cerr << "Error loading certificate key\n\n"; ERR_print_errors(bio_err); exit (1); } // Create the XSEC OpenSSL interface - used only to translate to Base64 certs[certCount++] = new OpenSSLCryptoX509(x); X509_free(x); BIO_free(bioX509); paramCount += 2; } /* argv[1] = "--x509cert" */ else if (stricmp(argv[paramCount], "--hmackey") == 0 || stricmp(argv[paramCount], "-h") == 0) { OpenSSLCryptoKeyHMAC * hmacKey = new OpenSSLCryptoKeyHMAC(); hmacKey->setKey((unsigned char *) argv[paramCount + 1], strlen(argv[paramCount + 1])); key = hmacKey; paramCount += 2; } else if (stricmp(argv[paramCount], "--clearkeys") == 0 || stricmp(argv[paramCount], "-c") == 0) { clearKeyInfo = true; paramCount += 1; } else { printUsage(); exit(1); } } // Create and set up the parser XercesDOMParser * parser = new XercesDOMParser; parser->setDoNamespaces(true); parser->setCreateEntityReferenceNodes(true); // Now parse out file bool errorsOccured = false; int errorCount = 0; try { parser->parse(argv[argc - 1]); errorCount = parser->getErrorCount(); if (errorCount > 0) errorsOccured = true; } catch (const XMLException& e) { cerr << "An error occured during parsing\n Message: " << e.getMessage() << endl; errorsOccured = true; } catch (const DOMException& e) { cerr << "A DOM error occured during parsing\n DOMException code: " << e.code << endl; errorsOccured = true; } if (errorsOccured) { cout << "Errors during parse" << endl; exit (1); } /* Now that we have the parsed file, get the DOM document and start looking at it */ DOMNode *doc; // The document that we parsed doc = parser->getDocument(); DOMDocument *theDOM = parser->getDocument(); // Find the signature node DOMNode *sigNode = findDSIGNode(doc, "Signature"); // Create the signature checker if (sigNode == 0) { cerr << "Could not find <Signature> node in " << argv[argc-1] << endl; exit(1); } XSECProvider prov; DSIGSignature * sig = prov.newSignatureFromDOM(theDOM, sigNode); int i; try { sig->load(); if (clearKeyInfo == true) sig->clearKeyInfo(); if (key != NULL) sig->setSigningKey(key); sig->sign(); // Add any KeyInfo elements if (certCount > 0) { // Have some certificates - see if there is already an X509 list DSIGKeyInfoList * kiList = sig->getKeyInfoList(); int kiSize = kiList->getSize(); for (i = 0; i < kiSize; ++i) { if (kiList->item(i)->getKeyInfoType() == DSIGKeyInfo::KEYINFO_X509) { keyInfoX509 = (DSIGKeyInfoX509 *) kiList->item(i); break; } } if (keyInfoX509 == 0) { // Not found - need to create keyInfoX509 = sig->appendX509Data(); } for (i = 0; i < certCount; ++i) { keyInfoX509->appendX509Certificate(certs[i]->getDEREncodingSB().rawCharBuffer()); } } /* certCount > 0 */ } catch (XSECException &e) { cerr << "An error occured during signature verification\n Message: " << e.getMsg() << endl; errorsOccured = true; exit (1); } // Print out the result DOMPrintFormatTarget* formatTarget = new DOMPrintFormatTarget(); const XMLCh* encNameStr = XMLString::transcode("UTF-8"); DOMNode *aNode = doc->getFirstChild(); if (aNode->getNodeType() == DOMNode::ENTITY_NODE) { const XMLCh* aStr = ((DOMEntity *)aNode)->getEncoding(); if (!strEquals(aStr, "")) { encNameStr = aStr; } } unsigned int lent = XMLString::stringLen(encNameStr); gEncodingName = new XMLCh[lent + 1]; XMLString::copyNString(gEncodingName, encNameStr, lent); gEncodingName[lent] = 0; gFormatter = new XMLFormatter("UTF-8", formatTarget, XMLFormatter::NoEscapes, gUnRepFlags); cout << doc; prov.releaseSignature(sig); return 0; }
void XMLSecurityLibraryTest::testSign() { XBE_LOG_DEBUG("signing a xbe-message document by hand"); xsd::cxx::xml::dom::auto_ptr<xercesc::DOMDocument> doc(create("message", "http://www.xenbee.net/schema/2008/02/xbe-msg", "xbemsg")); DOMElement* root = doc->getDocumentElement(); root->setAttributeNS(xml::string("http://www.w3.org/2000/xmlns/").c_str(), xml::string("xmlns:xbemsg").c_str(), xml::string("http://www.xenbee.net/schema/2008/02/xbe-msg").c_str()); /* HEADER */ DOMElement* hdrElem = doc->createElementNS(xml::string("http://www.xenbee.net/schema/2008/02/xbe-msg").c_str(), xml::string("xbemsg:header").c_str()); root->appendChild(hdrElem); DOMElement* toElem = doc->createElementNS(xml::string("http://www.xenbee.net/schema/2008/02/xbe-msg").c_str(), xml::string("xbemsg:to").c_str()); hdrElem->appendChild(toElem); DOMText* toTxt = doc->createTextNode(xml::string("foo.bar").c_str()); toElem->appendChild(toTxt); DOMElement* fromElem = doc->createElementNS(xml::string("http://www.xenbee.net/schema/2008/02/xbe-msg").c_str(), xml::string("xbemsg:from").c_str()); hdrElem->appendChild(fromElem); DOMText* fromTxt = doc->createTextNode(xml::string("foo.bar").c_str()); fromElem->appendChild(fromTxt); /* BODY */ DOMElement* bodyElem = doc->createElementNS(xml::string("http://www.xenbee.net/schema/2008/02/xbe-msg").c_str(), xml::string("xbemsg:body").c_str()); root->appendChild(bodyElem); /* some example content */ DOMElement* exampleContentElem = doc->createElementNS(xml::string("http://www.example.com/text").c_str(), xml::string("text").c_str()); exampleContentElem->setAttributeNS(xml::string("http://www.w3.org/2000/xmlns/").c_str(), xml::string("xmlns").c_str(), xml::string("http://www.example.com/text").c_str()); bodyElem->appendChild(exampleContentElem); DOMText* exampleContentTxt = doc->createTextNode(xml::string("Hello World!").c_str()); exampleContentElem->appendChild(exampleContentTxt); XSECProvider prov; DSIGSignature *sig; DOMElement *sigNode; sig = prov.newSignature(); sig->setDSIGNSPrefix(xml::string("dsig").c_str()); // Use it to create a blank signature DOM structure from the doc sigNode = sig->createBlankSignature(doc.get(), CANON_C14N_NOC, SIGNATURE_HMAC, HASH_SHA1); // Insert the signature DOM nodes into the doc hdrElem->appendChild(sigNode); // doc->normalizeDocument(); // Create an envelope reference for the text to be signed DSIGReference * ref = sig->createReference(xml::string("").c_str()); ref->appendEnvelopedSignatureTransform(); // Set the HMAC Key to be the string "secret" XSECCryptoKeyHMAC *hmacKey = XSECPlatformUtils::g_cryptoProvider->keyHMAC(); hmacKey->setKey((unsigned char *) "secret", (unsigned int)strlen("secret")); sig->setSigningKey(hmacKey); // Add a KeyInfo element sig->appendKeyName(xml::string("The secret key is \"secret\"").c_str()); // Sign XBE_LOG_DEBUG("signing the document"); sig->sign(); { std::ofstream of("resources/xbe-message-example.xml"); XbeLibUtils::serialize(of, *doc); XBE_LOG_DEBUG("dumped signed document to: " << "resources/xbe-message-example.xml"); } DSIGSignature *sig1 = prov.newSignatureFromDOM(doc.get()); sig1->load(); hmacKey = XSECPlatformUtils::g_cryptoProvider->keyHMAC(); hmacKey->setKey((unsigned char *) "secret", strlen("secret")); sig1->setSigningKey(hmacKey); XBE_LOG_DEBUG("validating the document"); bool isValid(sig1->verify()); char *_errMsgs = XMLString::transcode(sig1->getErrMsgs()); std::string errMsgs(_errMsgs); XMLString::release(&_errMsgs); prov.releaseSignature(sig); prov.releaseSignature(sig1); // Verify CPPUNIT_ASSERT_MESSAGE(errMsgs, isValid); XBE_LOG_DEBUG("the message is valid!"); }
void XMLSecurityLibraryTest::testSignHomePageExample() { XBE_LOG_DEBUG("running the simple signing example from the xml-security homepage..."); xsd::cxx::xml::dom::auto_ptr<xercesc::DOMDocument> doc(create("company", "", "")); DOMElement* rootElem = doc->getDocumentElement(); DOMElement* prodElem = doc->createElement(xml::string("product").c_str()); rootElem->appendChild(prodElem); DOMText* prodDataVal = doc->createTextNode(xml::string("Xerces-C").c_str()); prodElem->appendChild(prodDataVal); DOMElement* catElem = doc->createElement(xml::string("category").c_str()); rootElem->appendChild(catElem); catElem->setAttribute(xml::string("idea").c_str(), xml::string("great").c_str()); DOMText* catDataVal = doc->createTextNode(xml::string("XML Parsing Tools").c_str()); catElem->appendChild(catDataVal); DOMElement* devByElem = doc->createElement(xml::string("developedBy").c_str()); rootElem->appendChild(devByElem); DOMText* devByDataVal = doc->createTextNode(xml::string("Apache Software Foundation").c_str()); devByElem->appendChild(devByDataVal); XSECProvider prov; DSIGSignature *sig; DOMElement *sigNode; sig = prov.newSignature(); sig->setDSIGNSPrefix(xml::string("dsig").c_str()); // Use it to create a blank signature DOM structure from the doc sigNode = sig->createBlankSignature(doc.get(), CANON_C14N_NOC, SIGNATURE_HMAC, HASH_SHA1); // Insert the signature DOM nodes into the doc rootElem->appendChild(sigNode); // Create an envelope reference for the text to be signed DSIGReference * ref = sig->createReference(xml::string("").c_str()); ref->appendEnvelopedSignatureTransform(); // Set the HMAC Key to be the string "secret" XSECCryptoKeyHMAC *hmacKey = XSECPlatformUtils::g_cryptoProvider->keyHMAC(); hmacKey->setKey((unsigned char *) "secret", strlen("secret")); sig->setSigningKey(hmacKey); // Add a KeyInfo element sig->appendKeyName(xml::string("The secret key is \"secret\"").c_str()); // Sign XBE_LOG_DEBUG("signing the document with key \"secret\""); sig->sign(); { std::ofstream of("resources/company-example.xml"); XbeLibUtils::serialize(of, *doc); XBE_LOG_DEBUG("dumped signed document to: " << "resources/company-example.xml"); } DSIGSignature *sig1 = prov.newSignatureFromDOM(doc.get()); sig1->load(); hmacKey = XSECPlatformUtils::g_cryptoProvider->keyHMAC(); hmacKey->setKey((unsigned char *) "secret", strlen("secret")); sig1->setSigningKey(hmacKey); XBE_LOG_DEBUG("verifying the document"); bool isValid(sig1->verify()); char *_errMsgs = XMLString::transcode(sig1->getErrMsgs()); std::string errMsgs(_errMsgs); XMLString::release(&_errMsgs); prov.releaseSignature(sig); prov.releaseSignature(sig1); // Verify CPPUNIT_ASSERT_MESSAGE(errMsgs, isValid); XBE_LOG_DEBUG("document successfully validated!"); }
void verifySignature(DOMDocument* doc, DOMElement* sigNode, const char* cert) { Category& log=Category::getInstance("siterefresh"); // Load the certificate, stripping the first and last lines. string certbuf,line; auto_ptr<OpenSSLCryptoX509> x509(new OpenSSLCryptoX509()); ifstream infile(cert); while (!getline(infile,line).fail()) if (line.find("CERTIFICATE")==string::npos) certbuf+=line + '\n'; x509->loadX509Base64Bin(certbuf.data(),certbuf.length()); // Load the signature. XSECProvider prov; DSIGSignature* sig=NULL; try { sig=prov.newSignatureFromDOM(doc,sigNode); sig->load(); bool valid=false; // Verify the signature coverage. DSIGReferenceList* refs=sig->getReferenceList(); if (sig->getSignatureMethod()==SIGNATURE_RSA && refs && refs->getSize()==1) { DSIGReference* ref=refs->item(0); if (ref) { const XMLCh* URI=ref->getURI(); if (URI==NULL || *URI==0) { DSIGTransformList* tlist=ref->getTransforms(); for (int i=0; tlist && i<tlist->getSize(); i++) { if (tlist->item(i)->getTransformType()==TRANSFORM_ENVELOPED_SIGNATURE) valid=true; else if (tlist->item(i)->getTransformType()!=TRANSFORM_EXC_C14N) { valid=false; break; } } } } } if (!valid) { log.error("detected an invalid signature profile"); throw InvalidCryptoException("detected an invalid signature profile"); } sig->setSigningKey(x509->clonePublicKey()); if (!sig->verify()) { log.error("detected an invalid signature value"); throw InvalidCryptoException("detected an invalid signature value"); } prov.releaseSignature(sig); } catch(...) { if (sig) prov.releaseSignature(sig); throw; } }