gcc const fix, converted linefeeds
[shibboleth/cpp-xmltooling.git] / xmltooling / signature / impl / XMLSecSignatureImpl.cpp
index 31f5743..4168149 100644 (file)
-/*\r
-*  Copyright 2001-2006 Internet2\r
- * \r
-* Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *     http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * XMLSecSignatureImpl.cpp\r
- * \r
- * Signature class for XMLSec-based signature-handling\r
- */\r
-\r
-#include "internal.h"\r
-#include "exceptions.h"\r
-#include "impl/UnknownElement.h"\r
-#include "signature/KeyInfo.h"\r
-#include "signature/Signature.h"\r
-#include "util/NDC.h"\r
-#include "util/XMLConstants.h"\r
-#include "util/XMLHelper.h"\r
-\r
-#include <log4cpp/Category.hh>\r
-#include <xercesc/framework/MemBufInputSource.hpp>\r
-#include <xercesc/framework/Wrapper4InputSource.hpp>\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-#include <xsec/dsig/DSIGKeyInfoX509.hpp>\r
-#include <xsec/dsig/DSIGReference.hpp>\r
-#include <xsec/enc/XSECCryptoException.hpp>\r
-#include <xsec/framework/XSECException.hpp>\r
-\r
-using namespace xmlsignature;\r
-using namespace xmltooling;\r
-using namespace log4cpp;\r
-using namespace std;\r
-\r
-#if defined (_MSC_VER)\r
-    #pragma warning( push )\r
-    #pragma warning( disable : 4250 4251 )\r
-#endif\r
-\r
-namespace xmlsignature {\r
-    \r
-    class XMLTOOL_DLLLOCAL XMLSecSignatureImpl : public UnknownElementImpl, public virtual Signature\r
-    {\r
-    public:\r
-        XMLSecSignatureImpl() : UnknownElementImpl(XMLConstants::XMLSIG_NS, Signature::LOCAL_NAME, XMLConstants::XMLSIG_PREFIX),\r
-            m_signature(NULL), m_c14n(NULL), m_sm(NULL), m_key(NULL), m_keyInfo(NULL), m_reference(NULL) {}\r
-        virtual ~XMLSecSignatureImpl();\r
-        \r
-        void releaseDOM() const;\r
-        void releaseChildrenDOM(bool propagateRelease=true) const {\r
-            if (m_keyInfo) {\r
-                m_keyInfo->releaseDOM();\r
-                if (propagateRelease)\r
-                    m_keyInfo->releaseChildrenDOM();\r
-            }\r
-        }\r
-        XMLObject* clone() const;\r
-        Signature* cloneSignature() const;\r
-\r
-        DOMElement* marshall(DOMDocument* document=NULL, const vector<Signature*>* sigs=NULL) const;\r
-        DOMElement* marshall(DOMElement* parentElement, const vector<Signature*>* sigs=NULL) const;\r
-        XMLObject* unmarshall(DOMElement* element, bool bindDocument=false);\r
-        \r
-        // Getters\r
-        const XMLCh* getCanonicalizationMethod() const { return m_c14n ? m_c14n : DSIGConstants::s_unicodeStrURIEXC_C14N_NOC; }\r
-        const XMLCh* getSignatureAlgorithm() const { return m_sm ? m_sm : DSIGConstants::s_unicodeStrURIRSA_SHA1; }\r
-        KeyInfo* getKeyInfo() const { return m_keyInfo; }\r
-        ContentReference* getContentReference() const { return m_reference; }\r
-        DSIGSignature* getXMLSignature() const { return m_signature; }\r
-        \r
-        // Setters\r
-        void setCanonicalizationMethod(const XMLCh* c14n) { m_c14n = prepareForAssignment(m_c14n,c14n); }\r
-        void setSignatureAlgorithm(const XMLCh* sm) { m_sm = prepareForAssignment(m_sm,sm); }\r
-        void setSigningKey(XSECCryptoKey* signingKey) {\r
-            delete m_key;\r
-            m_key=signingKey;\r
-        }\r
-        void setKeyInfo(KeyInfo* keyInfo) {\r
-            prepareForAssignment(m_keyInfo, keyInfo);\r
-            m_keyInfo=keyInfo;\r
-        }\r
-        void setContentReference(ContentReference* reference) {\r
-            delete m_reference;\r
-            m_reference=reference;\r
-        }\r
-        \r
-        void sign();\r
-\r
-    private:\r
-        mutable DSIGSignature* m_signature;\r
-        XMLCh* m_c14n;\r
-        XMLCh* m_sm;\r
-        XSECCryptoKey* m_key;\r
-        KeyInfo* m_keyInfo;\r
-        ContentReference* m_reference;\r
-    };\r
-    \r
-};\r
-\r
-#if defined (_MSC_VER)\r
-    #pragma warning( pop )\r
-#endif\r
-\r
-XMLSecSignatureImpl::~XMLSecSignatureImpl()\r
-{\r
-    // Release the associated signature.\r
-    if (m_signature)\r
-        XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseSignature(m_signature);\r
-\r
-    XMLString::release(&m_c14n);\r
-    XMLString::release(&m_sm);\r
-    delete m_key;\r
-    delete m_keyInfo;\r
-    delete m_reference;\r
-}\r
-\r
-void XMLSecSignatureImpl::releaseDOM() const\r
-{\r
-    if (getDOM()) {\r
-        // This should save off the DOM\r
-        UnknownElementImpl::releaseDOM();\r
-        \r
-        // Release the associated signature.\r
-        if (m_signature) {\r
-            XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseSignature(m_signature);\r
-            m_signature=NULL;\r
-        }\r
-    }\r
-}\r
-\r
-XMLObject* XMLSecSignatureImpl::clone() const\r
-{\r
-    return cloneSignature();\r
-}\r
-\r
-Signature* XMLSecSignatureImpl::cloneSignature() const\r
-{\r
-    XMLSecSignatureImpl* ret=new XMLSecSignatureImpl();\r
-\r
-    ret->m_c14n=XMLString::replicate(m_c14n);\r
-    ret->m_sm=XMLString::replicate(m_sm);\r
-    if (m_key)\r
-        ret->m_key=m_key->clone();\r
-    if (m_keyInfo)\r
-        ret->m_keyInfo=m_keyInfo->cloneKeyInfo();\r
-\r
-    // If there's no XML locally, serialize this object into the new one, otherwise just copy it over.\r
-    if (m_xml.empty())\r
-        serialize(ret->m_xml);\r
-    else\r
-        ret->m_xml=m_xml;\r
-\r
-    return ret;\r
-}\r
-\r
-void XMLSecSignatureImpl::sign()\r
-{\r
-    Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Signature");\r
-    log.debug("applying signature");\r
-\r
-    if (!m_signature)\r
-        throw SignatureException("Only a marshalled Signature object can be signed.");\r
-    else if (!m_key)\r
-        throw SignatureException("No signing key available for signature creation.");\r
-    else if (!m_reference)\r
-        throw SignatureException("No ContentReference object set for signature creation.");\r
-\r
-    try {\r
-        log.debug("creating signature reference(s)");\r
-        DSIGReferenceList* refs = m_signature->getReferenceList();\r
-        while (refs && refs->getSize())\r
-            delete refs->removeReference(0);\r
-        m_reference->createReferences(m_signature);\r
-        \r
-        log.debug("computing signature");\r
-        m_signature->setSigningKey(m_key->clone());\r
-        m_signature->sign();\r
-    }\r
-    catch(XSECException& e) {\r
-        auto_ptr_char temp(e.getMsg());\r
-        throw SignatureException(string("Caught an XMLSecurity exception while signing: ") + temp.get());\r
-    }\r
-    catch(XSECCryptoException& e) {\r
-        throw SignatureException(string("Caught an XMLSecurity exception while signing: ") + e.getMsg());\r
-    }\r
-}\r
-\r
-DOMElement* XMLSecSignatureImpl::marshall(DOMDocument* document, const vector<Signature*>* sigs) const\r
-{\r
-#ifdef _DEBUG\r
-    xmltooling::NDC ndc("marshall");\r
-#endif\r
-    \r
-    Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Signature");\r
-    log.debug("marshalling ds:Signature");\r
-\r
-    DOMElement* cachedDOM=getDOM();\r
-    if (cachedDOM) {\r
-        if (!document || document==cachedDOM->getOwnerDocument()) {\r
-            log.debug("Signature has a usable cached DOM, reusing it");\r
-            if (document)\r
-                setDocumentElement(cachedDOM->getOwnerDocument(),cachedDOM);\r
-            releaseParentDOM(true);\r
-            return cachedDOM;\r
-        }\r
-        \r
-        // We have a DOM but it doesn't match the document we were given. This both sucks and blows.\r
-        // Without an adoptNode option to maintain the child pointers, we have to either import the\r
-        // DOM while somehow reassigning all the nested references (which amounts to a complete\r
-        // *unmarshall* operation), or we just release the existing DOM and hope that we can get\r
-        // it back. This depends on all objects being able to preserve their DOM at all costs.\r
-        releaseChildrenDOM(true);\r
-        releaseDOM();\r
-    }\r
-    \r
-    // If we get here, we didn't have a usable DOM.\r
-    bool bindDocument=false;\r
-    if (m_xml.empty()) {\r
-        // Fresh signature, so we just create an empty one.\r
-        log.debug("creating empty Signature element");\r
-        if (!document) {\r
-            document=DOMImplementationRegistry::getDOMImplementation(NULL)->createDocument();\r
-            bindDocument=true;\r
-        }\r
-        m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature();\r
-        m_signature->setDSIGNSPrefix(XMLConstants::XMLSIG_PREFIX);\r
-        cachedDOM=m_signature->createBlankSignature(document, getCanonicalizationMethod(), getSignatureAlgorithm());\r
-    }\r
-    else {\r
-        // We need to reparse the XML we saved off into a new DOM.\r
-        MemBufInputSource src(reinterpret_cast<const XMLByte*>(m_xml.c_str()),m_xml.length(),"XMLSecSignatureImpl");\r
-        Wrapper4InputSource dsrc(&src,false);\r
-        log.debug("parsing Signature XML back into DOM tree");\r
-        DOMDocument* internalDoc=XMLToolingConfig::getConfig().getParser().parse(dsrc);\r
-        if (document) {\r
-            // The caller insists on using his own document, so we now have to import the thing\r
-            // into it. Then we're just dumping the one we built.\r
-            log.debug("reimporting new DOM into caller-supplied document");\r
-            cachedDOM=static_cast<DOMElement*>(document->importNode(internalDoc->getDocumentElement(), true));\r
-            internalDoc->release();\r
-        }\r
-        else {\r
-            // We just bind the document we built to the object as the result.\r
-            cachedDOM=static_cast<DOMElement*>(internalDoc->getDocumentElement());\r
-            document=internalDoc;\r
-            bindDocument=true;\r
-        }\r
-\r
-        // Now reload the signature from the DOM.\r
-        try {\r
-            m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM(\r
-                document, cachedDOM\r
-                );\r
-            m_signature->load();\r
-        }\r
-        catch(XSECException& e) {\r
-            if (bindDocument)\r
-                document->release();\r
-            auto_ptr_char temp(e.getMsg());\r
-            throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + temp.get());\r
-        }\r
-        catch(XSECCryptoException& e) {\r
-            if (bindDocument)\r
-                document->release();\r
-            throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + e.getMsg());\r
-        }\r
-    }\r
-    \r
-    // Marshall KeyInfo data.\r
-    if (m_keyInfo && (!m_signature->getKeyInfoList() || m_signature->getKeyInfoList()->isEmpty())) {\r
-        m_keyInfo->marshall(cachedDOM);\r
-    }\r
-\r
-    // Recache the DOM and clear the serialized copy.\r
-    setDocumentElement(document, cachedDOM);\r
-    log.debug("caching DOM for Signature (document is %sbound)", bindDocument ? "" : "not ");\r
-    setDOM(cachedDOM, bindDocument);\r
-    releaseParentDOM(true);\r
-    m_xml.erase();\r
-    return cachedDOM;\r
-}\r
-\r
-DOMElement* XMLSecSignatureImpl::marshall(DOMElement* parentElement, const vector<Signature*>* sigs) const\r
-{\r
-#ifdef _DEBUG\r
-    xmltooling::NDC ndc("marshall");\r
-#endif\r
-    \r
-    Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Signature");\r
-    log.debug("marshalling ds:Signature");\r
-\r
-    DOMElement* cachedDOM=getDOM();\r
-    if (cachedDOM) {\r
-        if (parentElement->getOwnerDocument()==cachedDOM->getOwnerDocument()) {\r
-            log.debug("Signature has a usable cached DOM, reusing it");\r
-            if (parentElement!=cachedDOM->getParentNode()) {\r
-                parentElement->appendChild(cachedDOM);\r
-                releaseParentDOM(true);\r
-            }\r
-            return cachedDOM;\r
-        }\r
-        \r
-        // We have a DOM but it doesn't match the document we were given. This both sucks and blows.\r
-        // Without an adoptNode option to maintain the child pointers, we have to either import the\r
-        // DOM while somehow reassigning all the nested references (which amounts to a complete\r
-        // *unmarshall* operation), or we just release the existing DOM and hope that we can get\r
-        // it back. This depends on all objects being able to preserve their DOM at all costs.\r
-        releaseChildrenDOM(true);\r
-        releaseDOM();\r
-    }\r
-    \r
-    // If we get here, we didn't have a usable DOM.\r
-    if (m_xml.empty()) {\r
-        // Fresh signature, so we just create an empty one.\r
-        log.debug("creating empty Signature element");\r
-        m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature();\r
-        m_signature->setDSIGNSPrefix(XMLConstants::XMLSIG_PREFIX);\r
-        cachedDOM=m_signature->createBlankSignature(\r
-            parentElement->getOwnerDocument(), getCanonicalizationMethod(), getSignatureAlgorithm()\r
-            );\r
-    }\r
-    else {\r
-        MemBufInputSource src(reinterpret_cast<const XMLByte*>(m_xml.c_str()),m_xml.length(),"XMLSecSignatureImpl");\r
-        Wrapper4InputSource dsrc(&src,false);\r
-        log.debug("parsing XML back into DOM tree");\r
-        DOMDocument* internalDoc=XMLToolingConfig::getConfig().getParser().parse(dsrc);\r
-        \r
-        log.debug("reimporting new DOM into caller-supplied document");\r
-        cachedDOM=static_cast<DOMElement*>(parentElement->getOwnerDocument()->importNode(internalDoc->getDocumentElement(),true));\r
-        internalDoc->release();\r
-\r
-        // Now reload the signature from the DOM.\r
-        try {\r
-            m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM(\r
-                parentElement->getOwnerDocument(), cachedDOM\r
-                );\r
-            m_signature->load();\r
-        }\r
-        catch(XSECException& e) {\r
-            auto_ptr_char temp(e.getMsg());\r
-            throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + temp.get());\r
-        }\r
-        catch(XSECCryptoException& e) {\r
-            throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + e.getMsg());\r
-        }\r
-    }\r
-\r
-    // Marshall KeyInfo data.\r
-    if (m_keyInfo && (!m_signature->getKeyInfoList() || m_signature->getKeyInfoList()->isEmpty())) {\r
-        m_keyInfo->marshall(cachedDOM);\r
-    }\r
-\r
-    // Recache the DOM and clear the serialized copy.\r
-    parentElement->appendChild(cachedDOM);\r
-    log.debug("caching DOM for Signature");\r
-    setDOM(cachedDOM, false);\r
-    releaseParentDOM(true);\r
-    m_xml.erase();\r
-    return cachedDOM;\r
-}\r
-\r
-XMLObject* XMLSecSignatureImpl::unmarshall(DOMElement* element, bool bindDocument)\r
-{\r
-    Category::getInstance(XMLTOOLING_LOGCAT".Signature").debug("unmarshalling ds:Signature");\r
-\r
-    try {\r
-        m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM(\r
-            element->getOwnerDocument(), element\r
-            );\r
-        m_signature->load();\r
-    }\r
-    catch(XSECException& e) {\r
-        auto_ptr_char temp(e.getMsg());\r
-        throw UnmarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + temp.get());\r
-    }\r
-    catch(XSECCryptoException& e) {\r
-        throw UnmarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + e.getMsg());\r
-    }\r
-\r
-    setDOM(element, bindDocument);\r
-    return this;\r
-}\r
-\r
-Signature* SignatureBuilder::buildObject(\r
-    const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType\r
-    ) const\r
-{\r
-    if (!XMLString::equals(nsURI,XMLConstants::XMLSIG_NS) || !XMLString::equals(localName,Signature::LOCAL_NAME))\r
-        throw XMLObjectException("XMLSecSignatureBuilder requires standard Signature element name.");\r
-    return buildObject();\r
-}\r
-\r
-Signature* SignatureBuilder::buildObject() const\r
-{\r
-    return new XMLSecSignatureImpl();\r
-}\r
-\r
-const XMLCh Signature::LOCAL_NAME[] = UNICODE_LITERAL_9(S,i,g,n,a,t,u,r,e);\r
+/*
+*  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.
+ */
+
+/**
+ * XMLSecSignatureImpl.cpp
+ * 
+ * Signature class for XMLSec-based signature-handling
+ */
+
+#include "internal.h"
+#include "exceptions.h"
+#include "impl/UnknownElement.h"
+#include "signature/KeyInfo.h"
+#include "signature/Signature.h"
+#include "util/NDC.h"
+#include "util/XMLConstants.h"
+#include "util/XMLHelper.h"
+
+#include <log4cpp/Category.hh>
+#include <xercesc/framework/MemBufInputSource.hpp>
+#include <xercesc/framework/Wrapper4InputSource.hpp>
+#include <xercesc/util/XMLUniDefs.hpp>
+#include <xsec/dsig/DSIGKeyInfoX509.hpp>
+#include <xsec/dsig/DSIGReference.hpp>
+#include <xsec/enc/XSECCryptoException.hpp>
+#include <xsec/framework/XSECException.hpp>
+
+using namespace xmlsignature;
+using namespace xmltooling;
+using namespace log4cpp;
+using namespace std;
+
+#if defined (_MSC_VER)
+    #pragma warning( push )
+    #pragma warning( disable : 4250 4251 )
+#endif
+
+namespace xmlsignature {
+    
+    class XMLTOOL_DLLLOCAL XMLSecSignatureImpl : public UnknownElementImpl, public virtual Signature
+    {
+    public:
+        XMLSecSignatureImpl() : UnknownElementImpl(XMLConstants::XMLSIG_NS, Signature::LOCAL_NAME, XMLConstants::XMLSIG_PREFIX),
+            m_signature(NULL), m_c14n(NULL), m_sm(NULL), m_key(NULL), m_keyInfo(NULL), m_reference(NULL) {}
+        virtual ~XMLSecSignatureImpl();
+        
+        void releaseDOM() const;
+        void releaseChildrenDOM(bool propagateRelease=true) const {
+            if (m_keyInfo) {
+                m_keyInfo->releaseDOM();
+                if (propagateRelease)
+                    m_keyInfo->releaseChildrenDOM();
+            }
+        }
+        XMLObject* clone() const;
+        Signature* cloneSignature() const;
+
+        DOMElement* marshall(DOMDocument* document=NULL, const vector<Signature*>* sigs=NULL) const;
+        DOMElement* marshall(DOMElement* parentElement, const vector<Signature*>* sigs=NULL) const;
+        XMLObject* unmarshall(DOMElement* element, bool bindDocument=false);
+        
+        // Getters
+        const XMLCh* getCanonicalizationMethod() const { return m_c14n ? m_c14n : DSIGConstants::s_unicodeStrURIEXC_C14N_NOC; }
+        const XMLCh* getSignatureAlgorithm() const { return m_sm ? m_sm : DSIGConstants::s_unicodeStrURIRSA_SHA1; }
+        KeyInfo* getKeyInfo() const { return m_keyInfo; }
+        ContentReference* getContentReference() const { return m_reference; }
+        DSIGSignature* getXMLSignature() const { return m_signature; }
+        
+        // Setters
+        void setCanonicalizationMethod(const XMLCh* c14n) { m_c14n = prepareForAssignment(m_c14n,c14n); }
+        void setSignatureAlgorithm(const XMLCh* sm) { m_sm = prepareForAssignment(m_sm,sm); }
+        void setSigningKey(XSECCryptoKey* signingKey) {
+            delete m_key;
+            m_key=signingKey;
+        }
+        void setKeyInfo(KeyInfo* keyInfo) {
+            prepareForAssignment(m_keyInfo, keyInfo);
+            m_keyInfo=keyInfo;
+        }
+        void setContentReference(ContentReference* reference) {
+            delete m_reference;
+            m_reference=reference;
+        }
+        
+        void sign();
+
+    private:
+        mutable DSIGSignature* m_signature;
+        XMLCh* m_c14n;
+        XMLCh* m_sm;
+        XSECCryptoKey* m_key;
+        KeyInfo* m_keyInfo;
+        ContentReference* m_reference;
+    };
+    
+};
+
+#if defined (_MSC_VER)
+    #pragma warning( pop )
+#endif
+
+XMLSecSignatureImpl::~XMLSecSignatureImpl()
+{
+    // Release the associated signature.
+    if (m_signature)
+        XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseSignature(m_signature);
+
+    XMLString::release(&m_c14n);
+    XMLString::release(&m_sm);
+    delete m_key;
+    delete m_keyInfo;
+    delete m_reference;
+}
+
+void XMLSecSignatureImpl::releaseDOM() const
+{
+    if (getDOM()) {
+        // This should save off the DOM
+        UnknownElementImpl::releaseDOM();
+        
+        // Release the associated signature.
+        if (m_signature) {
+            XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseSignature(m_signature);
+            m_signature=NULL;
+        }
+    }
+}
+
+XMLObject* XMLSecSignatureImpl::clone() const
+{
+    return cloneSignature();
+}
+
+Signature* XMLSecSignatureImpl::cloneSignature() const
+{
+    XMLSecSignatureImpl* ret=new XMLSecSignatureImpl();
+
+    ret->m_c14n=XMLString::replicate(m_c14n);
+    ret->m_sm=XMLString::replicate(m_sm);
+    if (m_key)
+        ret->m_key=m_key->clone();
+    if (m_keyInfo)
+        ret->m_keyInfo=m_keyInfo->cloneKeyInfo();
+
+    // If there's no XML locally, serialize this object into the new one, otherwise just copy it over.
+    if (m_xml.empty())
+        serialize(ret->m_xml);
+    else
+        ret->m_xml=m_xml;
+
+    return ret;
+}
+
+void XMLSecSignatureImpl::sign()
+{
+    Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Signature");
+    log.debug("applying signature");
+
+    if (!m_signature)
+        throw SignatureException("Only a marshalled Signature object can be signed.");
+    else if (!m_key)
+        throw SignatureException("No signing key available for signature creation.");
+    else if (!m_reference)
+        throw SignatureException("No ContentReference object set for signature creation.");
+
+    try {
+        log.debug("creating signature reference(s)");
+        DSIGReferenceList* refs = m_signature->getReferenceList();
+        while (refs && refs->getSize())
+            delete refs->removeReference(0);
+        m_reference->createReferences(m_signature);
+        
+        log.debug("computing signature");
+        m_signature->setSigningKey(m_key->clone());
+        m_signature->sign();
+    }
+    catch(XSECException& e) {
+        auto_ptr_char temp(e.getMsg());
+        throw SignatureException(string("Caught an XMLSecurity exception while signing: ") + temp.get());
+    }
+    catch(XSECCryptoException& e) {
+        throw SignatureException(string("Caught an XMLSecurity exception while signing: ") + e.getMsg());
+    }
+}
+
+DOMElement* XMLSecSignatureImpl::marshall(DOMDocument* document, const vector<Signature*>* sigs) const
+{
+#ifdef _DEBUG
+    xmltooling::NDC ndc("marshall");
+#endif
+    
+    Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Signature");
+    log.debug("marshalling ds:Signature");
+
+    DOMElement* cachedDOM=getDOM();
+    if (cachedDOM) {
+        if (!document || document==cachedDOM->getOwnerDocument()) {
+            log.debug("Signature has a usable cached DOM, reusing it");
+            if (document)
+                setDocumentElement(cachedDOM->getOwnerDocument(),cachedDOM);
+            releaseParentDOM(true);
+            return cachedDOM;
+        }
+        
+        // We have a DOM but it doesn't match the document we were given. This both sucks and blows.
+        // Without an adoptNode option to maintain the child pointers, we have to either import the
+        // DOM while somehow reassigning all the nested references (which amounts to a complete
+        // *unmarshall* operation), or we just release the existing DOM and hope that we can get
+        // it back. This depends on all objects being able to preserve their DOM at all costs.
+        releaseChildrenDOM(true);
+        releaseDOM();
+    }
+    
+    // If we get here, we didn't have a usable DOM.
+    bool bindDocument=false;
+    if (m_xml.empty()) {
+        // Fresh signature, so we just create an empty one.
+        log.debug("creating empty Signature element");
+        if (!document) {
+            document=DOMImplementationRegistry::getDOMImplementation(NULL)->createDocument();
+            bindDocument=true;
+        }
+        m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature();
+        m_signature->setDSIGNSPrefix(XMLConstants::XMLSIG_PREFIX);
+        cachedDOM=m_signature->createBlankSignature(document, getCanonicalizationMethod(), getSignatureAlgorithm());
+    }
+    else {
+        // We need to reparse the XML we saved off into a new DOM.
+        MemBufInputSource src(reinterpret_cast<const XMLByte*>(m_xml.c_str()),m_xml.length(),"XMLSecSignatureImpl");
+        Wrapper4InputSource dsrc(&src,false);
+        log.debug("parsing Signature XML back into DOM tree");
+        DOMDocument* internalDoc=XMLToolingConfig::getConfig().getParser().parse(dsrc);
+        if (document) {
+            // The caller insists on using his own document, so we now have to import the thing
+            // into it. Then we're just dumping the one we built.
+            log.debug("reimporting new DOM into caller-supplied document");
+            cachedDOM=static_cast<DOMElement*>(document->importNode(internalDoc->getDocumentElement(), true));
+            internalDoc->release();
+        }
+        else {
+            // We just bind the document we built to the object as the result.
+            cachedDOM=static_cast<DOMElement*>(internalDoc->getDocumentElement());
+            document=internalDoc;
+            bindDocument=true;
+        }
+
+        // Now reload the signature from the DOM.
+        try {
+            m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM(
+                document, cachedDOM
+                );
+            m_signature->load();
+        }
+        catch(XSECException& e) {
+            if (bindDocument)
+                document->release();
+            auto_ptr_char temp(e.getMsg());
+            throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + temp.get());
+        }
+        catch(XSECCryptoException& e) {
+            if (bindDocument)
+                document->release();
+            throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + e.getMsg());
+        }
+    }
+    
+    // Marshall KeyInfo data.
+    if (m_keyInfo && (!m_signature->getKeyInfoList() || m_signature->getKeyInfoList()->isEmpty())) {
+        m_keyInfo->marshall(cachedDOM);
+    }
+
+    // Recache the DOM and clear the serialized copy.
+    setDocumentElement(document, cachedDOM);
+    log.debug("caching DOM for Signature (document is %sbound)", bindDocument ? "" : "not ");
+    setDOM(cachedDOM, bindDocument);
+    releaseParentDOM(true);
+    m_xml.erase();
+    return cachedDOM;
+}
+
+DOMElement* XMLSecSignatureImpl::marshall(DOMElement* parentElement, const vector<Signature*>* sigs) const
+{
+#ifdef _DEBUG
+    xmltooling::NDC ndc("marshall");
+#endif
+    
+    Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Signature");
+    log.debug("marshalling ds:Signature");
+
+    DOMElement* cachedDOM=getDOM();
+    if (cachedDOM) {
+        if (parentElement->getOwnerDocument()==cachedDOM->getOwnerDocument()) {
+            log.debug("Signature has a usable cached DOM, reusing it");
+            if (parentElement!=cachedDOM->getParentNode()) {
+                parentElement->appendChild(cachedDOM);
+                releaseParentDOM(true);
+            }
+            return cachedDOM;
+        }
+        
+        // We have a DOM but it doesn't match the document we were given. This both sucks and blows.
+        // Without an adoptNode option to maintain the child pointers, we have to either import the
+        // DOM while somehow reassigning all the nested references (which amounts to a complete
+        // *unmarshall* operation), or we just release the existing DOM and hope that we can get
+        // it back. This depends on all objects being able to preserve their DOM at all costs.
+        releaseChildrenDOM(true);
+        releaseDOM();
+    }
+    
+    // If we get here, we didn't have a usable DOM.
+    if (m_xml.empty()) {
+        // Fresh signature, so we just create an empty one.
+        log.debug("creating empty Signature element");
+        m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature();
+        m_signature->setDSIGNSPrefix(XMLConstants::XMLSIG_PREFIX);
+        cachedDOM=m_signature->createBlankSignature(
+            parentElement->getOwnerDocument(), getCanonicalizationMethod(), getSignatureAlgorithm()
+            );
+    }
+    else {
+        MemBufInputSource src(reinterpret_cast<const XMLByte*>(m_xml.c_str()),m_xml.length(),"XMLSecSignatureImpl");
+        Wrapper4InputSource dsrc(&src,false);
+        log.debug("parsing XML back into DOM tree");
+        DOMDocument* internalDoc=XMLToolingConfig::getConfig().getParser().parse(dsrc);
+        
+        log.debug("reimporting new DOM into caller-supplied document");
+        cachedDOM=static_cast<DOMElement*>(parentElement->getOwnerDocument()->importNode(internalDoc->getDocumentElement(),true));
+        internalDoc->release();
+
+        // Now reload the signature from the DOM.
+        try {
+            m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM(
+                parentElement->getOwnerDocument(), cachedDOM
+                );
+            m_signature->load();
+        }
+        catch(XSECException& e) {
+            auto_ptr_char temp(e.getMsg());
+            throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + temp.get());
+        }
+        catch(XSECCryptoException& e) {
+            throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + e.getMsg());
+        }
+    }
+
+    // Marshall KeyInfo data.
+    if (m_keyInfo && (!m_signature->getKeyInfoList() || m_signature->getKeyInfoList()->isEmpty())) {
+        m_keyInfo->marshall(cachedDOM);
+    }
+
+    // Recache the DOM and clear the serialized copy.
+    parentElement->appendChild(cachedDOM);
+    log.debug("caching DOM for Signature");
+    setDOM(cachedDOM, false);
+    releaseParentDOM(true);
+    m_xml.erase();
+    return cachedDOM;
+}
+
+XMLObject* XMLSecSignatureImpl::unmarshall(DOMElement* element, bool bindDocument)
+{
+    Category::getInstance(XMLTOOLING_LOGCAT".Signature").debug("unmarshalling ds:Signature");
+
+    try {
+        m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM(
+            element->getOwnerDocument(), element
+            );
+        m_signature->load();
+    }
+    catch(XSECException& e) {
+        auto_ptr_char temp(e.getMsg());
+        throw UnmarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + temp.get());
+    }
+    catch(XSECCryptoException& e) {
+        throw UnmarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + e.getMsg());
+    }
+
+    setDOM(element, bindDocument);
+    return this;
+}
+
+Signature* SignatureBuilder::buildObject(
+    const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType
+    ) const
+{
+    if (!XMLString::equals(nsURI,XMLConstants::XMLSIG_NS) || !XMLString::equals(localName,Signature::LOCAL_NAME))
+        throw XMLObjectException("XMLSecSignatureBuilder requires standard Signature element name.");
+    return buildObject();
+}
+
+Signature* SignatureBuilder::buildObject() const
+{
+    return new XMLSecSignatureImpl();
+}
+
+const XMLCh Signature::LOCAL_NAME[] = UNICODE_LITERAL_9(S,i,g,n,a,t,u,r,e);