.net – 如何验证数字XML签名

前端之家收集整理的这篇文章主要介绍了.net – 如何验证数字XML签名前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我想验证文档没有被修改.

Java Web服务,我收到以下Soap响应与数字XML签名:

  1. <?xml version="1.0" encoding="UTF-8"?><Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
  2. <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" SOAP-ENV:mustUnderstand="1">
  3. <wsse:BinarySecurityToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="CertId-38670273">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</wsse:BinarySecurityToken><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
  4. <ds:SignedInfo>
  5. <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
  6. <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
  7. <ds:Reference URI="#id-32516734">
  8. <ds:Transforms>
  9. <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
  10. </ds:Transforms>
  11. <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
  12. <ds:DigestValue>Rx5L4j8kF5RVYnC+spUCdvhh5N0=</ds:DigestValue>
  13. </ds:Reference>
  14. <ds:Reference URI="#id-7716709">
  15. <ds:Transforms>
  16. <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
  17. </ds:Transforms>
  18. <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
  19. <ds:DigestValue>fFr2j5DoKTgpEvX1Se7gTC55bWM=</ds:DigestValue>
  20. </ds:Reference>
  21. </ds:SignedInfo>
  22. <ds:SignatureValue>
  23. jG1BaGgNbbk9JCc3R6JsJKY56p++f0+8RM2aL6TGOXS34NAGv48Sp3iAHEAuUt9+JV6w3VDAcFct
  24. no3nCEISa0P4dVWTlPQJue3GVTWnnlcXao95tjukh9o8lIU7vZGgYHBUZLU+jgS6ZcaUlNW4KFUl
  25. AdrPxR5DmJcFyGEtRY2yclqYhnJdnUc+ZBu5eWbRZgbJzR4MgtGsEQcgtftFe2i0CvRbOSe4mt3T
  26. JQzbGY81ssFCnB44vitgjhVLfPd/08amSa5Xn8KRptbNatp2uq1iGXAifJLVup8T0yS0RzaqhCJg
  27. CaHRPFVKFN3WaJcqPZex75KBwSZMZaaJDZW7lQ==
  28. </ds:SignatureValue>
  29. <ds:KeyInfo Id="KeyId-16708261">
  30. <wsse:SecurityTokenReference xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="STRId-32258670"><wsse:Reference URI="#CertId-38670273" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/></wsse:SecurityTokenReference>
  31. </ds:KeyInfo>
  32. </ds:Signature>
  33. <wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-32516734"><wsu:Created>2017-03-31T09:04:40.352Z</wsu:Created><wsu:Expires>2017-03-31T09:09:40.352Z</wsu:Expires></wsu:Timestamp></wsse:Security><wsa:MessageID xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" SOAP-ENV:mustUnderstand="0">uuid:12b93a00-15f1-11e7-af6b-f16d80f418ae</wsa:MessageID><wsa:To xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" SOAP-ENV:mustUnderstand="0">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To></SOAP-ENV:Header>
  34.  
  35.  
  36. <SOAP-ENV:Body xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-7716709">
  37. ...
  38. </SOAP-ENV:Body></Envelope>

我发现一个有用的例子来验证MSDN上的xml文件

  1. ' Verify the signature of an XML file and return the result.
  2. Function VerifyXmlFile(ByVal Name As String) As [Boolean]
  3. ' Create a new XML document.
  4. Dim xmlDocument As New XmlDocument()
  5.  
  6. ' Format using white spaces.
  7. xmlDocument.PreserveWhitespace = True
  8.  
  9. ' Load the passed XML file into the document.
  10. xmlDocument.Load(Name)
  11.  
  12. ' Create a new SignedXml object and pass it
  13. ' the XML document class.
  14. Dim signedXml As New SignedXml(xmlDocument)
  15.  
  16. ' Find the "Signature" node and create a new
  17. ' XmlNodeList object.
  18. Dim nodeList As XmlNodeList = xmlDocument.GetElementsByTagName("Signature","http://www.w3.org/2000/09/xmldsig#")
  19.  
  20. ' Load the signature node.
  21. signedXml.LoadXml(CType(nodeList(0),XmlElement))
  22.  
  23. ' Check the signature and return the result.
  24. Return signedXml.CheckSignature()
  25.  
  26. End Function

不幸的是,验证总是返回false.我很难理解为什么它不起作用.

根据Henk Holterman Simon Mourier的建议进行变更:

  1. Function VerifyXmlFile(ByVal Name As String) As Boolean
  2.  
  3. ' <SOAP-ENV:Envelope ... > ... </SOAP-ENV:Envelope>
  4. Dim xDoc = XDocument.Load(Name)
  5.  
  6. ' <wsse:binarySecurityToken ... > ... </wsse:binarySecurityToken>
  7. Dim xBinarySecurityToken = xDoc.Root.Descendants().Skip(2).FirstOrDefault
  8.  
  9. ' <SOAP-ENV:Body ... > ... </SOAP-ENV:Body>
  10. Dim xBody = xDoc.Root.Elements().Skip(1).FirstOrDefault
  11. Dim signedXml = New SignedXml(ToXmlElement(xBody))
  12.  
  13. Dim xmlDocument As New XmlDocument()
  14. xmlDocument.PreserveWhitespace = True
  15. xmlDocument.Load(Name)
  16.  
  17. Dim nodeList = xmlDocument.GetElementsByTagName("Signature","http://www.w3.org/2000/09/xmldsig#")
  18. signedXml.LoadXml(CType(nodeList(0),XmlElement))
  19.  
  20. Dim byteCert = Encoding.UTF8.GetBytes(xBinarySecurityToken.Value)
  21. Dim cert = New X509Certificates.X509Certificate2(byteCert)
  22.  
  23. Return signedXml.CheckSignature(cert,True)
  24.  
  25. End Function
  26.  
  27. Public Shared Function ToXmlElement(xElement As XElement) As XmlElement
  28. Dim xmlDoc = New XmlDocument() With {.PreserveWhitespace = True}
  29. xmlDoc.Load(xElement.CreateReader())
  30. Return xmlDoc.DocumentElement
  31. End Function

通过调用函数CheckSignature()导致CryptographicException消息“Invalid reference element”.

其实这是一个已知和记录的问题:

The Canonicalization implementation between .NET 3.5 and .NET 4.0 has
changed.

我不知道这是否适用于所有XML签名,但它可以从我所做的测试中起作用.

将以下C14N Transform类添加到您的项目中:

  1. public class MyXmlDsigC14NTransform: XmlDsigC14NTransform {
  2. static XmlDocument _document;
  3. public static XmlDocument document {
  4. set {
  5. _document = value;
  6. }
  7. }
  8.  
  9. public MyXmlDsigC14NTransform() {}
  10.  
  11. public override Object GetOutput() {
  12. return base.GetOutput();
  13. }
  14.  
  15. public override void LoadInnerXml(XmlNodeList nodeList) {
  16. base.LoadInnerXml(nodeList);
  17. }
  18.  
  19. protected override XmlNodeList GetInnerXml() {
  20. XmlNodeList nodeList = base.GetInnerXml();
  21. return nodeList;
  22. }
  23.  
  24. public XmlElement GetXml() {
  25. return base.GetXml();
  26. }
  27.  
  28. public override void LoadInput(Object obj) {
  29. int n;
  30. bool fDefaultNS = true;
  31.  
  32. XmlElement element = ((XmlDocument) obj).DocumentElement;
  33.  
  34. if (element.Name.Contains("SignedInfo")) {
  35. XmlNodeList DigestValue = element.GetElementsByTagName("DigestValue",element.NamespaceURI);
  36. string strHash = DigestValue[0].InnerText;
  37. XmlNodeList nodeList = _document.GetElementsByTagName(element.Name);
  38.  
  39. for (n = 0; n < nodeList.Count; n++) {
  40. XmlNodeList DigestValue2 = ((XmlElement) nodeList[n]).GetElementsByTagName("DigestValue",((XmlElement) nodeList[n]).NamespaceURI);
  41. string strHash2 = DigestValue2[0].InnerText;
  42. if (strHash == strHash2) break;
  43. }
  44.  
  45. XmlNode node = nodeList[n];
  46.  
  47. while (node.ParentNode != null) {
  48. XmlAttributeCollection attrColl = node.ParentNode.Attributes;
  49. if (attrColl != null) {
  50. for (n = 0; n < attrColl.Count; n++) {
  51. XmlAttribute attr = attrColl[n];
  52. if (attr.Prefix == "xmlns") {
  53. element.SetAttribute(attr.Name,attr.Value);
  54. } else if (attr.Name == "xmlns") {
  55. if (fDefaultNS) {
  56. element.SetAttribute(attr.Name,attr.Value);
  57. fDefaultNS = false;
  58. }
  59. }
  60. }
  61. }
  62.  
  63. node = node.ParentNode;
  64. }
  65. }
  66.  
  67. base.LoadInput(obj);
  68. }
  69. }

并使用CryptoConfig.AddAlgorithm方法注册该类,如下所示:

  1. CryptoConfig.AddAlgorithm(typeof(MyXmlDsigC14NTransform),"http://www.w3.org/TR/2001/REC-xml-c14n-20010315");
  2.  
  3. var message = new XmlDocument();
  4. message.PreserveWhitespace = true;
  5. message.Load("XmlSig.xml");
  6.  
  7. MyXmlDsigC14NTransform.document = message; // The transform class needs the xml document
  8.  
  9. // Validate signature as normal.

这应该允许您正确验证XML签名并解决您的问题.

猜你在找的XML相关文章