使用SignedXml类添加基于Id属性的引用时,“格式错误的引用元素”

时间:2011-02-24 00:44:38

标签: c# xml soap cryptography xml-signature

当存在名称空间前缀时,无法通过Id属性对元素进行签名:

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()将因“格式错误的参考元素”而失败,应如何做到这一点?

4 个答案:

答案 0 :(得分:36)

我们使用的方法是继承System.Security.Cryptography.Xml.SignedXml类...

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;
    }
}

答案 1 :(得分:2)

var reference = new Reference(“”); //这将签署整个文件

答案 2 :(得分:2)

应该注意,您需要使用SignedXmlWithId对象而不是SignedXml对象才能使用重写的GetIdElement()方法。完成后,我就可以签署XmlElement并绕过格式错误的参考元素错误。

See my post about this topic here

答案 3 :(得分:0)

SignedXml无法将u:Id识别为有效的XML ID,并且XML签名确实要求它为XML ID。

如果您尝试使用WS-Security,可以使用Schema(http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd Id)或将DTD添加到XML片段。 (]&gt;用于XML片段)。只为你的LoadXml添加一个DTD会使SignedXml识别出Id,但由于SOAP不允许使用DTD,所以不要在你的在线SOAP中包含DTD。