不正确的引用元素签名 XML C#
Incorrect reference element signature XML C#
我需要实施 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="true"
为了在 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()
:
Incorrect reference element
你能帮我解决我的问题吗?
提前致谢!
托马斯!
我通过 SignedXml 和 Reference classes 对 XPointer 操作进行了逆向工程,并且..我可以在单独的答案中给你所有的细节,但我现在的结论是,你只能有两种类型查询数:
#xpointer(/)
之所以有效,是因为它已被明确检查,并且
#xpointer(id(
再次明确(使用 string.StartsWith)检查。
因此,正如您在评论中指出的那样,实现这一目标的唯一方法似乎是扩展 SignedXml class 并重写 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);
我需要实施 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="true"
为了在 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()
:
Incorrect reference element
你能帮我解决我的问题吗?
提前致谢!
托马斯!
我通过 SignedXml 和 Reference classes 对 XPointer 操作进行了逆向工程,并且..我可以在单独的答案中给你所有的细节,但我现在的结论是,你只能有两种类型查询数:
#xpointer(/)
之所以有效,是因为它已被明确检查,并且
#xpointer(id(
再次明确(使用 string.StartsWith)检查。
因此,正如您在评论中指出的那样,实现这一目标的唯一方法似乎是扩展 SignedXml class 并重写 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);