簡體   English   中英

誰能驗證使用此方法獲取md5哈希的正確性?

[英]Could anyone verify the correctness of getting a md5 hash using this method?

        MessageDigest m=MessageDigest.getInstance("MD5");
        StringBuffer sb = new StringBuffer();
        if(nodeName!=null) sb.append(nodeName);
        if(nodeParentName!=null) sb.append(nodeParentName);
        if(nodeParentFieldName!=null) sb.append(nodeParentFieldName);
        if(nodeRelationName!=null) sb.append(nodeRelationName);
        if(nodeViewName!=null) sb.append(nodeViewName);
        if(treeName!=null) sb.append(treeName);
        if(nodeValue!=null && nodeValue.trim().length()>0) sb.append(nodeValue);
        if(considerParentHash) sb.append(parentHash);
        m.update(sb.toString().getBytes("UTF-8"),0,sb.toString().length());
        BigInteger i = new BigInteger(1,m.digest());
        hash = String.format("%1$032X", i);

這些代碼行背后的想法是,我們將類/模型的所有值附加到StringBuilder中,然后返回其填充后的哈希值(Java實現返回長度為30或31的md5哈希值,因此最后一行格式化了哈希值填充0)。

我可以驗證此方法是否有效,但是我感覺它有時會失敗(我們的應用程序失敗了,我相信這可能是原因)。

誰能看到一個行不通的原因? 是否有任何變通辦法可以使此代碼不太容易出錯(例如,不需要將字符串設為UTF-8)。

您的代碼中有些奇怪的事情。

字符的UTF-8編碼可能使用多個字節。 因此,您不應將字符串長度用作update()調用的最終參數,而應使用getBytes()實際上返回的字節數組的長度。 如Paŭlo所建議,使用update()方法,該方法將單個byte[]作為參數。

MD5的輸出是一個16字節的序列,具有非常任意的值。 如果將其解釋為整數(這就是對BigInteger()調用),那么您將得到一個小於2 160的數值,可能小得多。 當轉換回十六進制數字時,您可能會獲得32、31、30 ...或少於30個字符。 您使用的"%032X"格式字符串左鍵帶有足夠的零,因此您的代碼可以工作,但是它是間接的(MD5的輸出從來都不是整數)。

您使用原始串聯組合哈希輸入元素。 這可能會引起問題。 例如,如果modeName為“ foo ”,而modeParentName為“ barqux ”,則MD5輸入將以“ barqux ”(UTF-8編碼) foobarqux 如果modeName為“ foobar ”,而modeParentName為“ qux ”,則MD5輸入將以“ foobarqux ”開頭。 您沒有說出為什么要使用哈希函數,但是通常,當使用哈希函數時,它具有對某些數據的唯一跟蹤。 兩個不同的數據元素應產生不同的哈希輸入。

在處理nodeValue ,您調用trim() ,這意味着該字符串可以以空格開頭和/或結尾,並且您不希望將該空格包含在哈希輸入中,但是您確實要包含它,因為您將nodeValue和不是nodeValue.trim()

如果您要嘗試執行的操作與安全性有任何關系,則不應使用加密破壞的MD5。 請改用SHA-256。

哈希XML元素通常是通過規范化完成的(規范處理空白,屬性順序,文本表示等)。 有關使用Java標准化XML數據的主題,請參見此問題

一個可能的問題在這里:

m.update(sb.toString().getBytes("UTF-8"),0,sb.toString().length());

就像Robing Green所說的那樣, UTF-8編碼可以產生一個比原始字符串更長的byte[] (當String包含非ASCII字符時,它將精確地執行此操作)。 在這種情況下,您僅哈希String的開頭。

最好這樣寫:

m.update(sb.toString().getBytes("UTF-8"));

當然,如果您的字符串中包含非ASCII字符,則不會導致異常,而不會產生異常。 您應該嘗試將失敗歸結為SSCCE,如推薦的lesmana。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM