From: Scott Cantor Date: Sun, 11 Jun 2006 19:25:17 +0000 (+0000) Subject: New KeyResolver/Validator/Encrypter/Decrypter classes. X-Git-Tag: 1.0-alpha1~230 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=shibboleth%2Fcpp-xmltooling.git;a=commitdiff_plain;h=c390bc9abfd5ef673577b2da3104c3f36fb1c18d New KeyResolver/Validator/Encrypter/Decrypter classes. --- diff --git a/xmltooling/Makefile.am b/xmltooling/Makefile.am index 35c6017..64543ae 100644 --- a/xmltooling/Makefile.am +++ b/xmltooling/Makefile.am @@ -41,6 +41,7 @@ libxmltoolinginclude_HEADERS = \ XMLToolingConfig.h encinclude_HEADERS = \ + encryption/Decrypter.h \ encryption/Encrypter.h \ encryption/Encryption.h @@ -55,6 +56,7 @@ ioinclude_HEADERS = \ siginclude_HEADERS = \ signature/ContentReference.h \ signature/KeyInfo.h \ + signature/KeyResolver.h \ signature/Signature.h \ signature/SignatureValidator.h @@ -76,6 +78,7 @@ noinst_HEADERS = \ if BUILD_XMLSEC xmlsec_sources = \ + encryption/impl/Decrypter.cpp \ encryption/impl/Encrypter.cpp \ signature/impl/SignatureValidator.cpp \ signature/impl/XMLSecSignatureImpl.cpp diff --git a/xmltooling/encryption/Decrypter.h b/xmltooling/encryption/Decrypter.h new file mode 100644 index 0000000..19a245b --- /dev/null +++ b/xmltooling/encryption/Decrypter.h @@ -0,0 +1,111 @@ +/* + * Copyright 2001-2006 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file Encrypter.h + * + * Methods for encrypting XMLObjects and other data. + */ + +#if !defined(__xmltooling_decrypter_h__) && !defined(XMLTOOLING_NO_XMLSEC) +#define __xmltooling_decrypter_h__ + +#include +#include + +#include +#include + +namespace xmlencryption { + + /** + * Wrapper API for XML Decryption functionality. + */ + class XMLTOOL_API Decrypter + { + public: + /** + * Constructor. + * Resolvers will be deleted when Decrypter is. + * + * @param KEKresolver resolves key decryption key based on KeyInfo information + * @param resolver resolves data decryption key based on KeyInfo information + */ + Decrypter(xmlsignature::KeyResolver* KEKresolver=NULL, xmlsignature::KeyResolver* resolver=NULL) + : m_cipher(NULL), m_resolver(resolver), m_KEKresolver(KEKresolver) { + } + + ~Decrypter(); + + /** + * Replace the current KeyResolver interface, if any, with a new one. + * + * @param resolver the KeyResolver to attach + */ + void setKeyResolver(xmlsignature::KeyResolver* resolver) { + delete m_resolver; + m_resolver=resolver; + } + + /** + * Replace the current key encryption KeyResolver interface, if any, with a new one. + * + * @param resolver the KeyResolver to attach + */ + void setKEKResolver(xmlsignature::KeyResolver* resolver) { + delete m_KEKresolver; + m_KEKresolver=resolver; + } + + /** + * Decrypts the supplied information and returns the resulting as a DOM + * fragment owned by the document associated with the marshalled EncryptedData + * object. + * + * Note that the DOM nodes will be invalidated once that document + * is released. The caller should therefore process the DOM fragment as + * required and drop all references to it before that happens. The usual + * approach should be to unmarshall the DOM and then release it, or the + * DOM can also be imported into a separately owned document. + * + * @param encryptedData the encrypted data to decrypt + * @return the decrypted DOM fragment + */ + DOMDocumentFragment* decryptData(EncryptedData* encryptedData); + + /** + * Decrypts the supplied information and returns the resulting key. + * The caller is responsible for deleting the key. The algorithm of the + * key must be supplied by the caller based on knowledge of the associated + * EncryptedData information. + * + * @param encryptedKey the encrypted/wrapped key to decrypt + * @param algorithm the algorithm associated with the decrypted key + * @return the decrypted key + */ + XSECCryptoKey* decryptKey(EncryptedKey* encryptedKey, const XMLCh* algorithm); + + private: + XENCCipher* m_cipher; + xmlsignature::KeyResolver* m_resolver; + xmlsignature::KeyResolver* m_KEKresolver; + }; + + DECL_XMLTOOLING_EXCEPTION(DecryptionException,XMLTOOL_EXCEPTIONAPI(XMLTOOL_API),xmlencryption,xmltooling::XMLToolingException,Exceptions in decryption processing); + +}; + +#endif /* __xmltooling_decrypter_h__ */ diff --git a/xmltooling/encryption/Encrypter.h b/xmltooling/encryption/Encrypter.h index bb00268..63d2be7 100644 --- a/xmltooling/encryption/Encrypter.h +++ b/xmltooling/encryption/Encrypter.h @@ -129,55 +129,61 @@ namespace xmlencryption { /** * Encrypts the supplied element and returns the resulting object. - * The returned object will be unmarshalled around a DOM tree created - * using the encrypted element's owning document. * * If an encryption algorithm is set, but no key, a random key will be - * generated iff keParams is non-NULL and the algorithm is known. + * generated iff kencParams is non-NULL and the algorithm is known. * * If key encryption parameters are supplied, then the encryption key * is wrapped and the result placed into an EncryptedKey object in the * KeyInfo of the returned EncryptedData. * - * @param element the DOM element to encrypt - * @param keParams key encryption settings, or NULL + * @param element the DOM element to encrypt + * @param encParams primary encryption settings + * @param kencParams key encryption settings, or NULL */ EncryptedData* encryptElement(DOMElement* element, EncryptionParams& encParams, KeyEncryptionParams* kencParams=NULL); /** * Encrypts the supplied element's children and returns the resulting object. - * The returned object will be unmarshalled around a DOM tree created - * using the encrypted content's owning document. * * If an encryption algorithm is set, but no key, a random key will be - * generated iff keParams is non-NULL and the algorithm is known. + * generated iff kencParams is non-NULL and the algorithm is known. * If key encryption parameters are supplied, then the encryption key * is wrapped and the result placed into an EncryptedKey object in the * KeyInfo of the returned EncryptedData. * - * @param element parent element of children to encrypt - * @param keParams key encryption settings, or NULL + * @param element parent element of children to encrypt + * @param encParams primary encryption settings + * @param kencParams key encryption settings, or NULL */ EncryptedData* encryptElementContent(DOMElement* element, EncryptionParams& encParams, KeyEncryptionParams* kencParams=NULL); /** * Encrypts the supplied input stream and returns the resulting object. - * The returned object will be unmarshalled around a DOM tree created - * using the encrypted element's owning document. * * If an encryption algorithm is set, but no key, a random key will be - * generated iff keParams is non-NULL and the algorithm is known. + * generated iff kencParams is non-NULL and the algorithm is known. * If key encryption parameters are supplied, then the encryption key * is wrapped and the result placed into an EncryptedKey object in the * KeyInfo of the returned EncryptedData. * - * @param input the stream to encrypt - * @param keParams key encryption settings, or NULL + * @param input the stream to encrypt + * @param encParams primary encryption settings + * @param kencParams key encryption settings, or NULL */ EncryptedData* encryptStream(std::istream& input, EncryptionParams& encParams, KeyEncryptionParams* kencParams=NULL); + /** + * Encrypts the supplied key and returns the resulting object. + * + * @param keyBuffer raw key material to encrypt + * @param keyBufferSize size in bytes of raw key material + * @param kencParams key encryption settings + */ + EncryptedKey* encryptKey(const unsigned char* keyBuffer, unsigned int keyBufferSize, KeyEncryptionParams& kencParams); + private: void checkParams(EncryptionParams& encParams, KeyEncryptionParams* kencParams); EncryptedData* decorateAndUnmarshall(EncryptionParams& encParams, KeyEncryptionParams* kencParams); diff --git a/xmltooling/encryption/impl/Decrypter.cpp b/xmltooling/encryption/impl/Decrypter.cpp new file mode 100644 index 0000000..0788761 --- /dev/null +++ b/xmltooling/encryption/impl/Decrypter.cpp @@ -0,0 +1,151 @@ +/* + * Copyright 2001-2006 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Encrypter.cpp + * + * Methods for encrypting XMLObjects and other data. + */ + +#include "internal.h" +#include "encryption/Decrypter.h" + +#include +#include +#include +#include +#include +#include +#include + +using namespace xmlencryption; +using namespace xmlsignature; +using namespace xmltooling; +using namespace std; + +Decrypter::~Decrypter() +{ + XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseCipher(m_cipher); + delete m_resolver; + delete m_KEKresolver; +} + +DOMDocumentFragment* Decrypter::decryptData(EncryptedData* encryptedData) +{ + if (encryptedData->getDOM()==NULL) + throw DecryptionException("The object must be marshalled before decryption."); + + // We can reuse the cipher object if the document hasn't changed. + + if (m_cipher && m_cipher->getDocument()!=encryptedData->getDOM()->getOwnerDocument()) { + XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseCipher(m_cipher); + m_cipher=NULL; + } + + if (!m_cipher) + m_cipher=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newCipher(encryptedData->getDOM()->getOwnerDocument()); + + try { + // Resolve decryption key. + XSECCryptoKey* key=NULL; + if (m_resolver) + key=m_resolver->resolveKey(encryptedData->getKeyInfo()); + if (!key) { + // See if there's an encrypted key present. We'll need the algorithm... + const XMLCh* algorithm= + encryptedData->getEncryptionMethod() ? encryptedData->getEncryptionMethod()->getAlgorithm() : NULL; + if (!algorithm) + throw DecryptionException("No EncryptionMethod/@Algorithm set, key decryption cannot proceed."); + + if (encryptedData->getKeyInfo()) { + const vector& others=const_cast(encryptedData->getKeyInfo())->getOthers(); + for (vector::const_iterator i=others.begin(); i!=others.end(); i++) { + EncryptedKey* encKey=dynamic_cast(*i); + if (encKey) { + try { + key=decryptKey(encKey, algorithm); + } + catch (DecryptionException& e) { + log4cpp::Category::getInstance(XMLTOOLING_LOGCAT".Decrypter").warn(e.what()); + } + } + } + } + + if (!key) + throw DecryptionException("Unable to resolve a decryption key."); + } + + m_cipher->setKey(key); + DOMNode* ret=m_cipher->decryptElementDetached(encryptedData->getDOM()); + if (ret->getNodeType()!=DOMNode::DOCUMENT_FRAGMENT_NODE) { + ret->release(); + throw DecryptionException("Decryption operation did not result in DocumentFragment."); + } + return static_cast(ret); + } + catch(XSECException& e) { + auto_ptr_char temp(e.getMsg()); + throw DecryptionException(string("XMLSecurity exception while decrypting: ") + temp.get()); + } + catch(XSECCryptoException& e) { + throw DecryptionException(string("XMLSecurity exception while decrypting: ") + e.getMsg()); + } +} + +XSECCryptoKey* Decrypter::decryptKey(EncryptedKey* encryptedKey, const XMLCh* algorithm) +{ + if (encryptedKey->getDOM()==NULL) + throw DecryptionException("The object must be marshalled before decryption."); + + // We can reuse the cipher object if the document hasn't changed. + + if (m_cipher && m_cipher->getDocument()!=encryptedKey->getDOM()->getOwnerDocument()) { + XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseCipher(m_cipher); + m_cipher=NULL; + } + + if (!m_cipher) + m_cipher=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newCipher(encryptedKey->getDOM()->getOwnerDocument()); + + try { + // Resolve key decryption key. + XSECCryptoKey* key=NULL; + if (m_KEKresolver) + key=m_KEKresolver->resolveKey(encryptedKey->getKeyInfo()); + if (!key) + throw DecryptionException("Unable to resolve a key decryption key."); + m_cipher->setKEK(key); + + XMLByte buffer[1024]; + int keySize = m_cipher->decryptKey(encryptedKey->getDOM(), buffer, 1024); + if (keySize > 0) { + // Try to map the key. + XSECAlgorithmHandler* handler = XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(algorithm); + if (handler != NULL) + return handler->createKeyForURI(algorithm, buffer, keySize); + throw DecryptionException("Unrecognized algorithm, could not build object around decrypted key."); + } + throw DecryptionException("Unable to decrypt key."); + } + catch(XSECException& e) { + auto_ptr_char temp(e.getMsg()); + throw DecryptionException(string("XMLSecurity exception while decrypting: ") + temp.get()); + } + catch(XSECCryptoException& e) { + throw DecryptionException(string("XMLSecurity exception while decrypting: ") + e.getMsg()); + } +} diff --git a/xmltooling/encryption/impl/Encrypter.cpp b/xmltooling/encryption/impl/Encrypter.cpp index 4f5b354..d4830cc 100644 --- a/xmltooling/encryption/impl/Encrypter.cpp +++ b/xmltooling/encryption/impl/Encrypter.cpp @@ -23,9 +23,10 @@ #include "internal.h" #include "encryption/Encrypter.h" -#include #include #include +#include +#include #include #include @@ -61,22 +62,14 @@ void Encrypter::checkParams(EncryptionParams& encParams, KeyEncryptionParams* ke if (!encParams.m_key) { // We have to have a raw key now, so we need to build a wrapper around it. - if (XMLString::equals(encParams.m_algorithm,DSIGConstants::s_unicodeStrURI3DES_CBC)) { - encParams.m_key=new OpenSSLCryptoSymmetricKey(XSECCryptoSymmetricKey::KEY_3DES_192); - } - else if (XMLString::equals(encParams.m_algorithm,DSIGConstants::s_unicodeStrURIAES128_CBC)) { - encParams.m_key=new OpenSSLCryptoSymmetricKey(XSECCryptoSymmetricKey::KEY_AES_128); - } - else if (XMLString::equals(encParams.m_algorithm,DSIGConstants::s_unicodeStrURIAES192_CBC)) { - encParams.m_key=new OpenSSLCryptoSymmetricKey(XSECCryptoSymmetricKey::KEY_AES_192); - } - else if (XMLString::equals(encParams.m_algorithm,DSIGConstants::s_unicodeStrURIAES256_CBC)) { - encParams.m_key=new OpenSSLCryptoSymmetricKey(XSECCryptoSymmetricKey::KEY_AES_256); - } - else { - throw EncryptionException("Unrecognized encryption algorithm, unable to build key wrapper."); - } - static_cast(encParams.m_key)->setKey(encParams.m_keyBuffer, encParams.m_keyBufferSize); + XSECAlgorithmHandler* handler =XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(encParams.m_algorithm); + if (handler != NULL) + encParams.m_key = handler->createKeyForURI( + encParams.m_algorithm,const_cast(encParams.m_keyBuffer),encParams.m_keyBufferSize + ); + + if (!encParams.m_key) + throw EncryptionException("Unable to build wrapper for key, unknown algorithm?"); } // Set the encryption key. @@ -222,3 +215,51 @@ EncryptedData* Encrypter::decorateAndUnmarshall(EncryptionParams& encParams, Key xmlObject.release(); return xmlEncData; } + +EncryptedKey* Encrypter::encryptKey(const unsigned char* keyBuffer, unsigned int keyBufferSize, KeyEncryptionParams& kencParams) +{ + // Get a fresh cipher object and document. + + if (m_cipher) { + XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseCipher(m_cipher); + m_cipher=NULL; + } + + DOMDocument* doc=NULL; + try { + doc=XMLToolingConfig::getConfig().getParser().newDocument(); + m_cipher=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newCipher(doc); + m_cipher->setKEK(kencParams.m_key->clone()); + auto_ptr encKey(m_cipher->encryptKey(keyBuffer, keyBufferSize, ENCRYPT_NONE, kencParams.m_algorithm)); + + EncryptedKey* xmlEncKey=NULL; + auto_ptr xmlObjectKey(XMLObjectBuilder::buildOneFromElement(encKey->getElement())); + if (!(xmlObjectKey.get()) || !(xmlEncKey=dynamic_cast(xmlObjectKey.get()))) + throw EncryptionException("Unable to unmarshall into EncryptedKey object."); + + xmlEncKey->releaseThisAndChildrenDOM(); + + // KeyInfo? + if (kencParams.m_keyInfo) { + xmlEncKey->setKeyInfo(kencParams.m_keyInfo); + kencParams.m_keyInfo=NULL; // transfer ownership + } + + doc->release(); + xmlObjectKey.release(); + return xmlEncKey; + } + catch(XSECException& e) { + doc->release(); + auto_ptr_char temp(e.getMsg()); + throw EncryptionException(string("XMLSecurity exception while encrypting: ") + temp.get()); + } + catch(XSECCryptoException& e) { + doc->release(); + throw EncryptionException(string("XMLSecurity exception while encrypting: ") + e.getMsg()); + } + catch (...) { + doc->release(); + throw; + } +} diff --git a/xmltooling/signature/KeyResolver.h b/xmltooling/signature/KeyResolver.h new file mode 100644 index 0000000..cf318be --- /dev/null +++ b/xmltooling/signature/KeyResolver.h @@ -0,0 +1,88 @@ +/* + * Copyright 2001-2006 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file KeyResolver.h + * + * Resolves keys based on KeyInfo information or other external factors. + */ + +#if !defined(__xmltooling_keyres_h__) && !defined(XMLTOOLING_NO_XMLSEC) +#define __xmltooling_keyres_h__ + +#include + +#include +#include + +namespace xmlsignature { + + /** + * An API for resolving decryption keys. + * Can be used during both data and key decryption. + */ + class XMLTOOL_API KeyResolver { + public: + /** + * Constructor based on a single externally supplied decryption key. + * The key will be destroyed when the resolver is. + * + * @param key external decryption key + */ + KeyResolver(XSECCryptoKey* key=NULL) : m_key(key) {} + + virtual ~KeyResolver() { + delete m_key; + } + + /** + * Returns a key based on the supplied KeyInfo information. + * The caller must delete the key when done with it. + * + * @param keyInfo the key information + * @return the resolved key + */ + virtual XSECCryptoKey* resolveKey(KeyInfo* keyInfo) { + return m_key ? m_key->clone() : NULL; + } + + /** + * Returns a key based on the supplied KeyInfo information. + * The caller must delete the key when done with it. + * + * @param keyInfo the key information + * @return the resolved key + */ + virtual XSECCryptoKey* resolveKey(DSIGKeyInfoList* keyInfo=NULL) { + return m_key ? m_key->clone() : NULL; + } + + /** + * Creates a copy of the resolver. + * + * @return the cloned resolver + */ + virtual KeyResolver* clone() const { + return new KeyResolver(m_key ? m_key->clone() : NULL); + } + + protected: + XSECCryptoKey* m_key; + }; + +}; + +#endif /* __xmltooling_keyres_h__ */ diff --git a/xmltooling/signature/SignatureValidator.h b/xmltooling/signature/SignatureValidator.h index 6a09ef4..4dc362a 100644 --- a/xmltooling/signature/SignatureValidator.h +++ b/xmltooling/signature/SignatureValidator.h @@ -23,13 +23,14 @@ #if !defined(__xmltooling_sigval_h__) && !defined(XMLTOOLING_NO_XMLSEC) #define __xmltooling_sigval_h__ +#include #include #include namespace xmlsignature { /** - * Validator for signatures based on an externally-supplied key. + * Validator for signatures based on a KeyResolver */ class XMLTOOL_API SignatureValidator : public virtual xmltooling::Validator { @@ -37,15 +38,13 @@ namespace xmlsignature { /** * Constructor * - * @param key the verification key to use, will be freed by Validator + * @param resolver the key resolver to use, will be freed by Validator */ - SignatureValidator(XSECCryptoKey* key) : m_key(key) { - if (!key) - throw xmltooling::ValidationException("Verification key cannot be NULL."); + SignatureValidator(KeyResolver* resolver) : m_resolver(resolver) { } virtual ~SignatureValidator() { - delete m_key; + delete m_resolver; } void validate(const xmltooling::XMLObject* xmlObject) const; @@ -55,14 +54,23 @@ namespace xmlsignature { SignatureValidator* clone() const { return new SignatureValidator(*this); } + + /** + * Replace the current KeyResolver, if any, with a new one. + * + * @param resolver the KeyResolver to attach + */ + void setKeyResolver(KeyResolver* resolver) { + delete m_resolver; + m_resolver=resolver; + } protected: SignatureValidator(const SignatureValidator& src) { - m_key=src.m_key->clone(); + m_resolver=src.m_resolver ? src.m_resolver->clone() : NULL; } - private: - XSECCryptoKey* m_key; + KeyResolver* m_resolver; }; }; diff --git a/xmltooling/signature/impl/SignatureValidator.cpp b/xmltooling/signature/impl/SignatureValidator.cpp index e6b1cec..ab41546 100644 --- a/xmltooling/signature/impl/SignatureValidator.cpp +++ b/xmltooling/signature/impl/SignatureValidator.cpp @@ -43,9 +43,14 @@ void SignatureValidator::validate(const Signature* sigObj) const DSIGSignature* sig=sigObj->getXMLSignature(); if (!sig) throw ValidationException("Signature does not exist yet."); + else if (!m_resolver) + throw ValidationException("No KeyResolver set on Validator."); try { - sig->setSigningKey(m_key->clone()); + XSECCryptoKey* key=m_resolver->resolveKey(sig->getKeyInfoList()); + if (!key) + throw ValidationException("Unable to resolve signing key."); + sig->setSigningKey(key); if (!sig->verify()) throw ValidationException("Digital signature does not validate with the given key."); } diff --git a/xmltooling/xmltooling.vcproj b/xmltooling/xmltooling.vcproj index b6d71f5..54a48c3 100644 --- a/xmltooling/xmltooling.vcproj +++ b/xmltooling/xmltooling.vcproj @@ -316,6 +316,10 @@ Name="impl" > + + @@ -507,6 +511,10 @@ > + + @@ -519,6 +527,10 @@ Name="encryption" > + + diff --git a/xmltoolingtest/EncryptionTest.h b/xmltoolingtest/EncryptionTest.h new file mode 100644 index 0000000..cff6670 --- /dev/null +++ b/xmltoolingtest/EncryptionTest.h @@ -0,0 +1,117 @@ +/* + * Copyright 2001-2005 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "XMLObjectBaseTestCase.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace xmlencryption; + +class _addcert : public std::binary_function { +public: + void operator()(X509Data* bag, XSECCryptoX509* cert) const { + safeBuffer& buf=cert->getDEREncodingSB(); + X509Certificate* x=X509CertificateBuilder::buildX509Certificate(); + x->setValue(buf.sbStrToXMLCh()); + bag->getX509Certificates().push_back(x); + } +}; + +class EncryptionTest : public CxxTest::TestSuite { + XSECCryptoKey* m_key; + vector m_certs; +public: + void setUp() { + string keypath=data_path + "key.pem"; + BIO* in=BIO_new(BIO_s_file_internal()); + if (in && BIO_read_filename(in,keypath.c_str())>0) { + EVP_PKEY* pkey=PEM_read_bio_PrivateKey(in, NULL, NULL, NULL); + if (pkey) { + m_key=new OpenSSLCryptoKeyRSA(pkey); + EVP_PKEY_free(pkey); + } + } + if (in) BIO_free(in); + TS_ASSERT(m_key!=NULL); + + string certpath=data_path + "cert.pem"; + in=BIO_new(BIO_s_file_internal()); + if (in && BIO_read_filename(in,certpath.c_str())>0) { + X509* x=NULL; + while (x=PEM_read_bio_X509(in,NULL,NULL,NULL)) { + m_certs.push_back(new OpenSSLCryptoX509(x)); + X509_free(x); + } + } + if (in) BIO_free(in); + TS_ASSERT(m_certs.size()>0); + + } + + void tearDown() { + delete m_key; + for_each(m_certs.begin(),m_certs.end(),xmltooling::cleanup()); + } + + void testBasic() { + TS_TRACE("testBasic"); + + string path=data_path + "ComplexXMLObject.xml"; + ifstream fs(path.c_str()); + DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); + TS_ASSERT(doc!=NULL); + + try { + Encrypter encrypter; + Encrypter::EncryptionParams ep; + Encrypter::KeyEncryptionParams kep(DSIGConstants::s_unicodeStrURIRSA_1_5,m_key->clone()); + auto_ptr encData(encrypter.encryptElement(doc->getDocumentElement(),ep,&kep)); + + string buf; + XMLHelper::serialize(encData->marshall(), buf); + istringstream is(buf); + DOMDocument* doc2=XMLToolingConfig::getConfig().getValidatingParser().parse(is); + auto_ptr encData2( + dynamic_cast(XMLObjectBuilder::buildOneFromElement(doc2->getDocumentElement(),true)) + ); + + Decrypter decrypter(new KeyResolver(m_key->clone())); + DOMDocumentFragment* frag = decrypter.decryptData(encData2.get()); + XMLHelper::serialize(static_cast(frag->getFirstChild()), buf); + TS_TRACE(buf.c_str()); + TS_ASSERT(doc->getDocumentElement()->isEqualNode(frag->getFirstChild())); + frag->release(); + doc->release(); + } + catch (XMLToolingException& e) { + TS_TRACE(e.what()); + doc->release(); + throw; + } + } + +}; diff --git a/xmltoolingtest/Makefile.am b/xmltoolingtest/Makefile.am index d8cd904..69538ec 100644 --- a/xmltoolingtest/Makefile.am +++ b/xmltoolingtest/Makefile.am @@ -9,6 +9,7 @@ endif if BUILD_XMLSEC xmlsec_sources = \ + EncryptionTest.h \ SignatureTest.h else xmlsec_sources = diff --git a/xmltoolingtest/SignatureTest.h b/xmltoolingtest/SignatureTest.h index c3cd9bb..458fa7e 100644 --- a/xmltoolingtest/SignatureTest.h +++ b/xmltoolingtest/SignatureTest.h @@ -57,7 +57,7 @@ class TestValidator : public SignatureValidator } public: - TestValidator(const XMLCh* uri, XSECCryptoKey* key) : SignatureValidator(key) { + TestValidator(const XMLCh* uri, XSECCryptoKey* key) : SignatureValidator(new KeyResolver(key)) { m_uri=XMLString::replicate(uri); } diff --git a/xmltoolingtest/data/ComplexXMLObject.xml b/xmltoolingtest/data/ComplexXMLObject.xml index 4cb5799..3951644 100644 --- a/xmltoolingtest/data/ComplexXMLObject.xml +++ b/xmltoolingtest/data/ComplexXMLObject.xml @@ -1,27 +1,21 @@ - + Python Perfect IDE Uses mind-reading technology to anticipate and accommodate all user needs in Python development. Implements all - from __future__ import features though + from __future__ import features though the year 3000. Works well with 1166. XSLT Perfect IDE - + red - blue - - A link + blue + + A link diff --git a/xmltoolingtest/xmltoolingtest.vcproj b/xmltoolingtest/xmltoolingtest.vcproj index 5b5b146..02de35a 100644 --- a/xmltoolingtest/xmltoolingtest.vcproj +++ b/xmltoolingtest/xmltoolingtest.vcproj @@ -184,6 +184,10 @@ > + + @@ -236,6 +240,28 @@ + + + + + + + +