Dog Ears
Dog Ears

Reputation: 10005

'Malformed Reference Element' when adding a reference based on an Id attribute with SignedXml class

Unable to sign element by Id attribute when there's a namespace prefix:

void Main()
{
    var doc = new XmlDocument();
    doc.LoadXml("<root xmlns:u=\"myuri\"><test u:Id=\"_0\">Zebra</test></root>");

    SignedXml signedXml = new SignedXml(doc);
    signedXml.SigningKey = new RSACryptoServiceProvider();

    Reference reference = new Reference("#_0");
    signedXml.AddReference(reference);

    signedXml.ComputeSignature();
}

ComputeSignature() will fail here with 'Malformed Reference Element' how should this be done?

Upvotes: 28

Views: 26909

Answers (4)

Russ
Russ

Reputation: 712

It should be noted that you will need to use SignedXmlWithId object instead of SignedXml object in order to be able to use the overridden GetIdElement() method. Once I did that, I was able to sign an XmlElement and get around the Malformed Reference Element error.

See my post about this topic here.

Upvotes: 2

Dog Ears
Dog Ears

Reputation: 10005

The approach we used was to subclass System.Security.Cryptography.Xml.SignedXml class...

public class SignedXmlWithId : SignedXml
{
    public SignedXmlWithId(XmlDocument xml) : base(xml)
    {
    }

    public SignedXmlWithId(XmlElement xmlElement) 
        : base(xmlElement)
    {       
    }

    public override XmlElement GetIdElement(XmlDocument doc, string id)
    {
        // check to see if it's a standard ID reference
        XmlElement idElem = base.GetIdElement(doc, id);

        if (idElem == null)
        {
            XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable);
            nsManager.AddNamespace("wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");

            idElem = doc.SelectSingleNode("//*[@wsu:Id=\"" + id + "\"]", nsManager) as XmlElement;
        }

        return idElem;
    }
}

Upvotes: 61

Marc de Graauw
Marc de Graauw

Reputation: 1

SignedXml does not recognize u:Id as a valid XML ID, and the XML Signature does require it to be an XML ID.

You can either use the Schema (http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd if your trying to use a WS-Security Id) or add an DTD to the XML fragment. ( ]> for an XML fragment). Adding a DTD to just your LoadXml will make SignedXml recognize the Id, but since SOAP does not allow DTD's, don't include the DTD in your on-the-wire SOAP.

Upvotes: 0

Richard Schneider
Richard Schneider

Reputation: 35477

var reference = new Reference(""); // This will sign the entire document

Upvotes: 3

Related Questions