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"); }
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); } }
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"); } }
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 evaluate(int argc, char ** argv) { char * filename = NULL; char * outfile = NULL; unsigned char * keyStr = NULL; bool doDecrypt = true; bool errorsOccured = false; bool doDecryptElement = false; bool useInteropResolver = false; bool encryptFileAsData = false; bool parseXMLInput = true; bool doXMLOutput = false; bool isXKMSKey = false; XSECCryptoKey * kek = NULL; XSECCryptoKey * key = NULL; int keyLen = 0; encryptionMethod kekAlg = ENCRYPT_NONE; encryptionMethod keyAlg = ENCRYPT_NONE; DOMDocument *doc; unsigned char keyBuf[24]; XMLFormatTarget *formatTarget ; #if defined(_WIN32) && defined (XSEC_HAVE_WINCAPI) HCRYPTPROV win32DSSCSP = 0; // Crypto Providers HCRYPTPROV win32RSACSP = 0; CryptAcquireContext(&win32DSSCSP, NULL, NULL, PROV_DSS, CRYPT_VERIFYCONTEXT); CryptAcquireContext(&win32RSACSP, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); #endif if (argc < 2) { printUsage(); return 2; } // Run through parameters int paramCount = 1; while (paramCount < argc - 1) { if (_stricmp(argv[paramCount], "--decrypt-element") == 0 || _stricmp(argv[paramCount], "-de") == 0) { paramCount++; doDecrypt = true; doDecryptElement = true; doXMLOutput = true; parseXMLInput = true; } else if (_stricmp(argv[paramCount], "--interop") == 0 || _stricmp(argv[paramCount], "-i") == 0) { // Use the interop key resolver useInteropResolver = true; paramCount++; } else if (_stricmp(argv[paramCount], "--encrypt-file") == 0 || _stricmp(argv[paramCount], "-ef") == 0) { // Use this file as the input doDecrypt = false; encryptFileAsData = true; doXMLOutput = true; parseXMLInput = false; paramCount++; } else if (_stricmp(argv[paramCount], "--encrypt-xml") == 0 || _stricmp(argv[paramCount], "-ex") == 0) { // Us this file as an XML input file doDecrypt = false; encryptFileAsData = false; doXMLOutput = true; parseXMLInput = true; paramCount++; } else if (_stricmp(argv[paramCount], "--out-file") == 0 || _stricmp(argv[paramCount], "-o") == 0) { if (paramCount +2 >= argc) { printUsage(); return 1; } paramCount++; outfile = argv[paramCount]; paramCount++; } else if (_stricmp(argv[paramCount], "--xkms") == 0 || _stricmp(argv[paramCount], "-x") == 0) { paramCount++; isXKMSKey = true; } #if defined (XSEC_HAVE_WINCAPI) else if (_stricmp(argv[paramCount], "--wincapi") == 0 || _stricmp(argv[paramCount], "-w") == 0) { // Use the interop key resolver WinCAPICryptoProvider * cp = new WinCAPICryptoProvider(); XSECPlatformUtils::SetCryptoProvider(cp); paramCount++; } #endif #if defined (XSEC_HAVE_NSS) else if (_stricmp(argv[paramCount], "--nss") == 0 || _stricmp(argv[paramCount], "-n") == 0) { // NSS Crypto Provider NSSCryptoProvider * cp = new NSSCryptoProvider(); XSECPlatformUtils::SetCryptoProvider(cp); paramCount++; } #endif else if (_stricmp(argv[paramCount], "--key") == 0 || _stricmp(argv[paramCount], "-k") == 0) { // Have a key! paramCount++; bool isKEK = false; XSECCryptoSymmetricKey::SymmetricKeyType loadKeyAs = XSECCryptoSymmetricKey::KEY_NONE; if (_stricmp(argv[paramCount], "kek") == 0) { isKEK = true; paramCount++; if (paramCount >= argc) { printUsage(); return 2; } } if (_stricmp(argv[paramCount], "3DES") == 0 || _stricmp(argv[paramCount], "AES128") == 0 || _stricmp(argv[paramCount], "AES192") == 0 || _stricmp(argv[paramCount], "AES256") == 0 || _stricmp(argv[paramCount], "AES128-GCM") == 0 || _stricmp(argv[paramCount], "AES192-GCM") == 0 || _stricmp(argv[paramCount], "AES256-GCM") == 0) { if (paramCount +2 >= argc) { printUsage(); return 2; } switch(argv[paramCount][4]) { case '\0' : keyLen = 24; loadKeyAs = XSECCryptoSymmetricKey::KEY_3DES_192; keyAlg = ENCRYPT_3DES_CBC; break; case '2' : keyLen = 16; loadKeyAs = XSECCryptoSymmetricKey::KEY_AES_128; if (isKEK) { kekAlg = ENCRYPT_KW_AES128; } else if (strlen(argv[paramCount]) == 6) { keyAlg = ENCRYPT_AES128_CBC; } else { keyAlg = ENCRYPT_AES128_GCM; } break; case '9' : keyLen = 24; loadKeyAs = XSECCryptoSymmetricKey::KEY_AES_192; if (isKEK) { kekAlg = ENCRYPT_KW_AES192; } else if (strlen(argv[paramCount]) == 6) { keyAlg = ENCRYPT_AES192_CBC; } else { keyAlg = ENCRYPT_AES192_GCM; } break; case '5' : keyLen = 32; loadKeyAs = XSECCryptoSymmetricKey::KEY_AES_256; if (isKEK) { kekAlg = ENCRYPT_KW_AES256; } else if (strlen(argv[paramCount]) == 6) { keyAlg = ENCRYPT_AES256_CBC; } else { keyAlg = ENCRYPT_AES256_GCM; } break; } paramCount++; unsigned char keyStr[64]; if (strlen(argv[paramCount]) > 64) { cerr << "Key string too long\n"; return 2; } XSECCryptoSymmetricKey * sk = XSECPlatformUtils::g_cryptoProvider->keySymmetric(loadKeyAs); if (isXKMSKey) { unsigned char kbuf[XSEC_MAX_HASH_SIZE]; CalculateXKMSKEK((unsigned char *) argv[paramCount], (int) strlen(argv[paramCount]), kbuf, XSEC_MAX_HASH_SIZE); sk->setKey(kbuf, keyLen); } else { memset(keyStr, 0, 64); strcpy((char *) keyStr, argv[paramCount]); sk->setKey(keyStr, keyLen); } paramCount++; if (isKEK) kek = sk; else key = sk; } #if defined (XSEC_HAVE_OPENSSL) else if (_stricmp(argv[paramCount], "RSA") == 0) { // RSA private key file if (paramCount + 3 >= argc) { printUsage(); return 2; } if (!isKEK) { cerr << "RSA private keys may only be KEKs\n"; return 2; } BIO * bioKey; if ((bioKey = BIO_new(BIO_s_file())) == NULL) { cerr << "Error opening private key file\n\n"; return 1; } if (BIO_read_filename(bioKey, argv[paramCount + 1]) <= 0) { cerr << "Error opening private key file\n\n"; return 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"; return 1; } kek = new OpenSSLCryptoKeyRSA(pkey); kekAlg = ENCRYPT_RSA_15; EVP_PKEY_free(pkey); BIO_free(bioKey); paramCount += 3; } else if (_stricmp(argv[paramCount], "X509") == 0) { // X509 cert used to load an encrypting key if (paramCount + 2 >= argc) { printUsage(); exit (1); } if (!isKEK) { cerr << "X509 private keys may only be KEKs\n"; return 2; } // Load the encrypting 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) { BIO * bio_err; if ((bio_err=BIO_new(BIO_s_file())) != NULL) BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); cerr << "Error loading certificate key\n\n"; ERR_print_errors(bio_err); BIO_free(bio_err); exit (1); } // Now load the key EVP_PKEY *pkey; pkey = X509_get_pubkey(x); if (pkey == NULL || pkey->type != EVP_PKEY_RSA) { cerr << "Error extracting RSA key from certificate" << endl; } kek = new OpenSSLCryptoKeyRSA(pkey); kekAlg = ENCRYPT_RSA_15; // Clean up EVP_PKEY_free (pkey); X509_free(x); BIO_free(bioX509); paramCount += 2; } /* argv[1] = "--x509cert" */ #endif /* XSEC_HAVE_OPENSSL */ else { printUsage(); return 2; } } else { cerr << "Unknown option: " << argv[paramCount] << endl; printUsage(); return 2; } } if (paramCount >= argc) { printUsage(); return 2; } if (outfile != NULL) { formatTarget = new LocalFileFormatTarget(outfile); } else { formatTarget = new StdOutFormatTarget(); } filename = argv[paramCount]; if (parseXMLInput) { XercesDOMParser * parser = new XercesDOMParser; Janitor<XercesDOMParser> j_parser(parser); parser->setDoNamespaces(true); parser->setCreateEntityReferenceNodes(true); // Now parse out file xsecsize_t errorCount = 0; try { parser->parse(filename); 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; return (2); } /* Now that we have the parsed file, get the DOM document and start looking at it */ doc = parser->adoptDocument(); } else { // Create an empty document XMLCh tempStr[100]; XMLString::transcode("Core", tempStr, 99); DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(tempStr); doc = impl->createDocument( 0, // root element namespace URI. MAKE_UNICODE_STRING("ADoc"), // root element name NULL);// DOMDocumentType()); // document type object (DTD). } XSECProvider prov; XENCCipher * cipher = prov.newCipher(doc); if (kek != NULL) cipher->setKEK(kek); if (key != NULL) cipher->setKey(key); try { if (doDecrypt) { if (useInteropResolver == true) { // Map out base path of the file char path[_MAX_PATH]; char baseURI[(_MAX_PATH * 2) + 10]; getcwd(path, _MAX_PATH); strcpy(baseURI, "file:///"); // Ugly and nasty but quick if (filename[0] != '\\' && filename[0] != '/' && filename[1] != ':') { strcat(baseURI, path); strcat(baseURI, "/"); } else if (path[1] == ':') { path[2] = '\0'; strcat(baseURI, path); } strcat(baseURI, filename); // Find any ':' and "\" characters int lastSlash = 0; for (unsigned int i = 8; i < strlen(baseURI); ++i) { if (baseURI[i] == '\\') { lastSlash = i; baseURI[i] = '/'; } else if (baseURI[i] == '/') lastSlash = i; } // The last "\\" must prefix the filename baseURI[lastSlash + 1] = '\0'; XMLCh * uriT = XMLString::transcode(baseURI); XencInteropResolver ires(doc, &(uriT[8])); XSEC_RELEASE_XMLCH(uriT); cipher->setKeyInfoResolver(&ires); } // Find the EncryptedData node DOMNode * n = findXENCNode(doc, "EncryptedData"); if (doDecryptElement) { while (n != NULL) { // decrypt cipher->decryptElement(static_cast<DOMElement *>(n)); // Find the next EncryptedData node n = findXENCNode(doc, "EncryptedData"); } } else { XSECBinTXFMInputStream * bis = cipher->decryptToBinInputStream(static_cast<DOMElement *>(n)); Janitor<XSECBinTXFMInputStream> j_bis(bis); XMLByte buf[1024]; xsecsize_t read = bis->readBytes(buf, 1023); while (read > 0) { formatTarget->writeChars(buf, read, NULL); read = bis->readBytes(buf, 1023); } } } else { XENCEncryptedData *xenc = NULL; // Encrypting if (kek != NULL && key == NULL) { XSECPlatformUtils::g_cryptoProvider->getRandom(keyBuf, 24); XSECCryptoSymmetricKey * k = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_3DES_192); k->setKey(keyBuf, 24); cipher->setKey(k); keyAlg = ENCRYPT_3DES_CBC; keyStr = keyBuf; keyLen = 24; } if (encryptFileAsData) { // Create a BinInputStream #if defined(XSEC_XERCES_REQUIRES_MEMMGR) BinFileInputStream * is = new BinFileInputStream(filename, XMLPlatformUtils::fgMemoryManager); #else BinFileInputStream * is = new BinFileInputStream(filename); #endif xenc = cipher->encryptBinInputStream(is, keyAlg); // Replace the document element DOMElement * elt = doc->getDocumentElement(); doc->replaceChild(xenc->getElement(), elt); elt->release(); } else { // Document encryption cipher->encryptElement(doc->getDocumentElement(), keyAlg); } // Do we encrypt a created key? if (kek != NULL && xenc != NULL) { XENCEncryptedKey *xkey = cipher->encryptKey(keyStr, keyLen, kekAlg); // Add to the EncryptedData xenc->appendEncryptedKey(xkey); } } if (doXMLOutput) { // Output the result XMLCh core[] = { XERCES_CPP_NAMESPACE_QUALIFIER chLatin_C, XERCES_CPP_NAMESPACE_QUALIFIER chLatin_o, XERCES_CPP_NAMESPACE_QUALIFIER chLatin_r, XERCES_CPP_NAMESPACE_QUALIFIER chLatin_e, XERCES_CPP_NAMESPACE_QUALIFIER chNull }; DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(core); #if defined (XSEC_XERCES_DOMLSSERIALIZER) // DOM L3 version as per Xerces 3.0 API DOMLSSerializer *theSerializer = ((DOMImplementationLS*)impl)->createLSSerializer(); Janitor<DOMLSSerializer> j_theSerializer(theSerializer); // 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); #else DOMWriter *theSerializer = ((DOMImplementationLS*)impl)->createDOMWriter(); Janitor<DOMWriter> j_theSerializer(theSerializer); theSerializer->setEncoding(MAKE_UNICODE_STRING("UTF-8")); if (theSerializer->canSetFeature(XMLUni::fgDOMWRTFormatPrettyPrint, false)) theSerializer->setFeature(XMLUni::fgDOMWRTFormatPrettyPrint, false); theSerializer->writeNode(formatTarget, *doc); #endif cout << endl; } } catch (XSECException &e) { char * msg = XMLString::transcode(e.getMsg()); cerr << "An error occured during encryption/decryption operation\n Message: " << msg << endl; XSEC_RELEASE_XMLCH(msg); errorsOccured = true; if (formatTarget != NULL) delete formatTarget; doc->release(); return 2; } catch (XSECCryptoException &e) { cerr << "An error occured during encryption/decryption operation\n Message: " << e.getMsg() << endl; errorsOccured = true; if (formatTarget != NULL) delete formatTarget; doc->release(); #if defined (XSEC_HAVE_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); ERR_print_errors(bio_err); #endif return 2; } if (formatTarget != NULL) delete formatTarget; doc->release(); return 0; }
XKMSRSAKeyPair * XKMSRegisterResultImpl::getRSAKeyPair(const char * passPhrase) { // Already done? if (mp_RSAKeyPair != NULL) return mp_RSAKeyPair; // Nope - can we do it? if (mp_privateKeyElement == NULL) return NULL; // Yep! Load the key unsigned char kbuf[XSEC_MAX_HASH_SIZE]; unsigned int len = CalculateXKMSKEK((unsigned char *) passPhrase, (int) strlen(passPhrase), kbuf, XSEC_MAX_HASH_SIZE); if (len == 0) { throw XSECException(XSECException::XKMSError, "XKMSRegisterResult::getRSAKeyPair - error deriving KEK"); } XSECProvider prov; XENCCipher * cipher = prov.newCipher(m_msg.mp_env->getParentDocument()); // Find the encrypted info DOMNode * n = findXENCNode(mp_privateKeyElement, "EncryptedData"); // Load into the Cipher class XENCEncryptedData * xed = cipher->loadEncryptedData((DOMElement *) n); if (xed == NULL) { throw XSECException(XSECException::XKMSError, "XKMSRegisterResult::getRSAKeyPair - error loading encrypted data"); } // Setup the appropriate key if (xed->getEncryptionMethod() == NULL) { throw XSECException(XSECException::XKMSError, "XKMSRegisterResult::getRSAKeyPair - no <EncryptionMethod> in EncryptedData"); } // Now find if we can get an algorithm for this URI XSECAlgorithmHandler *handler; handler = XSECPlatformUtils::g_algorithmMapper->mapURIToHandler( xed->getEncryptionMethod()->getAlgorithm()); if (handler == NULL) { throw XSECException(XSECException::XKMSError, "XKMSRegisterResult::getRSAKeyPair - unable to handle algorithm in EncryptedData"); } XSECCryptoKey * sk = handler->createKeyForURI( xed->getEncryptionMethod()->getAlgorithm(), (XMLByte *) kbuf, len); memset(kbuf, 0, XSEC_MAX_HASH_SIZE); cipher->setKey(sk); cipher->decryptElement(); // WooHoo - if we get this far things are looking good! DOMElement * kp = findFirstElementChild(mp_privateKeyElement); if (kp == NULL || !strEquals(getXKMSLocalName(kp), XKMSConstants::s_tagRSAKeyPair)) { throw XSECException(XSECException::XKMSError, "XKMSRegisterResult::getRSAKeyPair - private key did not decrypt to RSAKeyPair"); } XSECnew(mp_RSAKeyPair, XKMSRSAKeyPairImpl(m_msg.mp_env, kp)); mp_RSAKeyPair->load(); return mp_RSAKeyPair; }
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; }
int main (int argc, char **argv) { try { XMLPlatformUtils::Initialize(); #ifndef XSEC_NO_XALAN XalanTransformer::initialize(); #endif XSECPlatformUtils::Initialise(); } catch (const XMLException &e) { cerr << "Error during initialisation of Xerces" << endl; cerr << "Error Message = : " << e.getMessage() << endl; } // Create a blank Document DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(MAKE_UNICODE_STRING("Core")); // Create a letter DOMDocument *doc = createLetter(impl); try { /* Create the cipher object that we need */ XSECProvider prov; XENCCipher *cipher; cipher = prov.newCipher(doc); /* Now generate a random key that we can use to encrypt the element * * First check the status of the random generation in OpenSSL */ if (RAND_status() != 1) { cerr << "OpenSSL random generation not properly initialised" << endl; exit(1); } unsigned char keyBuf[24]; if (RAND_bytes(keyBuf, 24) == 0) { cerr << "Error obtaining 24 bytes of random from OpenSSL" << endl; exit(1); } /* Wrap this in a Symmetric 3DES key */ OpenSSLCryptoSymmetricKey * key = new OpenSSLCryptoSymmetricKey(XSECCryptoSymmetricKey::KEY_3DES_192); key->setKey(keyBuf, 24); cipher->setKey(key); /* Encrypt the element that needs to be hidden */ cipher->encryptElement(g_toEncrypt, ENCRYPT_3DES_CBC); /* Now lets create an EncryptedKey element to hold the generated key */ /* First lets load the public key in the certificate */ OpenSSLCryptoX509 * x509 = new OpenSSLCryptoX509(); x509->loadX509Base64Bin(cert, (unsigned int) strlen(cert)); /* Now set the Key Encrypting Key (NOTE: Not the normal key) */ cipher->setKEK(x509->clonePublicKey()); /* Now do the encrypt, using RSA with PKCS 1.5 padding */ XENCEncryptedKey * encryptedKey = cipher->encryptKey(keyBuf, 24, ENCRYPT_RSA_15); /* * Add the encrypted Key to the previously created EncryptedData, which * we first retrieve from the cipher object. This will automatically create * the appropriate <KeyInfo> element within the EncryptedData */ XENCEncryptedData * encryptedData = cipher->getEncryptedData(); encryptedData->appendEncryptedKey(encryptedKey); } catch (XSECException &e) { char * msg = XMLString::transcode(e.getMsg()); cerr << "An error occurred during an encryption operation\n Message: " << msg << endl; exit(1); } /* Output */ docSetup(doc); cout << doc; 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; }
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; } }