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;
}
Exemple #4
0
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());
}
Exemple #6
0
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;
}
Exemple #9
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!");
}
Exemple #13
0
/**
 * 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;
}
Exemple #14
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;
    }
}