Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
235 views
in Technique[技术] by (71.8m points)

c# - Malformed Reference Element

I am attempting to add References to my Security Header and am running into a fairly generic error:

Malformed Reference Element

I have tried the following with similar results:

  1. Referencing the element within the document by passing in the ID of the element as the URI of the Reference object.
  2. Passing an XmlElement object to the Reference through the LoadXml() method. I am retrieving the XmlElement reference by using the overloaded GetIdElement found on this StackOverflow post.

When I pass in an empty string as the URI, the ComputeSignature() method of the SignedXml works as expected. However, I need to add up to 3 references to the Security Header.

UPDATE #1
Thanks to this blog post, I was able to create the simplified version from that and I believe what is causing my problem is the use of the Namespace attributes and prefixes.

UPDATE #2
It appears as though the Namespace declaration on the Id attribute of the <Timestamp> element is causing this error to occur.

UPDATE #3
I think I got this working. See my answer post below.

Working Sample:
Please note the Id XAttribute with the Namespace defined does not work; while the Id XAttribute without the Namespace defined does work.

private void CreateSecurityAndTimestampXML(string fileName)
{
    TimestampID = "TS-E" + GUID.NewGuid();
    DateTime SecurityTimestampUTC = DateTime.UtcNow;

    XDocument xdoc = new XDocument(
        new XElement(wsse + "Security",
            new XAttribute(XNamespace.Xmlns + "wsse", wsse.NamespaceName),
            new XAttribute(XNamespace.Xmlns + "wsu", wsu.NamespaceName),
            new XElement(wsu + "Timestamp",
                // new XAttribute(wsu + "Id", TimestampID), // <-- Does Not Work
                new XAttribute("Id", TimestampID), // <-- Works
                new XElement(wsu + "Created", SecurityTimestampUTC.ToString(_timestampFormat)),
                new XElement(wsu + "Expires", SecurityTimestampUTC.AddMinutes(10).ToString(_timestampFormat))
            )
        )
    );

    using (XmlTextWriter tw = new XmlTextWriter(fileName, new UTF8Encoding(false)))
    {
        xdoc.WriteTo(tw);
    }
}

// Snippet
string[] elements = { TimestampID };

foreach (string s in elements)
{
    Reference reference = new Reference()
    {
        Uri = "#" + s
    };

    XmlDsigExcC14NTransform env = new XmlDsigExcC14NTransform();
    env.InclusiveNamespacesPrefixList = _includedPrefixList;
    reference.AddTransform(env);

    xSigned.AddReference(reference);
}

// Add Key Info Here.

// Compute the Signature.
xSigned.ComputeSignature();
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It looks like, at least for the time being, the answer to getting this working is as follows.

Instead of using the SignedXml class, create a new SignedXmlWithId object, using the class detailed here.

// Create a new XML Document.
XmlDocument xdoc = new XmlDocument();

xdoc.PreserveWhitespace = true;

// Load the passed XML File using its name.
xdoc.Load(new XmlTextReader(fileName));

// Create a SignedXml Object.
//SignedXml xSigned = new SignedXml(xdoc);
SignedXmlWithId xSigned = new SignedXmlWithId(xdoc); // Use this class instead of the SignedXml class above.

// Add the key to the SignedXml document.
xSigned.SigningKey = cert.PrivateKey;
xSigned.Signature.Id = SignatureID;
xSigned.SignedInfo.CanonicalizationMethod = 
        SignedXml.XmlDsigExcC14NWithCommentsTransformUrl;

//Initialize a variable to contain the ID of the Timestamp element.
string elementId = TimestampID;

Reference reference = new Reference()
{
    Uri = "#" + elementId
};

XmlDsigExcC14NTransform env = new XmlDsigExcC14NTransform();
env.InclusiveNamespacesPrefixList = _includedPrefixList;
reference.AddTransform(env);

xSigned.AddReference(reference);

// Add Key Information (omitted)

// Compute Signature
xSigned.ComputeSignature();

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...