c# - 使用 Sha256 RSA 验证 SignatureValue 和 DigestValue
问题描述
我正在尝试验证我收到的用于 C# 验证的数据。
这是我拥有的 XML,
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Response xmlns="http://www.site.ae/abc">
<Message xml:id="message">
<Header>
<SomeDate>SomValue</SomeDate>
</Header>
<Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="SomeDataType">
<SomeStatus>Success</SomeStatus>
</Body>
</Message>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<Reference URI="#message">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<DigestValue>XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX
</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</Response>
我正在使用下面的 C# 代码来验证上面的代码,
var signature = @"
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
var data = @"
<Header>
<SomeDate>SomValue</SomeDate>
</Header>
<Body xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:type=""SomeDataType"">
<SomeStatus>Success</SomeStatus>
</Body>";
var digest = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
var x509Data = @"
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX";
byte[] SignatureValueBytes = Convert.FromBase64String(signature);
byte[] x509DataBytes = Convert.FromBase64String(x509Data);
byte[] DigestValueBytes = Convert.FromBase64String(digest);
var cert = new System.Security.Cryptography.X509Certificates.X509Certificate2(x509DataBytes);
using (var rsa = System.Security.Cryptography.X509Certificates.RSACertificateExtensions.GetRSAPublicKey(cert))
{
bool a = rsa.VerifyHash(DigestValueBytes, SignatureValueBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
}
但是上面的代码无法验证。我错过了什么?这是空格问题吗?
解决方案
XML 签名的创建,即 XML 文档 ( XMLDSig ) 的签名,比普通签名的创建更复杂,因为同一个 XML 可以不同地序列化,即不同的序列化在逻辑上是相同的。因此,必须事先对 XML 进行规范化,即转换为唯一的格式(Canonicalization)。同样,这同样适用于验证。
.NET 在很大程度上封装了这些过程。因此,签名比验证更复杂,因为对于后者,参数(例如规范化变体)包含在签名的 XML 中。
在问题中发布的签名 XML 中,已嵌入用于验证的密钥(即证书)。在这种情况下,验证的可能实现是:
using System;
using System.Xml;
using System.Security.Cryptography.Xml;
public class VerifyTest
{
private static String signedXml =
@"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""no""?>
<Response xmlns=""http://www.site.ae/abc"">
<Message id=""message"">
<Header>
<SomeDate>SomValue</SomeDate>
</Header>
<Body xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:type=""SomeDataType"">
<SomeStatus>Success</SomeStatus>
</Body>
</Message>
<Signature xmlns=""http://www.w3.org/2000/09/xmldsig#"">
<SignedInfo>
<CanonicalizationMethod Algorithm=""http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments""/>
<SignatureMethod Algorithm=""http://www.w3.org/2001/04/xmldsig-more#rsa-sha256""/>
<Reference URI=""#message"">
<Transforms>
<Transform Algorithm=""http://www.w3.org/2000/09/xmldsig#enveloped-signature""/>
</Transforms>
<DigestMethod Algorithm=""http://www.w3.org/2001/04/xmlenc#sha256""/>
<DigestValue>hXuAfCAwKQIH1lGErMom2yO//25Pbyn1eXEmcEL1Rtk=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>izFP8eyDkG+9mDF2mAFl66174gpYbBzbcPPc/kDMjRm4TFnZdMAITLe60EPqdQAKK61A6FW8ZQrCkbbiBk/PRd8WaAxgAxjnMU8/U6gYUI6pk2LAANMquguYs7NQjURf7QFr1M1s7F1OrDDVlJiy2ZK3f0yLPoJstA+tnSbjYTQNlYP2qqzGARDkuEXZELSeCjXfA6M2gcGv7EsAv3GtgC2wR3GaVnnfLcieC+8bB9PJwkUtS3P/nmZuvezq/nBvZ/VsIgVjD/rLZX3rAxtVmhRj4d2ykGomnTBU0UJJtcIJyL3UJaQssr1U8YpSA5yWMfJ1uYUCZrGfh7OsHst/qrxeNwO0tGWAdsbD5MWYIwJzHAFcBTrNB0c6g1ehZwihBJWST2YJZvo3xV4UEO4++MhgsP0NHI8fPeBTZRx/vIN7quiJ21YxumUSwA5o8t4Rg9SSOthpnEbfyrSRntlSe8U28EdT0aNVL5gG/N5Qf3eW7XYHjJ2gxv8llMG6UcTY3ck48sW7f+ODatJ5Uk6GALFRjGgrdDlIBgImEormswDmwXSF46XoQVnEH2bR89Yd7g5GlzWQC+Fr5Q2vgVJ/ufS/85URVDr/KFYiJCzzmCEFdZWPR0zrOF/1GDbdAx0s8Zu3Sbq1ERMbdEQqxHs3N0NhdtVtYu96AXXnj5Azg3Y=</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>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</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</Response>";
public static void Main(String[] args)
{
// Print XML document
Console.WriteLine(VerifyTest.signedXml);
// Load signed XML document
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(VerifyTest.signedXml);
// Verify
SignedXml signedXml = new SignedXml(xmlDoc);
XmlNodeList nodeList = xmlDoc.GetElementsByTagName("Signature");
signedXml.LoadXml((XmlElement)nodeList[0]);
bool verified = signedXml.CheckSignature();
Console.WriteLine(new string('-', 100) + "\nVerified: " + verified);
}
}
代码中包含的签名 XML 基于您发布的示例,我使用私有测试密钥对其进行了签名。嵌入了验证所需并与私钥关联的证书。该代码可以在 .NET Fiddel 上在线运行:https ://dotnetfiddle.net/xpjAz4 。
请注意,XmlDocument
该类有一个PreserveWhitespace
属性,该属性默认为false
并控制在加载或保存时是否保留空格。签名时,XML 文档的格式必须与此一致,同时考虑到PreserveWhitespace
标志。在发布的代码中,使用默认值。
可以在此处找到使用嵌入式密钥进行签名的更多详细信息。此处描述了验证。
编辑:
为了使用id
带有xml
前缀的属性,SignedXml
必须派生类并且GetIdElement()
必须覆盖方法。这个解决方案来自这篇文章,需要调整前缀和命名空间。根据定义,前缀xml
绑定到命名空间http://www.w3.org/XML/1998/namespace
s。W3C 建议,3 声明命名空间,命名空间约束:保留前缀和命名空间名称。
此外,当然,由于xml:id
示例签名更改的修改因此也需要替换,因此上述代码片段总体更改为:
using System;
using System.Xml;
using System.Security.Cryptography.Xml;
public class VerifyTest
{
private static String signedXml =
@"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""no""?>
<Response xmlns=""http://www.site.ae/abc"">
<Message xml:id=""message"">
<Header>
<SomeDate>SomValue</SomeDate>
</Header>
<Body xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:type=""SomeDataType"">
<SomeStatus>Success</SomeStatus>
</Body>
</Message>
<Signature xmlns=""http://www.w3.org/2000/09/xmldsig#"">
<SignedInfo>
<CanonicalizationMethod Algorithm=""http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments""/>
<SignatureMethod Algorithm=""http://www.w3.org/2001/04/xmldsig-more#rsa-sha256""/>
<Reference URI=""#message"">
<Transforms>
<Transform Algorithm=""http://www.w3.org/2000/09/xmldsig#enveloped-signature""/>
</Transforms>
<DigestMethod Algorithm=""http://www.w3.org/2001/04/xmlenc#sha256""/>
<DigestValue>8anSzrELTpH8X6qq9rzTr6+T79EsRVhMLZ0ws3nYOTA=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>IAxXS6JBw/DGI4BdAKBSuUWYD7vX8zA5yWnez6/D2B7o2DhpGLuZVVA6gqIf9cr0omk+5kwyQMStKoYm9JWhFU136XtMgx19WC/ZCvGa59LBpIUsVpr3IKm0cQasp4jMIyeQCbAi0R/fYCY3fdH6GWdMcPuh47oOM63mBUYarokUv0ypuPykZsH010VvS9Af42BPRjnSpFRLoY4E9YtkWNpNoEgIMFRCCC6xsH+mLjMVFAmldAAGHiYn1v847NmHR3qmjRd+tfn8YtxEeLLJNgNgg8+lE1C2wsCpBTowXi/LKngEEwL+pckaSxCFa6qLIDC8aOJHM9BN30lrvSAYFGfaNZ0SHECga6aQ05UgZrlMpCg56d65qqNBz0+kDEgFhCzr8CqftHfGcVGXm95k27qNrDsrPac8s16/LBzzhONAhEwMJ7Rlef27/xSl87RSOQWTJWLF6unsJBqWvpKJY+CP0mmezqCcN/Q28oETOrR8q4QaW7ByLLv5FH1O8nneJyfd2QmhDJ3XDBSWeTGlJEGPYztVWzz2qcq9jpKmzpYxMFOJS24SKQlKcKWAdGeRJVillTyANeDnSt1YOS/z2lQoWPzrNY1XCkBUdEA+pe0aFtX2X1JCKEqvS3AtRui8fZzQ+frhcC/Y/hYDO1mD3NliUH9zkcEm8PdGNBJaLIY=</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIIF6zCCA9OgAwIBAgIJAM+qYs8R0GJeMA0GCSqGSIb3DQEBCwUAMIGLMQswCQYDVQQGEwJERTELMAkGA1UECAwCTlMxCjAIBgNVBAcMAUgxFDASBgNVBAoMC0lyZ2VuZGV0d2FzMRQwEgYDVQQLDAtJcmdlbmRldHdhczEUMBIGA1UEAwwLSXJnZW5kZXR3YXMxITAfBgkqhkiG9w0BCQEWEnh4eEBpcmdlbmRldHdhcy5kZTAeFw0yMTA1MDIxNDUxMThaFw0yMjA1MDIxNDUxMThaMIGLMQswCQYDVQQGEwJERTELMAkGA1UECAwCTlMxCjAIBgNVBAcMAUgxFDASBgNVBAoMC0lyZ2VuZGV0d2FzMRQwEgYDVQQLDAtJcmdlbmRldHdhczEUMBIGA1UEAwwLSXJnZW5kZXR3YXMxITAfBgkqhkiG9w0BCQEWEnh4eEBpcmdlbmRldHdhcy5kZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJr6EI/GVN8gnOf+TW0KDQkjUKWWgUcqclmXdDsT4s1Yd/EEFKTo6vVEm5Ny21Cer6wcZEdMOvK3lhVgFq/7/o9QEYGXiZPXJODcESvtbt+cpBS1X7LcCxJJVndcJV2txQIYtjao9/SdIoe85VbLypWbZXwWksL4RHC0ML59RDB+rfwf0q9uS3X48qXuf1dRuxWMawiV00Ov9PdnICNBNHZ//+S29ghJvTkqiRHOEu9Q9qMV7GCxM8fJBYEI+AAFyfaz2F6tswZFyluqDHbLDucBeqjcTqdZcHkazilNJHeMAZvraSuLHt9w69JMnERvL5HC6gVK4WRFfQHEeaYnwLmpOnhNMa+SaBflrlts015CmRDEtUFBDzK0PWdB3JWu+H44rBAWzhD5bJRvEdtfSqvLpp4a8wLmLXcADovK3PAA2k3KSEbxkOgvqPq5sJWo/SN9pcbFS6AINmATor7iZdwimP7pmddSsgmxARAQF07jPp8RaUkZ4+lKnnR7Jut/PoId9B+xqo6/LFVZlXXeht1mZBXj2DfWK6V0Bqwbct0IMjbOnCRnoeQ3IN+vWNzcB3X+8zguwzccrfnguvWT2HE9O6dQgARh2OqxYEp6VRcufndmwHkkAF8JHq15VLcgv4sabJg5OUsIgrCUDtP/O0UgGsDhfZPdvfSvYTHHlky5AgMBAAGjUDBOMB0GA1UdDgQWBBTnbZ3PwLMkg3NuCt0TKwiahLC+8zAfBgNVHSMEGDAWgBTnbZ3PwLMkg3NuCt0TKwiahLC+8zAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQBAelSzsSVVvvGDnQQvm73chbZo+QFL3MAqYoi1rUUCosni22Nfm/a2An6DrvCNM8RTuvXo5fVGd/7b6s0FsRB1/kR6Q31bCxNwJqT0TCsfVUE8QIgSTgqLFMo1JdDIci8V7SDb6lPCmJcrFjGWaqsCogtL/5Vjc1FdnUd+dz3w4QbkpcKOV5BW/Bc31ZBid9V7kQgp/w+3Rrxxm3M2M/0UINGMf+bKP2NQKoLr09WLZcxH0l8iRUXLHk1YY9HPGSUqlb1+7c38Iu2HAjd08N+3jeqFrbfjWL20Ebt2p8bzLrGkgK/HnaPAOKNpi+LGSjs/Uzvtuixv6ol2eZb/ZgA7YOd9DO5y4FRHKLBAwR3/tvoIPbxFBeLDl8y15unN74tNCzlNHs/FRwbG5aUvG1cJ+PylDvbjlymdinDtQeVR0F3p++5gEaqNoJoVjUiL5PT5zBEGxmXi6FXQG45hBCDkImyuvBKaflPN4Vbpmvg6M8u3Tfc4kKvgEfBP47/VsvomTw7ZyJqIQbCL8/dTFaPmh+Fmq1LDOt36MTw/I9Iiem2SKl0cR1s7lVyCGzHhkKDakvhz+QeAoCD7zAceF+BRKdirQ53PR4N3a8/Gv9Yord19TsU3Xb8u80bsVNB68JKgqDe4D7gsNK+Ou4exdxikoBq/hYWcKRdtOycYN2pP7g==</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</Response>";
public static void Main(String[] args)
{
// Print XML document
Console.WriteLine(VerifyTest.signedXml);
// Load signed XML document
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(VerifyTest.signedXml);
// Verify
SignedXmlWithId signedXml = new SignedXmlWithId(xmlDoc);
XmlNodeList nodeList = xmlDoc.GetElementsByTagName("Signature");
signedXml.LoadXml((XmlElement)nodeList[0]);
bool verified = signedXml.CheckSignature();
Console.WriteLine(new string('-', 100) + "\nVerified: " + verified);
}
class SignedXmlWithId : SignedXml
{
public SignedXmlWithId(XmlDocument xml) : base(xml) { }
public SignedXmlWithId(XmlElement xmlElement) : base(xmlElement) { }
public override XmlElement GetIdElement(XmlDocument doc, string id)
{
XmlElement idElem = base.GetIdElement(doc, id);
if (idElem == null)
{
XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable);
nsManager.AddNamespace("xml", "http://www.w3.org/XML/1998/namespace");
idElem = doc.SelectSingleNode("//*[@xml:id=\"" + id + "\"]", nsManager) as XmlElement;
}
return idElem;
}
}
}
现在 XML 示例与您发布的示例完全匹配,包括xml:id
属性。代码片段可以成功执行,例如在 .NET Fiddel 上在线执行:https ://dotnetfiddle.net/nqNhu3 。
推荐阅读
- asp.net - 防止在按钮单击时刷新页面
- wordpress - 标题计数器功能不适用于 WordPress,错误 500
- r - 将 R Shiny ggplot 与背景图像对齐
- android - 如何播放本地视频文件
- laravel - 我们如何在laravel中获得学校的最后一个ID?
- alexa - 如何从 alexa 语音资料或亚马逊帐户获取联系电话以开发 alexa 技能?
- java - Java 中的 ActionPerformed 方法
- php - 在 PHP7 中运行与 php 5.3 一起使用有什么问题?
- jquery - 使用 Id 在 Datalist 中设置选定值
- selenium-webdriver - 使用 TestNG (Java) 自定义范围报告