2014-09-06 54 views
2

嗨,我讀this post關於如何實現鹽和哈希到密碼,我堅持在我指定的網站下面指定的代碼。將填充添加到十六進制的目的是什麼?

private static String toHex(byte[] array) 
{ 
    BigInteger bi = new BigInteger(1, array); 
    String hex = bi.toString(16); 
    int paddingLength = (array.length * 2) - hex.length(); 
    if(paddingLength > 0) 
     return String.format("%0" + paddingLength + "d", 0) + hex; 
    else 
     return hex; 
} 

我的問題是,爲什麼他們計算paddingLength並落實到十六進制如果結果paddingLength大於零?

回答

1

因爲他們希望數組中的所有字節都以十六進制字符串表示,即使它們是前導零字節。

儘管這不是編寫toHex方法最明顯的方法。

,我覺得這樣的事情更清楚:

private static String toHex(byte[] array) { 
    StringBuilder s = new StringBuilder(); 
    for (byte b : array) { 
     s.append(String.format("%02x", b)); 
    } 
    return s.toString(); 
} 
+0

這也是我的方法(如果我不需要性能)。但是我總是在字符串生成器的構造函數中指定'array.length * 2'。 – 2014-09-06 13:17:55

2

BigInteger(byte[])解釋字節數組成二進制補碼值;這意味着它對於N長度數組有2 ^(8 * N)個可能的值(因爲每個字節包含8位)。同時,長度爲M的十六進制字符串具有16^M個可能值(因爲每個字符都編碼16個值中的一個)。

作者想要byte[]String之間的一對一映射:給定一個字符串,你應該能夠確切地確定它來自於byte[]。爲了達到這個目的,我們必須確保字符串可以編碼與byte[]一樣多的值。從上面插入數字,我們得到:

(# values for an N-length byte[]) == (# values for an M-length String) 
2^(8*N)       == 16^M 

讓我們用N來解答M.第一步是重寫右邊。如果你還記得你的exponent power rules,a ^(b * c)==(a^b)^ c。讓我們指數的基礎上的權利是一個2:

        == (2^4)^M 
            == 2^(4*M) 

因此,我們有2 ^(8 * N)== 2 ^(4 * M)。如果2^k == 2^j,則表示k == j。所以,8 * N == 4 * M。將兩邊除以4得到M = 2N。

要將它連接在一起,請記住N是字節數組的長度,M是十六進制字符串的長度。我們剛剛發現,要有一對一映射,M = 2N - 換句話說,十六進制字符串應該是字節數組的兩倍。

填充確保。

+0

這當然是一個正確的答案,但不應該使用上面的'toHex()'方法。它很慢,很難閱讀,使用額外的內存,使用帶動態比賽的格式字符串等。 – 2014-09-06 13:20:22

+0

確實如此。我關注的是意圖(將字節數組的長度加倍)而不是實現,因爲這就是問題的癥結所在。 – yshavit 2014-09-06 17:03:01

相關問題