2010-02-11 133 views
19

我有這樣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> 

的XML如何被創建在參考的摘要值(WqpRWHxXA0YgH + p3Sxy6hRo1XIk =)?我的意思是我如何手動計算這個值?

+0

爲什麼你要手動計算呢?這將是一個單調乏味且容易出錯的過程。 – HerbN 2010-02-11 15:16:30

+0

我正在使用.net函數來驗證簽名。它返回的簽名是無效的。所以我想手動檢查它,或者是否有任何工具來檢查簽名... – user252816 2010-02-11 15:18:26

+0

我知道你解決了「摘要驗證失敗的參考」錯誤?是否有可能詳細解釋你是如何做到的?我有一個使用Metro進行簽名肥皂信息的問題,.Net WCF應用程序無法識別摘要值。 – 2012-04-12 20:52:12

回答

-1

This文檔應包含如何計算摘要值。

我希望它有幫助!

2

我自己也遇到過這個問題:我正在用.NET驗證Java &中的XML簽名,驗證總是失敗。在我的情況下,原因是'打印XML到文件'函數XMLWrite.m(是的,在MATLAB *中),它'漂亮'打印XML,插入製表符,空格和換行符。由於這些是文檔的一部分,因此驗證失敗(在Java中也失敗了)。看着你的來源,這可能發生在你身上。使用Transformer(javax.xml.transform。*)正確地串行化DOM,而不更改內容。你知道MATLAB也理解Java嗎?您可以將Java語句鍵入到解釋器控制檯&中,它們將像本地m代碼一樣執行。

+2

這已經通過依賴XML規範化的XML簽名解決。首先對XML進行標準化,然後將正確處理語法差異(空格,名稱空間等)。 – ewernli 2010-02-12 12:04:36

+1

確實:但是它是DOM,而不是它的seralization,它已被規範化。在序列化(到文件)期間插入額外的空白字符,在計算摘要之後,當驗證代碼創建其DOM時,它們仍然存在,對其進行規範化並重新計算摘要。空格在解析的字符數據節點中很重要。 – Max 2010-02-12 12:21:48

16

我試圖找出完全相同的東西時遇到了這個問題。後來我想出瞭如何去做,所以我想在這裏發佈答案。

需要發生的事情是:

  • 規範化
  • 創建摘要值,通常SHA1(但可以在其他之中被SHA256)
  • Base64編碼,它

規範化部分相當簡單,就像Java庫爲我做的那樣。我之所苦的是接下來的一點,即創建摘要,因爲我犯了一個致命的錯誤,因爲我生成的SHA1摘要是以十六進制形式的SHA1。 SHA1是160位,因此有20個字節,但如果以十六進制輸出這些160位,則會得到40個字符。如果您使用base64進行編碼,那麼與DigestValue中的內容相比,您將得到的的值完全是錯誤值

相反,您應該生成SHA1摘要,base64編碼20個字節的輸出。不要試圖將20個字節輸出到STDOUT,因爲它不太可能被讀取(這就是爲什麼人們經常輸出HEX等價物,因爲它的可讀)。相反,只需base64對20個字節進行編碼,這就是您的DigestValue。

+0

我也這麼認爲,但我也得到了不同的價值。你是直接消化Canonicalization Bytes還是消化String字節? – 2012-09-04 13:11:04

+0

SHA1摘要是什麼? – lonelyloner 2017-12-21 01:58:37

0

很簡單,在控制檯中使用OpenSSL:

OpenSSL的DGST -binary -sha1文件| OpenSSL的ENC -base64

完成

+0

OP沒有將「手動」指定爲「以編程方式」。 無論如何,這是一個很好的檢查方法。 – Vbakke 2017-05-24 15:12:57

0

這是一個JAVA溶液,其需要以下罐子:

  • 共享記錄-1.2.jar
  • 公地編解碼器1.6。罐子
  • 撒克遜-HE-9.4.jar
  • xmlsec-1.3.0.jar

此解決方案使用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);