/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.
 */

/*
 * XSEC
 *
 * DSIGSignature := Class for checking and setting up signature nodes in a DSIG signature
 *
 * Author(s): Berin Lautenbach
 *
 * $Id$
 *
 */

// XSEC Includes
#include <xsec/dsig/DSIGSignature.hpp>
#include <xsec/dsig/DSIGConstants.hpp>
#include <xsec/dsig/DSIGKeyInfoX509.hpp>
#include <xsec/dsig/DSIGObject.hpp>
#include <xsec/dsig/DSIGReference.hpp>
#include <xsec/dsig/DSIGTransformList.hpp>
#include <xsec/dsig/DSIGKeyInfoValue.hpp>
#include <xsec/dsig/DSIGKeyInfoX509.hpp>
#include <xsec/dsig/DSIGKeyInfoName.hpp>
#include <xsec/dsig/DSIGKeyInfoPGPData.hpp>
#include <xsec/dsig/DSIGKeyInfoSPKIData.hpp>
#include <xsec/dsig/DSIGKeyInfoMgmtData.hpp>
#include <xsec/dsig/DSIGAlgorithmHandlerDefault.hpp>
#include <xsec/enc/XSECCryptoKeyDSA.hpp>
#include <xsec/enc/XSECCryptoKeyRSA.hpp>
#include <xsec/enc/XSECKeyInfoResolver.hpp>
#include <xsec/framework/XSECError.hpp>
#include <xsec/framework/XSECAlgorithmHandler.hpp>
#include <xsec/framework/XSECAlgorithmMapper.hpp>
#include <xsec/framework/XSECEnv.hpp>
#include <xsec/framework/XSECURIResolver.hpp>
#include <xsec/transformers/TXFMDocObject.hpp>
#include <xsec/transformers/TXFMOutputFile.hpp>
#include <xsec/transformers/TXFMBase64.hpp>
#include <xsec/transformers/TXFMC14n.hpp>
#include <xsec/transformers/TXFMChain.hpp>
#include <xsec/utils/XSECBinTXFMInputStream.hpp>
#include <xsec/utils/XSECDOMUtils.hpp>
#include <xsec/utils/XSECPlatformUtils.hpp>

#include "../utils/XSECAlgorithmSupport.hpp"

// Xerces includes

#include <xercesc/dom/DOMNamedNodeMap.hpp>
#include <xercesc/util/Janitor.hpp>

XERCES_CPP_NAMESPACE_USE

// --------------------------------------------------------------------------------
//           Init
// --------------------------------------------------------------------------------


void DSIGSignature::Initialise() {

    DSIGAlgorithmHandlerDefault def;

    // Register default signature algorithm handlers

    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIRSA_SHA1, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIRSA_MD5, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIRSA_SHA224, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIRSA_SHA256, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIRSA_SHA384, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIRSA_SHA512, def);

    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIDSA_SHA1, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIDSA_SHA256, def);

    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIECDSA_SHA1, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIECDSA_SHA224, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIECDSA_SHA256, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIECDSA_SHA384, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIECDSA_SHA512, def);

    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIHMAC_SHA1, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIHMAC_SHA224, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIHMAC_SHA256, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIHMAC_SHA384, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIHMAC_SHA512, def);

    // Register default hashing algorithm handlers

    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURISHA1, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURISHA224, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURISHA256, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURISHA384, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURISHA512, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIMD5, def);

}


// --------------------------------------------------------------------------------
//           Get the Canonicalised BYTE_STREAM of the SignedInfo
// --------------------------------------------------------------------------------

XSECBinTXFMInputStream* DSIGSignature::makeBinInputStream() const {

    TXFMBase* txfm;

    // Create the starting point for the transform list

    XSECnew(txfm, TXFMDocObject(mp_doc));

    TXFMChain* chain;
    XSECnew(chain, TXFMChain(txfm));
    Janitor<TXFMChain> j_chain(chain);

    ((TXFMDocObject*) txfm)->setInput(mp_doc, mp_signedInfo->getDOMNode());

    // canonicalize the SignedInfo content

    bool exclusive;
    bool comments;
    bool onedotone;
    if (XSECAlgorithmSupport::evalCanonicalizationMethod(mp_signedInfo->getCanonicalizationMethod(),
            exclusive, comments, onedotone)) {

        XSECnew(txfm, TXFMC14n(mp_doc));
        chain->appendTxfm(txfm);

        if (comments)
            txfm->activateComments();
        else
            txfm->stripComments();

        if (exclusive)
            ((TXFMC14n*) txfm)->setExclusive();

        if (onedotone)
            ((TXFMC14n*) txfm)->setInclusive11();

    } else {
        throw XSECException(XSECException::SigVfyError,
            "Unknown CanonicalizationMethod in DSIGSignature::makeBinInputStream()");
    }

    // Now create the InputStream

    XSECBinTXFMInputStream* ret = new XSECBinTXFMInputStream(chain);
    j_chain.release();

    return ret;
}


// --------------------------------------------------------------------------------
//           Get the list of references
// --------------------------------------------------------------------------------

DSIGReferenceList* DSIGSignature::getReferenceList() {
    return mp_signedInfo ? mp_signedInfo->getReferenceList() : NULL;
}

const DSIGReferenceList* DSIGSignature::getReferenceList() const {
    return mp_signedInfo ? mp_signedInfo->getReferenceList() : NULL;
}

const XMLCh* DSIGSignature::getAlgorithmURI() const {
    return mp_signedInfo ? mp_signedInfo->getAlgorithmURI() : NULL;
}

// --------------------------------------------------------------------------------
//           Set and Get Resolvers
// --------------------------------------------------------------------------------


void DSIGSignature::setURIResolver(XSECURIResolver* resolver) {
    mp_env->setURIResolver(resolver);
}

XSECURIResolver* DSIGSignature::getURIResolver() const {
    return mp_env->getURIResolver();
}

void DSIGSignature::setKeyInfoResolver(XSECKeyInfoResolver* resolver) {

    if (mp_KeyInfoResolver != 0)
        delete mp_KeyInfoResolver;

    mp_KeyInfoResolver = resolver->clone();
}

XSECKeyInfoResolver* DSIGSignature::getKeyInfoResolver() const {
    return mp_KeyInfoResolver;
}

// --------------------------------------------------------------------------------
//           Object Handling
// --------------------------------------------------------------------------------

DSIGObject* DSIGSignature::appendObject() {

    DSIGObject* ret;
    XSECnew(ret, DSIGObject(mp_env));
    DOMElement* elt = ret->createBlankObject();

    mp_sigNode->appendChild(elt);
    mp_env->doPrettyPrint(mp_sigNode);

    m_objects.push_back(ret);

    return ret;

}

int DSIGSignature::getObjectLength() const {
    return (unsigned int) m_objects.size();
}

DSIGObject* DSIGSignature::getObjectItem(int i) {

    if ( i < 0 || i >= ((int) m_objects.size())) {
        throw XSECException(XSECException::ObjectError,
            "DSIGSignature::getObjectItem - index out of range");
    }

    return m_objects[i];
}

const DSIGObject* DSIGSignature::getObjectItem(int i) const {

    if ( i < 0 || i >= ((int) m_objects.size())) {
        throw XSECException(XSECException::ObjectError,
            "DSIGSignature::getObjectItem - index out of range");
    }

    return m_objects[i];
}

// --------------------------------------------------------------------------------
//           Signature
// --------------------------------------------------------------------------------

// Constructors and Destructors

DSIGSignature::DSIGSignature(DOMDocument* doc, DOMNode* sigNode) :
        m_loaded(false),
        mp_doc(doc),
        mp_sigNode(sigNode),
        mp_signedInfo(NULL),
        mp_signatureValueNode(NULL),
        m_keyInfoList(NULL),
        mp_KeyInfoNode(NULL),
        m_errStr(""),
        mp_signingKey(NULL),
        mp_KeyInfoResolver(NULL),
        m_interlockingReferences(false) {

    // Set up our formatter
    XSECnew(mp_formatter, XSECSafeBufferFormatter("UTF-8",XMLFormatter::NoEscapes,
                                                XMLFormatter::UnRep_CharRef));

    // Set up the environment
    XSECnew(mp_env, XSECEnv(doc));

    m_keyInfoList.setEnvironment(mp_env);
}

DSIGSignature::DSIGSignature() :
        m_loaded(false),
        mp_doc(NULL),
        mp_sigNode(NULL),
        mp_signedInfo(NULL),
        mp_signatureValueNode(NULL),
        m_keyInfoList(NULL),
        mp_KeyInfoNode(NULL),
        m_errStr(""),
        mp_signingKey(NULL),
        mp_KeyInfoResolver(NULL),
        m_interlockingReferences(false) {

    // Set up our formatter
    XSECnew(mp_formatter, XSECSafeBufferFormatter("UTF-8",XMLFormatter::NoEscapes,
                                                XMLFormatter::UnRep_CharRef));

    XSECnew(mp_env, XSECEnv(NULL));

    m_keyInfoList.setEnvironment(mp_env);
}

DSIGSignature::~DSIGSignature() {

    if (mp_env != NULL)
        delete mp_env;

    if (mp_signingKey != NULL) {

        delete mp_signingKey;
        mp_signingKey = NULL;

    }

    if (mp_signedInfo != NULL) {

        delete mp_signedInfo;
        mp_signedInfo = NULL;

    }

    if (mp_formatter != NULL) {

        delete mp_formatter;
        mp_formatter = NULL;
    }

    if (mp_KeyInfoResolver != NULL) {
        delete mp_KeyInfoResolver;
        mp_KeyInfoResolver = NULL;
    }

    // Delete any object items
    for (int i = 0; i < ((int) m_objects.size()); ++i) {
        delete (m_objects[i]);
    }
}

// Actions

const XMLCh* DSIGSignature::getErrMsgs() const {
    return m_errStr.rawXMLChBuffer();
}

// --------------------------------------------------------------------------------
//           Pretty Printing
// --------------------------------------------------------------------------------

void DSIGSignature::setPrettyPrint(bool flag) {
    mp_env->setPrettyPrintFlag(flag);
}


bool DSIGSignature::getPrettyPrint() const {
    return mp_env->getPrettyPrintFlag();
}

// --------------------------------------------------------------------------------
//           Creating signatures from blank
// --------------------------------------------------------------------------------

void DSIGSignature::setDSIGNSPrefix(const XMLCh* prefix) {
    mp_env->setDSIGNSPrefix(prefix);
}

void DSIGSignature::setECNSPrefix(const XMLCh* prefix) {
    mp_env->setECNSPrefix(prefix);
}

void DSIGSignature::setXPFNSPrefix(const XMLCh* prefix) {
    mp_env->setXPFNSPrefix(prefix);
}

// get

const XMLCh* DSIGSignature::getDSIGNSPrefix() const {
    return mp_env->getDSIGNSPrefix();
}


const XMLCh* DSIGSignature::getECNSPrefix() const {
    return mp_env->getECNSPrefix();
}

const XMLCh* DSIGSignature::getXPFNSPrefix() const {
    return mp_env->getXPFNSPrefix();
}

DOMElement*DSIGSignature::createBlankSignature(
        DOMDocument* doc,
        const XMLCh* canonicalizationAlgorithmURI,
        const XMLCh* signatureAlgorithmURI) {

    // "New" method to create a blank signature, based on URIs.

    mp_doc = doc;
    mp_env->setParentDocument(doc);

    const XMLCh* prefixNS = mp_env->getDSIGNSPrefix();

    safeBuffer str;

    makeQName(str, prefixNS, "Signature");

    DOMElement*sigNode = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());

    if (prefixNS[0] == '\0') {
        str.sbTranscodeIn("xmlns");
    }
    else {
        str.sbTranscodeIn("xmlns:");
        str.sbXMLChCat(prefixNS);
    }

    sigNode->setAttributeNS(DSIGConstants::s_unicodeStrURIXMLNS,
                            str.rawXMLChBuffer(),
                            DSIGConstants::s_unicodeStrURIDSIG);

    mp_sigNode = sigNode;

    mp_env->doPrettyPrint(mp_sigNode);

    // Create the skeleton SignedInfo
    XSECnew(mp_signedInfo, DSIGSignedInfo(mp_doc, mp_formatter, mp_env));

    mp_sigNode->appendChild(mp_signedInfo->createBlankSignedInfo(
        canonicalizationAlgorithmURI, signatureAlgorithmURI));
    mp_env->doPrettyPrint(mp_sigNode);

    // Create a dummy signature value (dummy until signed)

    makeQName(str, mp_env->getDSIGNSPrefix(), "SignatureValue");
    DOMElement*sigValNode = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG,
                                                  str.rawXMLChBuffer());
    mp_signatureValueNode = sigValNode;
    mp_sigNode->appendChild(sigValNode);
    mp_env->doPrettyPrint(mp_sigNode);

    // Some text to mark this as a template only
    sigValNode->appendChild(doc->createTextNode(MAKE_UNICODE_STRING("Not yet signed")));

    m_loaded = true;

    return sigNode;
}



// --------------------------------------------------------------------------------
//           Creating References
// --------------------------------------------------------------------------------

DSIGReference* DSIGSignature::createReference(
        const XMLCh* URI,
        const XMLCh* hashAlgorithmURI,
        const XMLCh* type) {

    return mp_signedInfo->createReference(URI, hashAlgorithmURI, type);
}

DSIGReference* DSIGSignature::removeReference(DSIGReferenceList::size_type index) {
    return mp_signedInfo ? mp_signedInfo->removeReference(index) : NULL;
}

// --------------------------------------------------------------------------------
//           Manipulation of KeyInfo elements
// --------------------------------------------------------------------------------

void DSIGSignature::clearKeyInfo() {

    if (mp_KeyInfoNode == 0)
        return;

    if (mp_sigNode->removeChild(mp_KeyInfoNode) != mp_KeyInfoNode) {

        throw XSECException(XSECException::ExpectedDSIGChildNotFound,
            "Attempted to remove KeyInfo node but it is no longer a child of <Signature>");

    }

    mp_KeyInfoNode->release();        // No longer required

    mp_KeyInfoNode = NULL;

    // Clear out the list
    m_keyInfoList.empty();

}

void DSIGSignature::createKeyInfoElement() {

    if (mp_KeyInfoNode != NULL)
        return;

    safeBuffer str;

    makeQName(str, mp_env->getDSIGNSPrefix(), "KeyInfo");

    mp_KeyInfoNode = m_keyInfoList.createKeyInfo();

    // Append the node to the end of the signature

    DOMNode* afterSignatureValue = mp_signatureValueNode->getNextSibling();
    while (afterSignatureValue != 0 && afterSignatureValue->getNodeType() != DOMNode::ELEMENT_NODE)
        afterSignatureValue = afterSignatureValue->getNextSibling();

    if (afterSignatureValue == 0) {
        mp_sigNode->appendChild(mp_KeyInfoNode);
        mp_env->doPrettyPrint(mp_sigNode);
    }
    else {
        mp_sigNode->insertBefore(mp_KeyInfoNode, afterSignatureValue);
        if (mp_env->getPrettyPrintFlag() == true)
            mp_sigNode->insertBefore(mp_doc->createTextNode(DSIGConstants::s_unicodeStrNL),
                afterSignatureValue);
    }
}

DSIGKeyInfoValue* DSIGSignature::appendDSAKeyValue(const XMLCh* P,
                           const XMLCh* Q,
                           const XMLCh* G,
                           const XMLCh* Y) {

    createKeyInfoElement();
    return m_keyInfoList.appendDSAKeyValue(P, Q, G, Y);
}

DSIGKeyInfoValue* DSIGSignature::appendRSAKeyValue(const XMLCh* modulus,
                           const XMLCh* exponent) {

    createKeyInfoElement();
    return m_keyInfoList.appendRSAKeyValue(modulus, exponent);
}


DSIGKeyInfoX509* DSIGSignature::appendX509Data() {

    createKeyInfoElement();
    return m_keyInfoList.appendX509Data();
}

DSIGKeyInfoName* DSIGSignature::appendKeyName(const XMLCh* name, bool isDName) {

    createKeyInfoElement();
    return m_keyInfoList.appendKeyName(name, isDName);
}

DSIGKeyInfoPGPData* DSIGSignature::appendPGPData(const XMLCh* id, const XMLCh* packet) {

    createKeyInfoElement();
    return m_keyInfoList.appendPGPData(id, packet);
}

DSIGKeyInfoSPKIData* DSIGSignature::appendSPKIData(const XMLCh* sexp) {

    createKeyInfoElement();
    return m_keyInfoList.appendSPKIData(sexp);
}

DSIGKeyInfoMgmtData* DSIGSignature::appendMgmtData(const XMLCh* data) {

    createKeyInfoElement();
    return m_keyInfoList.appendMgmtData(data);
}

// --------------------------------------------------------------------------------
//           Working on Existing templates
// --------------------------------------------------------------------------------


void DSIGSignature::load() {

    // Load all the information from the source document into local variables for easier
    // manipulation by the other functions in the class

    if (mp_sigNode == NULL) {

        // Attempt to load an empty signature element
        throw XSECException(XSECException::LoadEmptySignature);

    }

    if (!strEquals(getDSIGLocalName(mp_sigNode), "Signature")) {

        throw XSECException(XSECException::LoadNonSignature);

    }

    m_loaded = true;

    // Find the prefix being used so that we can later use it to manipulate the signature
    mp_env->setDSIGNSPrefix(mp_sigNode->getPrefix());

    // Now check for SignedInfo
    DOMNode*tmpElt = mp_sigNode->getFirstChild();

    while (tmpElt != 0 && (tmpElt->getNodeType() != DOMNode::ELEMENT_NODE))
        // Skip text and comments
        tmpElt = tmpElt->getNextSibling();

    if (tmpElt == 0 || !strEquals(getDSIGLocalName(tmpElt), "SignedInfo")) {

            throw XSECException(XSECException::ExpectedDSIGChildNotFound,
                    "Expected <SignedInfo> as first child of <Signature>");

    }

    // Have a signed info

    XSECnew(mp_signedInfo, DSIGSignedInfo(mp_doc, mp_formatter, tmpElt, mp_env));
    mp_signedInfo->load();

    // Look at Signature Value
    tmpElt = findNextElementChild(tmpElt);
    if (tmpElt == 0 || !strEquals(getDSIGLocalName(tmpElt), "SignatureValue")) {

        throw XSECException(XSECException::ExpectedDSIGChildNotFound,
            "Expected <SignatureValue> node");

    }

    DOMNode*tmpSV = tmpElt->getFirstChild();
    while (tmpSV != 0 && tmpSV->getNodeType() != DOMNode::TEXT_NODE)
        tmpSV = tmpSV->getNextSibling();

    if (tmpSV == 0)
        throw XSECException(XSECException::ExpectedDSIGChildNotFound,
        "Expected TEXT child of <SignatureValue>");

    mp_signatureValueNode = tmpElt;

    // The signature value is transcoded to local code page, as it is easier
    // to work with, and should be low ASCII in any case (Base64)

    m_signatureValueSB.sbTranscodeIn(tmpSV->getNodeValue());


    // Now look at KeyInfo
    tmpElt = findNextElementChild(tmpElt);

    if (tmpElt != 0 && strEquals(getDSIGLocalName(tmpElt), "KeyInfo")) {

        // Have a keyInfo

        mp_KeyInfoNode = tmpElt;        // In case we later want to manipulate it

        m_keyInfoList.loadListFromXML(tmpElt);

        tmpElt = findNextElementChild(tmpElt);
    }

    while (tmpElt != 0 && strEquals(getDSIGLocalName(tmpElt), "Object")) {

        DSIGObject* obj;
        XSECnew(obj, DSIGObject(mp_env, tmpElt));
        obj->load();

        m_objects.push_back(obj);

        tmpElt = findNextElementChild(tmpElt);

    }
/*
    * Strictly speaking, this should remain, but it causes too many problems with non
    * conforming signatures

    if (tmpElt != 0) {
        throw XSECException(XSECException::ExpectedDSIGChildNotFound,
            "DSIGSignature::load - Unexpected (non Object) Element found at end of signature");
    }
*/
}

TXFMChain* DSIGSignature::getSignedInfoInput() const {

    TXFMBase* txfm;
    TXFMChain* chain;

    // First we calculate the hash.  Start off by creating a starting point
    XSECnew(txfm, TXFMDocObject(mp_doc));
    XSECnew(chain, TXFMChain(txfm));
    Janitor<TXFMChain> j_chain(chain);

    ((TXFMDocObject*) txfm)->setInput(mp_doc, mp_signedInfo->getDOMNode());

    // canonicalise the SignedInfo content

    bool exclusive;
    bool comments;
    bool onedotone;
    if (XSECAlgorithmSupport::evalCanonicalizationMethod(mp_signedInfo->getCanonicalizationMethod(),
            exclusive, comments, onedotone)) {

        XSECnew(txfm, TXFMC14n(mp_doc));
        chain->appendTxfm(txfm);

        if (comments)
            txfm->activateComments();
        else
            txfm->stripComments();

        if (exclusive)
            ((TXFMC14n*) txfm)->setExclusive();

        if (onedotone)
            ((TXFMC14n*) txfm)->setInclusive11();

    } else {
        throw XSECException(XSECException::SigVfyError,
            "Unknown CanonicalizationMethod in DSIGSignature::calculateSignedInfoHash()");
    }

    j_chain.release();
    return chain;
}

unsigned int DSIGSignature::calculateSignedInfoHash(unsigned char* hashBuf,
                                                    unsigned int hashBufLen) const {

    // Get the SignedInfo input bytes
    TXFMChain* chain = getSignedInfoInput();
    Janitor<TXFMChain> j_chain(chain);

    // Check for debugging sink for the data
    TXFMBase* sink = XSECPlatformUtils::GetReferenceLoggingSink(mp_doc);
    if (sink)
        chain->appendTxfm(sink);

    // Setup Hash
    // First find the appropriate handler for the URI
    XSECAlgorithmHandler* handler =
        XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(
                    mp_signedInfo->getAlgorithmURI());

    if (handler == NULL) {
        throw XSECException(XSECException::SigVfyError,
            "Hash method unknown in DSIGSignature::calculateSignedInfoHash()");
    }

    if (!handler->appendSignatureHashTxfm(chain, mp_signedInfo->getAlgorithmURI(), mp_signingKey)) {
        throw XSECException(XSECException::SigVfyError,
            "Unexpected error in handler whilst appending Signature Hash transform");
    }


    // Write hash to the buffer
    return chain->getLastTxfm()->readBytes((XMLByte*) hashBuf, hashBufLen);
}

unsigned int DSIGSignature::calculateSignedInfoAndReferenceHash(unsigned char* hashBuf,
                                                    unsigned int hashBufLen) const {

    // Set up the reference list hashes - including any manifests
    mp_signedInfo->hash(m_interlockingReferences);
    // calculaet signed InfoHash
    return calculateSignedInfoHash(hashBuf,hashBufLen);
}

// --------------------------------------------------------------------------------
//           Verify a signature
// --------------------------------------------------------------------------------

bool DSIGSignature::verifySignatureOnlyInternal() const {

    unsigned char hash[4096];

    if (!m_loaded) {

        // Need to call "load" prior to checking a signature
        throw XSECException(XSECException::SigVfyError,
                    "DSIGSignature::verify() called prior to DSIGSignature::load()");

    }

    // FIX: CVE-2009-0217

    if (mp_signedInfo->getHMACOutputLength() > 0 && mp_signedInfo->getHMACOutputLength() < 80) {
        throw XSECException(XSECException::SigVfyError,
            "DSIGSignature::verify() - HMACOutputLength is unsafe");
    }

    // Try to find a key
    if (mp_signingKey == NULL) {

//        // Try to load a key from the KeyInfo list
//        if ((mp_signingKey = m_keyInfoList.findKey()) == NULL) {

//            throw XSECException(XSECException::SigVfyError,
//                "DSIGSignature::verify() - no verification key loaded and cannot determine from KeyInfo list");
//        }

        if (mp_KeyInfoResolver == NULL) {

            throw XSECException(XSECException::SigVfyError,
                "DSIGSignature::verify() - no verification key loaded and no KeyInfoResolver loaded");

        }

        if ((mp_signingKey = mp_KeyInfoResolver->resolveKey(&m_keyInfoList)) == NULL) {

            throw XSECException(XSECException::SigVfyError,
                "DSIGSignature::verify() - no verification key loaded and cannot determine from KeyInfoResolver");
        }

    }

    // Get the SignedInfo input bytes
    TXFMChain* chain = getSignedInfoInput();
    Janitor<TXFMChain> j_chain(chain);

    calculateSignedInfoHash(hash, 4096);

    // Now set up to verify
    // First find the appropriate handler for the URI
    XSECAlgorithmHandler* handler =
        XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(
                    mp_signedInfo->getAlgorithmURI());

    if (handler == NULL) {

        throw XSECException(XSECException::SigVfyError,
            "Hash method unknown in DSIGSignature::verifySignatureOnlyInternal()");

    }

    bool sigVfyRet = handler->verifyBase64Signature(chain,
        mp_signedInfo->getAlgorithmURI(),
        m_signatureValueSB.rawCharBuffer(),
        mp_signedInfo->getHMACOutputLength(),
        mp_signingKey);

    if (!sigVfyRet)
        m_errStr.sbXMLChCat("Validation of <SignedInfo> failed");

    return sigVfyRet;
}

bool DSIGSignature::verifySignatureOnly() const {
    m_errStr.sbTranscodeIn("");
    return verifySignatureOnlyInternal();
}

bool DSIGSignature::verify() const {

    // We have a (hopefully) fully loaded signature.  Need to
    // verify

    bool referenceCheckResult;

    if (!m_loaded) {

        // Need to call "load" prior to checking a signature
        throw XSECException(XSECException::SigVfyError,
                    "DSIGSignature::verify() called prior to DSIGSignature::load()");

    }

    // Reset
    m_errStr.sbXMLChIn(DSIGConstants::s_unicodeStrEmpty);

    // First thing to do is check the references

    referenceCheckResult = mp_signedInfo->verify(m_errStr);

    // Check the signature

    bool sigVfyResult = verifySignatureOnlyInternal();

    return sigVfyResult & referenceCheckResult;
}

// --------------------------------------------------------------------------------
//           Sign the XML document that has been previously loaded
// --------------------------------------------------------------------------------

void DSIGSignature::sign() {

    // We have a (hopefully) fully loaded signature.  Need to
    // sign

    if (!m_loaded) {

        // Need to call "load" prior to checking a signature
        throw XSECException(XSECException::SigVfyError,
                    "DSIGSignature::sign() called prior to DSIGSignature::load()");

    }

    // Check we have a key
    if (mp_signingKey == NULL) {

        throw XSECException(XSECException::SigVfyError,
            "DSIGSignature::sign() - no signing key loaded");


    }

    // Reset error string in case we have any reference problems.
    m_errStr.sbXMLChIn(DSIGConstants::s_unicodeStrEmpty);

    // Set up the reference list hashes - including any manifests
    mp_signedInfo->hash(m_interlockingReferences);

    // Get the SignedInfo input bytes
    TXFMChain* chain = getSignedInfoInput();
    Janitor<TXFMChain> j_chain(chain);

    // Calculate the hash to be signed

    safeBuffer b64Buf;

    XSECAlgorithmHandler* handler =
        XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(
                    mp_signedInfo->getAlgorithmURI());

    if (handler == NULL) {


        throw XSECException(XSECException::SigVfyError,
            "Hash method unknown in DSIGSignature::sign()");

    }

    if (!handler->signToSafeBuffer(chain, mp_signedInfo->getAlgorithmURI(),
                                   mp_signingKey, mp_signedInfo->getHMACOutputLength(), b64Buf)) {

        throw XSECException(XSECException::SigVfyError,
            "Unexpected error in handler whilst appending Signature Hash transform");

    }

    // Now we have the signature - place it in the DOM structures

    DOMNode*tmpElt = mp_signatureValueNode->getFirstChild();

    while (tmpElt != NULL && tmpElt->getNodeType() != DOMNode::TEXT_NODE)
        tmpElt = tmpElt->getNextSibling();

    if (tmpElt == NULL) {
        // Need to create the underlying TEXT_NODE
        DOMDocument* doc = mp_signatureValueNode->getOwnerDocument();
        tmpElt = doc->createTextNode(b64Buf.sbStrToXMLCh());
        mp_signatureValueNode->appendChild(tmpElt);
    }
    else {
        tmpElt->setNodeValue(b64Buf.sbStrToXMLCh());
    }

    // And copy to the local buffer
    m_signatureValueSB = b64Buf;
}

// --------------------------------------------------------------------------------
//           Key Management
// --------------------------------------------------------------------------------

void DSIGSignature::setSigningKey(XSECCryptoKey* k) {

    if (mp_signingKey != NULL)
        delete mp_signingKey;

    mp_signingKey = k;
}

// --------------------------------------------------------------------------------
//           ID Handling
// --------------------------------------------------------------------------------

/*
 * ID handling is really all done within the environment object - just pass the
 * calls straight through
 */

void DSIGSignature::setIdByAttributeName(bool flag) {
    mp_env->setIdByAttributeName(flag);
}

bool DSIGSignature::getIdByAttributeName() const {
    return mp_env->getIdByAttributeName();
}


void DSIGSignature::registerIdAttributeName(const XMLCh* name) {
    mp_env->registerIdAttributeName(name);
}

bool DSIGSignature::deregisterIdAttributeName(const XMLCh* name) {
    return mp_env->deregisterIdAttributeName(name);
}

void DSIGSignature::registerIdAttributeNameNS(const XMLCh* ns, const XMLCh* name) {
    mp_env->registerIdAttributeNameNS(ns, name);
}

bool DSIGSignature::deregisterIdAttributeNameNS(const XMLCh* ns, const XMLCh* name) {
    return mp_env->deregisterIdAttributeNameNS(ns, name);
}

// --------------------------------------------------------------------------------
//           Other functions
// --------------------------------------------------------------------------------

const XMLCh* DSIGSignature::getSignatureValue() const {

    if (mp_signatureValueNode == NULL)
        return NULL;

    return findFirstChildOfType(mp_signatureValueNode, DOMNode::TEXT_NODE)->getNodeValue();
}
