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);
    }
}
Exemplo n.º 2
0
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!");
}
Exemplo n.º 5
0
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;
    }
}