我有这样的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>
如何创建参考中的摘要值(WqpRWHxXA0YgH + p3Sxy6hRo1XIk =)?我的意思是如何手动计算这个值?
答案 0 :(得分:21)
我试图找出完全相同的东西时遇到了这个问题。我后来想出了怎么做,所以我想在这里发布答案。
需要发生的事情是:
规范化部分相当简单,因为Java库为我做了这些。我努力的是接下来的一点,即摘要的创建,因为我犯了一个致命错误,因为我生成的SHA1摘要是HEX形式的SHA1。 SHA1是160位,所以20个字节,但如果你在HEX中输出这160位,你会得到40个字符。如果你然后对其进行base64编码,那么与DigestValue中的内容相比,你会得到完全错误的值。
相反,您应该生成SHA1摘要,base64编码20字节输出。不要尝试将20个字节输出到STDOUT,因为它不太可能被读取(这就是为什么人们经常输出HEX等价物,因为它 可读)。相反,只需base64编码20个字节,这就是你的DigestValue。
答案 1 :(得分:3)
我自己遇到了这个问题:我在Java&amp;中生成了一个XML签名。在.NET中验证,验证总是失败。在我的情况下,原因是'打印XML到文件'功能XMLWrite.m(是的,在MATLAB *中),它“非常打印”XML,插入标签,空格和换行符。由于这些是文档的一部分,因此验证自然失败(它在Java中也失败了)。看看你的来源,这可能发生在你身上。使用Transformer(javax.xml.transform。*)在不更改内容的情况下正确地序列化DOM。
*您确实知道MATLAB也理解Java吗?您只需在解释器控制台&amp;中键入Java语句即可。它们将像本机m代码一样执行。
答案 2 :(得分:3)
非常简单,在控制台中使用openssl:
openssl dgst -binary -sha1文件| openssl enc -base64
完成
答案 3 :(得分:2)
这是一个JAVA解决方案,需要以下罐子:
此解决方案使用http://www.w3.org/2001/10/xml-exc-c14n#
作为规范化算法,并使用SHA256
作为散列算法和base64编码。
注意:
document
将XML文档表示为JAVA中的DOM对象。
代码示例:
// create the transformer in order to transform the document from
// DOM Source as a JAVA document class, into a character stream (StreamResult) of
// type String writer, in order to be converted to a string later on
TransformerFactory tf = new net.sf.saxon.TransformerFactoryImpl();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
// create the string writer and transform the document to a character stream
StringWriter sw = new StringWriter();
transformer.transform(new DOMSource(document), new StreamResult(sw));
String documentAsString = sw.toString();
// initialize the XML security object, which is necessary to run the apache canonicalization
com.sun.org.apache.xml.internal.security.Init.init();
// canonicalize the document to a byte array and convert it to string
Canonicalizer canon = Canonicalizer.getInstance(Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
byte canonXmlBytes[] = canon.canonicalize(documentAsString.getBytes());
String canonXmlString = new String(canonXmlBytes);
// get instance of the message digest based on the SHA-256 hashing algorithm
MessageDigest digest = MessageDigest.getInstance("SHA-256");
// call the digest method passing the byte stream on the text, this directly updates the message
// being digested and perform the hashing
byte[] hash = digest.digest(canonXmlString.getBytes(StandardCharsets.UTF_8));
// encode the endresult byte hash
byte[] encodedBytes = Base64.encodeBase64(hash);
return new String(encodedBytes);
答案 4 :(得分:-2)
This文档应包含如何计算摘要值。
我希望它有所帮助!