Algorithm and key size criteria, incoming signature algorithm extraction.
authorScott Cantor <cantor.2@osu.edu>
Mon, 9 Apr 2007 03:34:12 +0000 (03:34 +0000)
committerScott Cantor <cantor.2@osu.edu>
Mon, 9 Apr 2007 03:34:12 +0000 (03:34 +0000)
xmltooling/XMLToolingConfig.cpp
xmltooling/XMLToolingConfig.h
xmltooling/encryption/impl/Decrypter.cpp
xmltooling/internal.h
xmltooling/security/BasicX509Credential.h
xmltooling/security/Credential.h
xmltooling/security/CredentialCriteria.h
xmltooling/security/impl/ExplicitKeyTrustEngine.cpp
xmltooling/security/impl/FilesystemCredentialResolver.cpp
xmltooling/signature/Signature.h
xmltooling/signature/impl/XMLSecSignatureImpl.cpp

index 4a00d2a..86c8396 100644 (file)
@@ -301,6 +301,7 @@ void XMLToolingInternalConfig::term()
     TrustEngineManager.deregisterFactories();
     CredentialResolverManager.deregisterFactories();
     KeyInfoResolverManager.deregisterFactories();
+    registerXMLAlgorithms();
 #endif
 
     delete m_keyInfoResolver;
@@ -463,4 +464,37 @@ XSECCryptoX509CRL* XMLToolingInternalConfig::X509CRL() const
 {
     return new OpenSSLCryptoX509CRL();
 }
+
+void XMLToolingInternalConfig::registerXMLAlgorithms()
+{
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIRSA_MD5, "RSA", 0);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIRSA_SHA1, "RSA", 0);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIRSA_SHA224, "RSA", 0);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIRSA_SHA256, "RSA", 0);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIRSA_SHA384, "RSA", 0);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIRSA_SHA512, "RSA", 0);
+
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIRSA_1_5, "RSA", 0);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIRSA_OAEP_MGFP1, "RSA", 0);
+
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIDSA_SHA1, "DSA", 0);
+
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIHMAC_SHA1, "HMAC", 0);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIHMAC_SHA224, "HMAC", 0);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIHMAC_SHA256, "HMAC", 0);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIHMAC_SHA384, "HMAC", 0);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIHMAC_SHA512, "HMAC", 0);
+
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURI3DES_CBC, "DESede", 192);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIKW_3DES, "DESede", 192);
+
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIAES128_CBC, "AES", 128);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIKW_AES128, "AES", 128);
+
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIAES192_CBC, "AES", 192);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIKW_AES192, "AES", 192);
+
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIAES256_CBC, "AES", 256);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIKW_AES256, "AES", 256);
+}
 #endif
index a16b806..92062e8 100644 (file)
@@ -30,7 +30,6 @@
 #ifndef XMLTOOLING_NO_XMLSEC
 namespace xmltooling {
     class XMLTOOL_API CredentialResolver;
-    class XMLTOOL_API KeyInfoSource;
     class XMLTOOL_API KeyInfoResolver;
     class XMLTOOL_API TrustEngine;
     class XMLTOOL_API XSECCryptoX509CRL;
@@ -252,6 +251,25 @@ namespace xmltooling {
          * Manages factories for TrustEngine plugins.
          */
         PluginManager<TrustEngine,const DOMElement*> TrustEngineManager;
+
+        /**
+         * Maps an XML Signature/Encryption algorithm identifier to a library-specific
+         * key algorithm and size for use in resolving credentials.
+         *
+         * @param xmlAlgorithm  XML Signature/Encryption algorithm identifier
+         * @return  a general key algorithm and key size (or 0 if the size is irrelevant)
+         */
+        virtual std::pair<const char*,unsigned int> mapXMLAlgorithmToKeyAlgorithm(const XMLCh* xmlAlgorithm) const=0;
+
+        /**
+         * Registers an XML Signature/Encryption algorithm identifier against a library-specific
+         * key algorithm and size for use in resolving credentials.
+         *
+         * @param xmlAlgorithm  XML Signature/Encryption algorithm identifier
+         * @param keyAlgorithm  a key algorithm
+         * @param size          a key size (or 0 if the size is irrelevant)
+         */
+        virtual void registerXMLAlgorithm(const XMLCh* xmlAlgorithm, const char* keyAlgorithm, unsigned int size=0)=0;
 #endif
 
         /**
index 5a34ab8..58a6dd0 100644 (file)
@@ -90,10 +90,8 @@ DOMDocumentFragment* Decrypter::decryptData(const EncryptedData& encryptedData,
         m_criteria->setUsage(CredentialCriteria::ENCRYPTION_CREDENTIAL);
         m_criteria->setKeyInfo(encryptedData.getKeyInfo());
         const EncryptionMethod* meth = encryptedData.getEncryptionMethod();
-        if (meth) {
-            auto_ptr_char alg(meth->getAlgorithm());
-            m_criteria->setKeyAlgorithm(alg.get());
-        }
+        if (meth)
+            m_criteria->setXMLAlgorithm(meth->getAlgorithm());
         m_credResolver->resolve(creds,m_criteria);
     }
     else {
@@ -101,10 +99,8 @@ DOMDocumentFragment* Decrypter::decryptData(const EncryptedData& encryptedData,
         criteria.setUsage(CredentialCriteria::ENCRYPTION_CREDENTIAL);
         criteria.setKeyInfo(encryptedData.getKeyInfo());
         const EncryptionMethod* meth = encryptedData.getEncryptionMethod();
-        if (meth) {
-            auto_ptr_char alg(meth->getAlgorithm());
-            criteria.setKeyAlgorithm(alg.get());
-        }
+        if (meth)
+            criteria.setXMLAlgorithm(meth->getAlgorithm());
         m_credResolver->resolve(creds,&criteria);
     }
 
@@ -175,10 +171,8 @@ XSECCryptoKey* Decrypter::decryptKey(const EncryptedKey& encryptedKey, const XML
         m_criteria->setUsage(CredentialCriteria::ENCRYPTION_CREDENTIAL);
         m_criteria->setKeyInfo(encryptedKey.getKeyInfo());
         const EncryptionMethod* meth = encryptedKey.getEncryptionMethod();
-        if (meth) {
-            auto_ptr_char alg(meth->getAlgorithm());
-            m_criteria->setKeyAlgorithm(alg.get());
-        }
+        if (meth)
+            m_criteria->setXMLAlgorithm(meth->getAlgorithm());
         m_credResolver->resolve(creds, m_criteria);
     }
     else {
@@ -186,10 +180,8 @@ XSECCryptoKey* Decrypter::decryptKey(const EncryptedKey& encryptedKey, const XML
         criteria.setUsage(CredentialCriteria::ENCRYPTION_CREDENTIAL);
         criteria.setKeyInfo(encryptedKey.getKeyInfo());
         const EncryptionMethod* meth = encryptedKey.getEncryptionMethod();
-        if (meth) {
-            auto_ptr_char alg(meth->getAlgorithm());
-            criteria.setKeyAlgorithm(alg.get());
-        }
+        if (meth)
+            criteria.setXMLAlgorithm(meth->getAlgorithm());
         m_credResolver->resolve(creds, &criteria);
     }
     if (creds.empty())
index b6cc265..02b2ada 100644 (file)
@@ -110,7 +110,37 @@ namespace xmltooling {
 #ifndef XMLTOOLING_NO_XMLSEC
         XSECCryptoX509CRL* X509CRL() const;
 
+        std::pair<const char*,unsigned int> mapXMLAlgorithmToKeyAlgorithm(const XMLCh* xmlAlgorithm) const {
+# ifdef HAVE_GOOD_STL
+            algmap_t::const_iterator i = m_algorithmMap.find(xmlAlgorithm);
+# else
+            auto_ptr_char alg(xmlAlgorithm);
+            algmap_t::const_iterator i = m_algorithmMap.find(alg.get());
+# endif
+            if (i==m_algorithmMap.end())
+                return std::pair<const char*,unsigned int>(NULL,0);
+            return std::make_pair(i->second.first.c_str(), i->second.second);
+        }
+
+        void registerXMLAlgorithm(const XMLCh* xmlAlgorithm, const char* keyAlgorithm, unsigned int size=0) {
+# ifdef HAVE_GOOD_STL
+            m_algorithmMap[xmlAlgorithm] = std::pair<std::string,unsigned int>(keyAlgorithm,size);
+# else
+            auto_ptr_char alg(xmlAlgorithm);
+            m_algorithmMap[alg.get()] = std::pair<std::string,unsigned int>(keyAlgorithm,size);
+# endif
+        }
+
+        void registerXMLAlgorithms();
+
         XSECProvider* m_xsecProvider;
+    private:
+# ifdef HAVE_GOOD_STL
+        typedef std::map< xstring,std::pair<std::string,unsigned int> > algmap_t;
+# else
+        typedef std::map< std::string,std::pair<std::string,unsigned int> > algmap_t;
+# endif
+        algmap_t m_algorithmMap;
 #endif
 
     private:
index 6225f69..617f174 100644 (file)
@@ -79,6 +79,68 @@ namespace xmltooling {
     public:
         virtual ~BasicX509Credential();
         
+        const char* getAlgorithm() const {
+            if (m_key) {
+                switch (m_key->getKeyType()) {
+                    case XSECCryptoKey::KEY_RSA_PRIVATE:
+                    case XSECCryptoKey::KEY_RSA_PUBLIC:
+                    case XSECCryptoKey::KEY_RSA_PAIR:
+                        return "RSA";
+
+                    case XSECCryptoKey::KEY_DSA_PRIVATE:
+                    case XSECCryptoKey::KEY_DSA_PUBLIC:
+                    case XSECCryptoKey::KEY_DSA_PAIR:
+                        return "DSA";
+                    
+                    case XSECCryptoKey::KEY_HMAC:
+                        return "HMAC";
+
+                    case XSECCryptoKey::KEY_SYMMETRIC: {
+                        XSECCryptoSymmetricKey* skey = static_cast<XSECCryptoSymmetricKey*>(m_key);
+                        switch (skey->getSymmetricKeyType()) {
+                            case XSECCryptoSymmetricKey::KEY_3DES_192:
+                                return "DESede";
+                            case XSECCryptoSymmetricKey::KEY_AES_128:
+                                return "AES";
+                            case XSECCryptoSymmetricKey::KEY_AES_192:
+                                return "AES";
+                            case XSECCryptoSymmetricKey::KEY_AES_256:
+                                return "AES";
+                        }
+                    }
+                }
+            }
+            return NULL;
+        }
+
+        unsigned int getKeySize() const {
+            if (m_key) {
+                switch (m_key->getKeyType()) {
+                    case XSECCryptoKey::KEY_RSA_PRIVATE:
+                    case XSECCryptoKey::KEY_RSA_PUBLIC:
+                    case XSECCryptoKey::KEY_RSA_PAIR: {
+                        XSECCryptoKeyRSA* rkey = static_cast<XSECCryptoKeyRSA*>(m_key);
+                        return rkey->getLength();
+                    }
+
+                    case XSECCryptoKey::KEY_SYMMETRIC: {
+                        XSECCryptoSymmetricKey* skey = static_cast<XSECCryptoSymmetricKey*>(m_key);
+                        switch (skey->getSymmetricKeyType()) {
+                            case XSECCryptoSymmetricKey::KEY_3DES_192:
+                                return 192;
+                            case XSECCryptoSymmetricKey::KEY_AES_128:
+                                return 128;
+                            case XSECCryptoSymmetricKey::KEY_AES_192:
+                                return 192;
+                            case XSECCryptoSymmetricKey::KEY_AES_256:
+                                return 256;
+                        }
+                    }
+                }
+            }
+            return 0;
+        }
+
         XSECCryptoKey* getPrivateKey() const {
             if (m_key) {
                 XSECCryptoKey::KeyType type = m_key->getKeyType();
@@ -96,7 +158,7 @@ namespace xmltooling {
             }
             return NULL;
         }
-
+        
         std::vector<std::string>::size_type getKeyNames(std::vector<std::string>& results) const;
 
         const xmlsignature::KeyInfo* getKeyInfo(bool compact=false) const {
index c8d7756..c333b67 100644 (file)
@@ -24,7 +24,6 @@
 #define __xmltooling_cred_h__
 
 #include <xmltooling/base.h>
-
 #include <xsec/enc/XSECCryptoKey.hpp>
 
 namespace xmlsignature {
@@ -53,6 +52,20 @@ namespace xmltooling {
         };
 
         /**
+         * Returns an algorithm identifier for the Credential.
+         *
+         * @return  the Credential algorithm, or NULL if indeterminate
+         */
+        virtual const char* getAlgorithm() const=0;
+
+        /**
+         * Returns the size of the key.
+         *
+         * @return  the key size, or 0 if indeterminate
+         */
+        virtual unsigned int getKeySize() const=0;
+
+        /**
          * Returns a secret or private key to use for signing or decryption operations.
          * 
          * @return  a secret or private key
index 6777bd4..80509fd 100644 (file)
@@ -23,7 +23,7 @@
 #if !defined(__xmltooling_credcrit_h__) && !defined(XMLTOOLING_NO_XMLSEC)
 #define __xmltooling_credcrit_h__
 
-#include <xmltooling/unicode.h>
+#include <xmltooling/XMLToolingConfig.h>
 #include <xmltooling/signature/KeyInfo.h>
 #include <xmltooling/signature/Signature.h>
 
@@ -40,7 +40,7 @@ namespace xmltooling {
     {
         MAKE_NONCOPYABLE(CredentialCriteria);
     public:
-        CredentialCriteria() : m_keyUsage(UNSPECIFIED_CREDENTIAL), m_keyInfo(NULL), m_nativeKeyInfo(NULL) {}
+        CredentialCriteria() : m_keyUsage(UNSPECIFIED_CREDENTIAL), m_keySize(0), m_keyInfo(NULL), m_nativeKeyInfo(NULL) {}
         virtual ~CredentialCriteria() {}
 
         enum UsageType {
@@ -91,7 +91,7 @@ namespace xmltooling {
         /**
          * Get the key algorithm criteria.
          * 
-         * @return returns the keyAlgorithm.
+         * @return the key algorithm
          */
         const char* getKeyAlgorithm() const {
             return m_keyAlgorithm.c_str();
@@ -100,15 +100,51 @@ namespace xmltooling {
         /**
          * Set the key algorithm criteria.
          * 
-         * @param keyAlgorithm The keyAlgorithm to set.
+         * @param keyAlgorithm The key algorithm to set
          */
         void setKeyAlgorithm(const char* keyAlgorithm) {
             m_keyAlgorithm.erase();
             if (keyAlgorithm)
                 m_keyAlgorithm = keyAlgorithm;
         }
+
+        /**
+         * Get the key size criteria.
+         *
+         * @return  the key size, or 0
+         */
+        unsigned int getKeySize() const {
+            return m_keySize;
+        }
+
+        /**
+         * Set the key size criteria.
+         *
+         * @param keySize Key size to set
+         */
+        void setKeySize(unsigned int keySize) {
+            m_keySize = keySize;
+        }
     
         /**
+         * Set the key algorithm and size criteria based on an XML algorithm specifier.
+         *
+         * @param algorithm XML algorithm specifier
+         */
+        void setXMLAlgorithm(const XMLCh* algorithm) {
+            if (algorithm) {
+                std::pair<const char*,unsigned int> mapped =
+                    XMLToolingConfig::getConfig().mapXMLAlgorithmToKeyAlgorithm(algorithm);
+                setKeyAlgorithm(mapped.first);
+                setKeySize(mapped.second);
+            }
+            else {
+                setKeyAlgorithm(NULL);
+                setKeySize(0);
+            }
+        }
+
+        /**
          * Get the key name criteria.
          * 
          * @return the key name
@@ -165,6 +201,7 @@ namespace xmltooling {
         }
 
         void setSignature(const xmlsignature::Signature& sig) {
+            setXMLAlgorithm(sig.getSignatureAlgorithm());
             xmlsignature::KeyInfo* k = sig.getKeyInfo();
             if (k)
                 return setKeyInfo(k);
@@ -175,6 +212,7 @@ namespace xmltooling {
 
     private:
         UsageType m_keyUsage;
+        unsigned int m_keySize;
         std::string m_peerName,m_keyAlgorithm,m_keyName;
         const xmlsignature::KeyInfo* m_keyInfo;
         DSIGKeyInfoList* m_nativeKeyInfo;
index 7646bc5..e89ccac 100644 (file)
@@ -145,12 +145,14 @@ bool ExplicitKeyTrustEngine::validate(
     if (criteria) {
         criteria->setUsage(CredentialCriteria::SIGNING_CREDENTIAL);
         criteria->setKeyInfo(keyInfo);
+        criteria->setXMLAlgorithm(sigAlgorithm);
         credResolver.resolve(credentials,criteria);
     }
     else {
         CredentialCriteria cc;
         cc.setUsage(CredentialCriteria::SIGNING_CREDENTIAL);
         cc.setKeyInfo(keyInfo);
+        cc.setXMLAlgorithm(sigAlgorithm);
         credResolver.resolve(credentials,&cc);
     }
     if (credentials.empty()) {
@@ -241,7 +243,6 @@ bool ExplicitKeyTrustEngine::validate(
     for (vector<const Credential*>::const_iterator c=credentials.begin(); c!=credentials.end(); ++c) {
         XSECCryptoKey* key = (*c)->getPublicKey();
         if (key) {
-            log.debug("checking if peer key matches end-entity certificate");
             if (key->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) {
                 log.error("only the OpenSSL XSEC provider is supported");
                 continue;
index 1e81da0..a790bd7 100644 (file)
@@ -72,9 +72,12 @@ namespace xmltooling {
                 : BasicX509Credential(key, xseccerts), m_resolver(resolver) {
             initKeyInfo();
         }
-        virtual ~FilesystemCredential() {}
-        void attach(SSL_CTX* ctx) const;
+        virtual ~FilesystemCredential() {
+        }
 
+        void attach(SSL_CTX* ctx) const;
+    
+    private:
         FilesystemCredentialResolver* m_resolver;
     };
 
@@ -115,15 +118,14 @@ namespace xmltooling {
         bool matches(const CredentialCriteria* criteria) const {
             bool match = true;
             if (criteria) {
-                // See if algorithm is kosher.
                 const char* alg = criteria->getKeyAlgorithm();
                 if (alg && *alg) {
-                    match = false;
-                    for (vector<string>::const_iterator a = m_algorithms.begin(); a!=m_algorithms.end(); ++a) {
-                        if (strstr(alg, a->c_str()))
-                            match = true;
-                    }
+                    const char* alg2 = m_credential->getAlgorithm();
+                    if (alg2 && *alg2)
+                        match = XMLString::equals(alg,alg2);
                 }
+                if (match && criteria->getKeySize()>0 && m_credential->getKeySize()>0)
+                    match = (criteria->getKeySize() == m_credential->getKeySize());
                 if (match && m_credential->getPublicKey()) {
                     // See if we have to match a specific key.
                     auto_ptr<Credential> cred(
@@ -146,7 +148,6 @@ namespace xmltooling {
         string m_keypath,m_keypass;
         vector<X509*> m_certs;
         FilesystemCredential* m_credential;
-        vector<string> m_algorithms;
     };
 
     CredentialResolver* XMLTOOL_DLLLOCAL FilesystemCredentialResolverFactory(const DOMElement* const & e)
@@ -155,7 +156,6 @@ namespace xmltooling {
     }
 };
 
-static const XMLCh AlgorithmPrefix[] =  UNICODE_LITERAL_15(A,l,g,o,r,i,t,h,m,P,r,e,f,i,x);
 static const XMLCh CAPath[] =           UNICODE_LITERAL_6(C,A,P,a,t,h);
 static const XMLCh Certificate[] =      UNICODE_LITERAL_11(C,e,r,t,i,f,i,c,a,t,e);
 static const XMLCh format[] =           UNICODE_LITERAL_6(f,o,r,m,a,t);
@@ -171,21 +171,6 @@ FilesystemCredentialResolver::FilesystemCredentialResolver(const DOMElement* e)
     Category& log=Category::getInstance(XMLTOOLING_LOGCAT".CredentialResolver");
 
     const DOMElement* root=e;
-    e=XMLHelper::getFirstChildElement(root,AlgorithmPrefix);
-    while (e) {
-        if (e->hasChildNodes()) {
-            auto_ptr_char alg(e->getFirstChild()->getNodeValue());
-            if (alg.get())
-                m_algorithms.push_back(alg.get());
-        }
-        e=XMLHelper::getNextSiblingElement(e,AlgorithmPrefix);
-    }
-
-    if (m_algorithms.empty()) {
-        m_algorithms.push_back(URI_ID_SIG_BASE);
-        m_algorithms.push_back(URI_ID_SIG_BASEMORE);
-        m_algorithms.push_back("http://www.w3.org/2001/04/xmlenc#rsa");
-    }
 
     XSECCryptoKey* key=NULL;
     vector<XSECCryptoX509*> xseccerts;
index d26ccb8..a4d74e5 100644 (file)
@@ -52,7 +52,21 @@ namespace xmlsignature {
         static const XMLCh LOCAL_NAME[];
 
         /**
-         * Sets the canonicalization method for the ds:SignedInfo element
+         * Gets the canonicalization method for the ds:SignedInfo element.
+         * 
+         * @return the canonicalization method
+         */
+        virtual const XMLCh* getCanonicalizationMethod() const=0;
+        
+        /**
+         * Gets the signing algorithm for the signature.
+         * 
+         * @return    the signature algorithm
+         */
+        virtual const XMLCh* getSignatureAlgorithm() const=0;
+
+        /**
+         * Sets the canonicalization method for the ds:SignedInfo element.
          * 
          * @param c14n  the canonicalization method
          */
index 51a5119..57ab8bc 100644 (file)
@@ -61,7 +61,8 @@ namespace xmlsignature {
     class XMLTOOL_DLLLOCAL XMLSecSignatureImpl : public UnknownElementImpl, public virtual Signature
     {
     public:
-        XMLSecSignatureImpl() : UnknownElementImpl(XMLSIG_NS, Signature::LOCAL_NAME, XMLSIG_PREFIX),
+        XMLSecSignatureImpl() : AbstractXMLObject(XMLSIG_NS, Signature::LOCAL_NAME, XMLSIG_PREFIX),
+            UnknownElementImpl(XMLSIG_NS, Signature::LOCAL_NAME, XMLSIG_PREFIX),
             m_signature(NULL), m_c14n(NULL), m_sm(NULL), m_key(NULL), m_keyInfo(NULL), m_reference(NULL) {}
         virtual ~XMLSecSignatureImpl();
         
@@ -81,8 +82,21 @@ namespace xmlsignature {
         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; }
+        const XMLCh* getCanonicalizationMethod() const {
+            if (m_signature)
+                return canonicalizationMethod2UNICODEURI(m_signature->getCanonicalizationMethod());
+            return m_c14n ? m_c14n : DSIGConstants::s_unicodeStrURIEXC_C14N_NOC;
+        }
+        const XMLCh* getSignatureAlgorithm() const {
+            if (!m_sm && m_signature) {
+                safeBuffer sURI;
+                if (signatureHashMethod2URI(sURI, m_signature->getSignatureMethod(), m_signature->getHashMethod()) == false)
+                    return NULL;
+                m_sm = XMLString::replicate(sURI.sbStrToXMLCh());
+            }
+            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; }
@@ -108,7 +122,7 @@ namespace xmlsignature {
     private:
         mutable DSIGSignature* m_signature;
         XMLCh* m_c14n;
-        XMLCh* m_sm;
+        mutable XMLCh* m_sm;
         XSECCryptoKey* m_key;
         mutable KeyInfo* m_keyInfo;
         ContentReference* m_reference;
@@ -243,9 +257,10 @@ DOMElement* XMLSecSignatureImpl::marshall(DOMDocument* document, const vector<Si
             document=DOMImplementationRegistry::getDOMImplementation(NULL)->createDocument();
             bindDocument=true;
         }
-        m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature();
-        m_signature->setDSIGNSPrefix(XMLSIG_PREFIX);
-        cachedDOM=m_signature->createBlankSignature(document, getCanonicalizationMethod(), getSignatureAlgorithm());
+        DSIGSignature* temp=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature();
+        temp->setDSIGNSPrefix(XMLSIG_PREFIX);
+        cachedDOM=temp->createBlankSignature(document, getCanonicalizationMethod(), getSignatureAlgorithm());
+        m_signature = temp;
     }
     else {
         // We need to reparse the XML we saved off into a new DOM.
@@ -341,11 +356,10 @@ DOMElement* XMLSecSignatureImpl::marshall(DOMElement* parentElement, const vecto
     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(XMLSIG_PREFIX);
-        cachedDOM=m_signature->createBlankSignature(
-            parentElement->getOwnerDocument(), getCanonicalizationMethod(), getSignatureAlgorithm()
-            );
+        DSIGSignature* temp=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature();
+        temp->setDSIGNSPrefix(XMLSIG_PREFIX);
+        cachedDOM=temp->createBlankSignature(parentElement->getOwnerDocument(), getCanonicalizationMethod(), getSignatureAlgorithm());
+        m_signature = temp;
     }
     else {
         MemBufInputSource src(reinterpret_cast<const XMLByte*>(m_xml.c_str()),m_xml.length(),"XMLSecSignatureImpl");