参考元素签名XML C#不正确

时间:2015-11-13 10:32:35

标签: c# xml signature xml-signature

我需要实现EBICS协议,特别是HPB请求,我需要签署我的XML文件:

    <?xml version="1.0" encoding="UTF-8"?>
<ebicsNoPubKeyDigestsRequest xmlns="http://www.ebics.org/H003" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.ebics.org/H003 http://www.ebics.org/H003/ebics_keymgmt_request.xsd" Version="H003" Revision="1">
  <header authenticate="true">
    <static>
      <HostID>EBIXQUAL</HostID>
      <Nonce>234AB2340FD2C23035764578FF3091C1</Nonce>
      <Timestamp>2015-11-13T10:32:30.123Z</Timestamp>
      <PartnerID>AD598</PartnerID>
      <UserID>EF056</UserID>
      <OrderDetails>
        <OrderType>HPB</OrderType>
        <OrderAttribute>DZHNN</OrderAttribute>
      </OrderDetails>
      <SecurityMedium>0000</SecurityMedium>
    </static>
    <mutable />
  </header>
</ebicsNoPubKeyDigestsRequest>

所以我需要签署

的元素
  

的authenticate = “真”

要在C#中签署我的文档,我写了这段代码:

XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.PreserveWhitespace = false;
        xmlDoc.Load("hpbtest.xml");
        RSA Key = new GestionCertificat("CN=XML_ENC_TEST_CERT4").getClePrivee();
        // Create a SignedXml object.
        SignedXml signedXml = new SignedXml(xmlDoc);
        // Add the key to the SignedXml document.
        signedXml.SigningKey = Key;
        // Create a reference to be signed.
        Reference reference = new Reference();
        reference.Uri = "#xpointer(//*[@authenticate='true'])";
        // Add an enveloped transformation to the reference.
        XmlDsigExcC14NTransform env = new XmlDsigExcC14NTransform();
        reference.AddTransform(env);
        // Add the reference to the SignedXml object.
        signedXml.AddReference(reference);
        // Compute the signature.
        signedXml.ComputeSignature();
        // Get the XML representation of the signature and save
        // it to an XmlElement object.
        XmlElement xmlDigitalSignature = signedXml.GetXml();
        // Append the element to the XML document.
        xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));
        xmlDoc.Save("hpbtest.xml");

但是当我尝试签名时,我在网上得到了这个错误

  

signedXml.ComputeSignature()

  

参考元素

不正确
你能帮我解决一下我的问题吗?

提前谢谢!

托马斯!

1 个答案:

答案 0 :(得分:1)

我通过SignedXml和Reference类反向设计XPointer操作。我可以在单独的答案中给你所有细节,但我现在得出的结论是,你只能有两种类型的查询:

#xpointer(/)

这是有效的,因为它是明确检查的,并且

#xpointer(id(

再次明确地(使用string.StartsWith)检查。

因此,正如您在注释中指出的那样,实现此目的的唯一方法似乎是扩展SignedXml类并覆盖GetIdElement方法,如下所示:

public class CustomSignedXml : SignedXml
{
    XmlDocument xmlDocumentToSign;

    public CustomSignedXml(XmlDocument xmlDocument) : base(xmlDocument)
    {
        xmlDocumentToSign = xmlDocument;
    }

    public override XmlElement GetIdElement(XmlDocument document, string idValue)
    {
        XmlElement matchingElement = null;
        try
        {
            matchingElement = base.GetIdElement(document, idValue);
        }
        catch (Exception idElementException)
        {
            Trace.TraceError(idElementException.ToString());
        }

        if (matchingElement == null)
        {
            // at this point, idValue = xpointer(//*[@authenticate='true'])
            string customXPath = idValue.TrimEnd(')');
            customXPath = customXPath.Substring(customXPath.IndexOf('(') + 1);
            matchingElement = xmlDocumentToSign.SelectSingleNode(customXPath) as XmlElement;
        }

        return matchingElement;
    }
}

然后在使用者代码中,只需将SignedXml更改为CustomSignedXml:

CustomSignedXml signedXml = new CustomSignedXml(xmlDoc);