XML签名:如何计算摘要值?

use*_*816 23 xml digest digital-signature xml-signature

我有这样的XML

<?xml version="1.0" encoding="utf-8"?>
<foo>
  <bar>
    <value>A</value>
  </bar>
  <bar>
    <value>B</value>
  </bar>
  <baz>
    <value>C</value>
  </baz><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /><DigestValue>WqpRWHxXA0YgH+p3Sxy6hRo1XIk=</DigestValue></Reference></SignedInfo><SignatureValue>EoRk/GhR4UA4D+8AzGPPkeim1dZrlSy88eF73n/T9Lpeq9IxoGRHNUA8FEwuDNJuz3IugC0n2RHQQpQajiYvhlY3XG+z742pgsdMfFE4Pddk4gF1T8CVS1rsF7bjX+FKT/c8B2/C8FNgmfkxDlB/ochtbRvuAGPQGtgJ3h/wjSg=</SignatureValue><KeyInfo><X509Data><X509Certificate>MIIB8zCCAVygAwIBAgIQgfzbrIjhLL9FobStI2ub3zANBgkqhkiG9w0BAQQFADATMREwDwYDVQQDEwhUZXN0ZUFjbjAeFw0wMDAxMDEwMDAwMDBaFw0zNjAxMDEwMDAwMDBaMBMxETAPBgNVBAMTCFRlc3RlQWNuMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDO+yAZ8/qJbhSVH/+2wMmzix3jM/CExb6sTgaiPwe6ylcHgF45zeQDq06OSJZCSns34em/ULINZddDf8z0b9uk/2sOGr1pYqsunLLBvw2FkvWJQDkhx2SzCm8v4xGX2kyXNbjiY/K56oPOMjpayKoAFnnvk7p2iFAxNZK/6lpZ7wIDAQABo0gwRjBEBgNVHQEEPTA7gBCOOHcajwnATYZ0t6w7LVU0oRUwEzERMA8GA1UEAxMIVGVzdGVBY26CEIH826yI4Sy/RaG0rSNrm98wDQYJKoZIhvcNAQEEBQADgYEABL9Qhi6f1Z+/t8oKXBQFx3UUsNF9N2o4k6q1c3CKZYqx2E/in+nARIYRdh5kbeLfomi6GIyVFeXExp8crob3MAzOQMvXf9+ByuezimMPIHDvv0u3kmmeITXfoZrHCDxLoWWlESN1owBfKPqe7JKAuu9ORDC0pUiUfCHWxCoqNos=</X509Certificate></X509Data></KeyInfo></Signature>
</foo>
Run Code Online (Sandbox Code Playgroud)

如何创建引用中的摘要值(WqpRWHxXA0YgH + p3Sxy6hRo1XIk =)?我的意思是如何手动计算这个值?

Ken*_*nny 22

我试图找出完全相同的东西时遇到了这个问题.我后来想知道怎么做,所以我想在这里发布答案.

需要发生的事情是:

  • 规范化
  • 创建摘要值,通常为SHA1(但可能是SHA256)
  • base64对它进行编码

规范化部分相当简单,因为Java库为我做了这些.我努力的是接下来的一点,即摘要的创建,因为我犯了一个致命错误,因为我生成的SHA1摘要是HEX形式的SHA1.SHA1是160位,所以20个字节,但如果你在HEX中输出这160位,你会得到40个字符.如果你对base64进行编码,那么与DigestValue中的相比,你会得到完全错误的值.

相反,您应该生成SHA1摘要,base64编码20字节输出.不要尝试将20个字节输出到STDOUT,因为它几乎不可读(这就是为什么人们经常输出HEX等价物,因为它可读的).相反,只需base64编码20个字节,这就是你的DigestValue.

  • SHA1消化了什么? (4认同)

小智 5

很简单,在控制台中使用openssl:

openssl dgst -binary -sha1文件| openssl enc -base64

完成了


Max*_*Max 3

我自己就遇到过这个问题:我在 Java 中生成 XML 签名并在 .NET 中验证,但验证总是失败。在我的例子中,原因是“将 XML 打印到文件”函数 XMLWrite.m(是的,在 MATLAB* 中),它“漂亮地打印”了 XML,插入了制表符、空格和换行符。由于这些是文档的一部分,验证自然会失败(在 Java 中也失败了)。查看您的消息来源,这可能发生在您身上。使用 Transformer (javax.xml.transform.*) 正确序列化 DOM,而不更改内容。

*您确实知道 MATLAB 也理解 Java?您只需在解释器控制台中输入 Java 语句即可,它们将像本机 m 代码一样执行。

  • 依赖于 XML 规范化的 XML 签名已经解决了这个问题。XML 首先被规范化,语法差异(空格、命名空间等)将被正确处理。 (2认同)