void XKMSMessageFactoryImpl::copyRequestToResult(XKMSRequestAbstractType * req, XKMSResultType * res) { /* Set the requestId */ res->setRequestId(req->getId()); /* Copy any Opaque Data */ int i; int sz = req->getOpaqueClientDataSize(); for (i = 0; i < sz; ++i) { res->appendOpaqueClientDataItem(req->getOpaqueClientDataItemStr(i)); } /* Set RequestSignatureValue data if necessary */ sz = req->getResponseMechanismSize(); for (i = 0; i < sz; ++i) { if (strEquals(req->getResponseMechanismItemStr(i), XKMSConstants::s_tagRequestSignatureValue)) { DSIGSignature *s = req->getSignature(); if (s != NULL && res->getResultMinor() != XKMSResultType::NoAuthentication) { res->setRequestSignatureValue(s->getSignatureValue()); } break; } } }
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); } }
void XMLSecurityLibraryTest::testParseValidateValidSignature() { std::string filename("resources/signed-message-checked-valid.xml"); XBE_LOG_DEBUG("parsing valid message: " << filename); std::ifstream ifs(filename.c_str()); xsd::cxx::xml::dom::auto_ptr<xercesc::DOMDocument> doc(XbeLibUtils::parse(ifs, filename, false)); XSECProvider prov; DSIGSignature *sig = prov.newSignatureFromDOM(doc.get()); XBE_LOG_DEBUG("loading signature"); sig->load(); XSECCryptoKeyHMAC *hmacKey = XSECPlatformUtils::g_cryptoProvider->keyHMAC(); hmacKey->setKey((unsigned char *) "secret", (unsigned int)strlen("secret")); sig->setSigningKey(hmacKey); XBE_LOG_DEBUG("verifying signature"); bool isValid(sig->verify()); if (!isValid) { char *_errMsgs = XMLString::transcode(sig->getErrMsgs()); std::string errMsgs(_errMsgs); XMLString::release(&_errMsgs); CPPUNIT_ASSERT_MESSAGE(errMsgs, isValid); } else { CPPUNIT_ASSERT(isValid); } XBE_LOG_DEBUG("message is valid"); }
static bool SAMLCheckSignature(DOMDocument *doc, vector<string> &certs) { DOMElement *sigElem = SAMLFindChildByName(doc->getDocumentElement(), "ds:Signature"); if (NULL == sigElem) { Warning("%s: No top level signature found.\n", __FUNCTION__); return false; } XSECEnv secEnv(doc); auto_ptr<DSIGKeyInfoX509> keyInfo = SAMLFindKey(secEnv, sigElem); if (keyInfo.get() == NULL) { Warning("%s: No X509 data found as part of the signature.\n", __FUNCTION__); return false; } if (keyInfo->getCertificateListSize() == 0) { Warning("%s: No X509 certificates found in the signature\n", __FUNCTION__); return false; } const XSECCryptoX509 *x509 = keyInfo->getCertificateCryptoItem(0); ASSERT(NULL != x509); XSECProvider prov; DSIGSignature *sig = prov.newSignatureFromDOM(doc, sigElem); sig->load(); sig->setSigningKey(x509->clonePublicKey()); if (!SAMLCheckReference(doc, sig)) { return false; } if (!sig->verify()) { Warning("%s: Signature check failed: %s.\n", __FUNCTION__, SAMLStringWrapper(sig->getErrMsgs()).c_str()); return false; } for (int i = 0; i < keyInfo->getCertificateListSize(); i++) { const XSECCryptoX509 *cert = keyInfo->getCertificateCryptoItem(i); certs.push_back(string(cert->getDEREncodingSB().rawCharBuffer())); } return true; }
void TSL::validate(const std::vector<X509Cert> &certs) { if(!tsl) THROW("Failed to parse XML"); X509Cert signingCert; if(tsl->signature().present() && tsl->signature()->keyInfo().present() && !tsl->signature()->keyInfo()->x509Data().empty() && !tsl->signature()->keyInfo()->x509Data().front().x509Certificate().empty()) { const Base64Binary &base64 = tsl->signature()->keyInfo()->x509Data().front().x509Certificate().front(); signingCert = X509Cert((const unsigned char*)base64.data(), base64.capacity()); } if(find(certs.begin(), certs.end(), signingCert) == certs.end()) THROW("TSL Signature is signed with untrusted certificate"); try { XSECProvider prov; DSIGSignature *sig = prov.newSignatureFromDOM(tsl->_node()->getOwnerDocument()); //sig->setKeyInfoResolver(new XSECKeyInfoResolverDefault); sig->setSigningKey(OpenSSLCryptoX509(signingCert.handle()).clonePublicKey()); //sig->registerIdAttributeName(MAKE_UNICODE_STRING("ID")); sig->load(); if(!sig->verify()) { string msg = xsd::cxx::xml::transcode<char>(sig->getErrMsgs()); THROW("TLS Signature is invalid: %s", msg.c_str()); } } catch(XSECException &e) { string msg = xsd::cxx::xml::transcode<char>(e.getMsg()); THROW("TSL Signature is invalid: %s", msg.c_str()); } catch(const Exception &) { throw; } catch(...) { THROW("TSL Signature is invalid"); } }
DSIGSignature * XKMSAuthenticationImpl::addKeyBindingAuthenticationSignature( canonicalizationMethod cm, signatureMethod sm, hashMethod hm) { if (mp_keyBindingId == NULL) { throw XSECException(XSECException::XKMSError, "XKMSAuthenticationImpl::addKeyBindingAuthenticationSignature - called prior to key infos being added"); } DSIGSignature * ret = m_prov.newSignature(); DOMElement * elt = ret->createBlankSignature(mp_env->getParentDocument(), cm, sm, hm); /* Create the enveloping reference */ safeBuffer sb; sb.sbXMLChIn(DSIGConstants::s_unicodeStrEmpty); sb.sbXMLChAppendCh(chPound); sb.sbXMLChCat(mp_keyBindingId); DSIGReference *ref = ret->createReference(sb.rawXMLChBuffer()); ref->appendCanonicalizationTransform(CANON_C14NE_COM); /* Embed the signature in the document inside a KeyBindingAuthentication element */ safeBuffer str; DOMDocument *doc = mp_env->getParentDocument(); const XMLCh * prefix = mp_env->getXKMSNSPrefix(); makeQName(str, prefix, XKMSConstants::s_tagKeyBindingAuthentication); DOMElement * t = doc->createElementNS(XKMSConstants::s_unicodeStrURIXKMS, str.rawXMLChBuffer()); mp_env->doPrettyPrint(t); t->appendChild(elt); mp_env->doPrettyPrint(t); mp_authenticationElement->appendChild(t); mp_env->doPrettyPrint(mp_authenticationElement); return ret; }
void XMLSecurityTest::testSign() { xbemsg::header_t hdr("tests.xbe.foo.bar", "tests.xbe.foo.bar"); xbemsg::body_t body; body.any().push_back(body.dom_document().createElementNS(xml::string("http://www.xenbee.net/schema/2008/02/pingpong").c_str(), xml::string("Ping").c_str())); xbemsg::message_t msg(hdr,body); // serialize to DOMDocument xml_schema::dom::auto_ptr< ::xercesc::DOMDocument > doc = xbemsg::message(msg, XbeLibUtils::namespace_infomap()); ::xercesc::DOMElement *rootElem = doc->getDocumentElement(); XSECProvider prov; DSIGSignature *sig; xercesc::DOMElement *sigNode; sig = prov.newSignature(); sig->setDSIGNSPrefix(xml::string("dsig").c_str()); // sig->setECNSPrefix( NULL ); // sig->setXPFNSPrefix(NULL); // sig->setPrettyPrint(false); // Use it to create a blank signature DOM structure from the doc sigNode = sig->createBlankSignature(doc.get(), CANON_C14NE_NOC, SIGNATURE_HMAC, HASH_SHA1); // Insert the signature element at the right place within the document // find the header DOM node DOMNode *hdrNode = rootElem->getFirstChild(); CPPUNIT_ASSERT(hdrNode != 0); char *tmpNodeName = XMLString::transcode(hdrNode->getLocalName()); std::string nodeName(tmpNodeName); XMLString::release(&tmpNodeName); CPPUNIT_ASSERT_EQUAL(nodeName, std::string("header")); hdrNode->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" OpenSSLCryptoProvider cryptoProvider; XSECCryptoKeyHMAC *hmacKey = cryptoProvider.keyHMAC(); hmacKey->setKey((unsigned char *) "secret", strlen("secret")); sig->setSigningKey(hmacKey); // Add a KeyInfo element sig->appendKeyName(MAKE_UNICODE_STRING("The secret key is \"secret\"")); // Sign sig->sign(); xbemsg::message_t signed_msg(*rootElem); std::ostringstream oss; xbemsg::message(oss, signed_msg, XbeLibUtils::namespace_infomap()); // write to an xml file // { // std::ofstream ofs("sig-test-2.xml"); // ofs << oss.str(); // } XBE_LOG_DEBUG(oss.str()); // std::string expected_digest("6gEokD/uXFJHZdGdup83UEJAL7U=\n"); // std::string expected_sigval("t9LLbEU8GHtWrrx+qWTWWujTGEY=\n"); // CPPUNIT_ASSERT_EQUAL(expected_digest, // signed_msg.header().Signature().get().SignedInfo().Reference().begin()->DigestValue().encode()); // CPPUNIT_ASSERT_EQUAL(expected_sigval, // signed_msg.header().Signature().get().SignatureValue().encode()); }
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::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 XMLSecurityLibraryTest::testValidateXbeMessage() { XBE_LOG_DEBUG("**** Test: testValidateXbeMessage ****"); xbemsg::header_t hdr("test.xbe.to", "tests.xbe.from"); xbemsg::body_t body; body.any().push_back(body.dom_document().createElementNS(xml::string("http://www.xenbee.net/schema/2008/02/xbetest").c_str(), xml::string("xbetest:Ping").c_str())); xbemsg::message_t msg(hdr, body); // create DOMDocument ::xml_schema::dom::auto_ptr< ::xercesc::DOMDocument > doc(xbemsg::message(msg, XbeLibUtils::namespace_infomap(), 0)); // sign the message 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 doc->getDocumentElement()->appendChild(sigNode); 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::string filename("resources/signed-xbe-msg.xml"); std::ofstream out(filename.c_str()); XbeLibUtils::serialize(out, *doc); // load the document from file XBE_LOG_DEBUG("parsing dumped message: " << filename); std::ifstream ifs(filename.c_str()); xsd::cxx::xml::dom::auto_ptr<xercesc::DOMDocument> doc2(XbeLibUtils::parse(ifs, "", false)); DSIGSignature *sig2 = prov.newSignatureFromDOM(doc2.get()); XBE_LOG_DEBUG("loading signature"); sig2->load(); XSECCryptoKeyHMAC *hmacKey2 = XSECPlatformUtils::g_cryptoProvider->keyHMAC(); hmacKey2->setKey((unsigned char *) "secret", strlen("secret")); sig2->setSigningKey(hmacKey2); XBE_LOG_DEBUG("verifying signature"); bool isValid(sig2->verify()); CPPUNIT_ASSERT(isValid); XBE_LOG_DEBUG("message is valid"); }
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!"); }
/** * Check if signature is valid according to BDoc-BES format. Performs * any off-line checks that prove mathematical correctness. * However, there is no warranty against if the signature has expired. On-line * validation should be performed to check for signature expiration. * * @throws SignatureException containing details on what's wrong in this signature. */ void SignatureBES::validate() const { // A "master" exception containing all problems (causes) with this signature. // It'll be only thrown in case we have a reason (cause). Exception exception(__FILE__, __LINE__, "Signature validation"); if(!Exception::hasWarningIgnore(Exception::SignatureDigestWeak) && (signatureMethod() == URI_RSA_SHA1 || signatureMethod() == URI_ECDSA_SHA1)) { Exception e(EXCEPTION_PARAMS("Signature digest weak")); e.setCode(Exception::SignatureDigestWeak); exception.addCause(e); } if(signerRoles().size() > 1) EXCEPTION_ADD(exception, "More than 1 signer role is not supported"); if(profile().find(BDoc::ASIC_TM_PROFILE) != string::npos) { if(SPUri().empty()) EXCEPTION_ADD(exception, "Signature SPUri is missing"); map<string,Policy>::const_iterator p = policylist.find(policy()); if(p != policylist.end()) { const SignedSignaturePropertiesType::SignaturePolicyIdentifierOptional &identifier = getSignedSignatureProperties().signaturePolicyIdentifier(); if(identifier.present()) { const SignaturePolicyIdentifierType::SignaturePolicyIdOptional &id = identifier->signaturePolicyId(); if(id.present()) { #if 0 //Disabled IB-3684 const DigestAlgAndValueType &hash = id->sigPolicyHash(); vector<unsigned char> digest(hash.digestValue().begin(), hash.digestValue().end()); bool valid = false; if(hash.digestMethod().algorithm() == URI_SHA1) valid = digest == p->second.SHA1; else if(hash.digestMethod().algorithm() == URI_SHA224) valid = digest == p->second.SHA224; else if(hash.digestMethod().algorithm() == URI_SHA256) valid = digest == p->second.SHA256; else if(hash.digestMethod().algorithm() == URI_SHA384) valid = digest == p->second.SHA384; else if(hash.digestMethod().algorithm() == URI_SHA512) valid = digest == p->second.SHA512; else EXCEPTION_ADD(exception, "Signature policy unknwon digest method"); if(!valid) EXCEPTION_ADD(exception, "Signature policy digest does not match"); #endif } else EXCEPTION_ADD(exception, "Signature policy digest is missing"); } else EXCEPTION_ADD(exception, "Signature policy digest is missing"); } else EXCEPTION_ADD(exception, "Signature policy does not match BDOC 2.1 policy"); } try { unique_ptr<XercesDOMParser> parser(new XercesDOMParser()); parser->setDoNamespaces(true); parser->setValidationScheme(XercesDOMParser::Val_Always); parser->setDoSchema(true); parser->setCreateEntityReferenceNodes(false); stringstream ofs; saveToXml(ofs); string data = ofs.str(); MemBufInputSource source((XMLByte*)data.c_str(), data.size(), "temp"); parser->parse(source); XSECProvider prov; DSIGSignature *sig = prov.newSignatureFromDOM(parser->getDocument()); unique_ptr<URIResolver> uriresolver(new URIResolver(bdoc)); unique_ptr<XSECKeyInfoResolverDefault> keyresolver(new XSECKeyInfoResolverDefault); sig->setURIResolver(uriresolver.get()); sig->setKeyInfoResolver(keyresolver.get()); sig->load(); safeBuffer m_errStr; m_errStr.sbXMLChIn(DSIGConstants::s_unicodeStrEmpty); if(!DSIGReference::verifyReferenceList(sig->getReferenceList(), m_errStr)) //if(!sig->verify()) does not support URI_ID_C14N11_NOC canonicalization { //string s = xsd::cxx::xml::transcode<char>(sig->getErrMsgs()); string s = xsd::cxx::xml::transcode<char>(m_errStr.rawXMLChBuffer()); EXCEPTION_ADD(exception, "Failed to validate signature: %s", s.c_str()); } } catch(const Parsing &e) { stringstream s; s << e; EXCEPTION_ADD(exception, "Failed to validate signature: %s", s.str().c_str()); } catch(XSECException &e) { string s = xsd::cxx::xml::transcode<char>(e.getMsg()); EXCEPTION_ADD(exception, "Failed to validate signature: %s", s.c_str()); } catch(XMLException &e) { string s = xsd::cxx::xml::transcode<char>(e.getMessage()); EXCEPTION_ADD(exception, "Failed to validate signature: %s", s.c_str()); } catch(...) { EXCEPTION_ADD(exception, "Failed to validate signature"); } const SignedPropertiesType &sp = qualifyingProperties().signedProperties().get(); map<string,string> mimeinfo; if(sp.signedDataObjectProperties().present()) { for(const DataObjectFormatType &data: sp.signedDataObjectProperties()->dataObjectFormat()) { if(data.mimeType().present()) mimeinfo.insert(pair<string,string>(data.objectReference(), data.mimeType().get())); } } else { EXCEPTION_ADD(exception, "DataObjectFormat element is missing"); } map<string,string> signatureref; string signedPropertiesId; bool signedInfoFound = false, weak = false; if(sp.id().present()) signedPropertiesId = "#" + sp.id().get(); for(const ReferenceType &ref: signature->signedInfo().reference()) { if(ref.digestMethod().algorithm() == URI_SHA1 || ref.digestMethod().algorithm() == URI_SHA224 ) weak = true; if(ref.uRI().present() && ref.uRI().get() != signedPropertiesId) { string uri = File::fromUriPath(ref.uRI().get()); if(strncmp(uri.c_str(), "/", 1) == 0) uri.erase(0, 1); signatureref.insert({ uri, mimeinfo["#"+ref.id().get()] }); } if(ref.uRI().present() && ref.uRI().get() == signedPropertiesId) signedInfoFound = true; }; if(!signedInfoFound) EXCEPTION_ADD(exception, "SignedProperties not found"); if(!Exception::hasWarningIgnore(Exception::ReferenceDigestWeak) && weak) { Exception e(EXCEPTION_PARAMS("Reference digest weak")); e.setCode(Exception::ReferenceDigestWeak); exception.addCause(e); } for(const DataFile *file: bdoc->dataFiles()) { map<string,string>::const_iterator i = signatureref.find(file->fileName()); if(i != signatureref.end()) { if(i->second != file->mediaType()) EXCEPTION_ADD(exception, "Manifest datafile '%s' mime '%s' does not match signature mime '%s'", file->fileName().c_str(), file->mediaType().c_str(), i->second.c_str()); signatureref.erase(i); } else EXCEPTION_ADD(exception, "Manifest datafile not listed in signature references %s", file->fileName().c_str()); }; if(bdoc->dataFiles().empty()) EXCEPTION_ADD(exception, "No DataFiles signed"); if(!signatureref.empty()) EXCEPTION_ADD(exception, "Manifest references and signature references do not match"); try { checkKeyInfo(); } catch(const Exception& e) { exception.addCause(e); } try { checkSignatureValue(); } catch(const Exception& e) { exception.addCause(e); } try { checkSigningCertificate(); } catch(const Exception& e) { exception.addCause(e); } if(!exception.causes().empty()) throw exception; }