2011-09-30 45 views
10

我有一個包含用戶名和密碼的SQL表。密碼使用MessageDigest的摘要()方法進行編碼。如果我使用MessageDigest的digest()方法對密碼進行編碼(比如說「abcdef12」),然後將其轉換爲十六進制值,則String與使用PHP的SHA1方法執行相同操作時不同。我希望這些值是完全一樣的。用來編碼密碼Java的MessageDigest SHA1算法返回的結果不是SHA1的函數php

代碼:

public static String convertStringToHex(String str) { 

    char[] chars = str.toCharArray(); 

    StringBuffer hex = new StringBuffer(); 
    for (int i = 0; i < chars.length; i++) { 
     hex.append(Integer.toHexString((int) chars[i])); 
    } 

    return hex.toString(); 
} 

密碼:abcdef12

這裏的

MessageDigest md = MessageDigest.getInstance("SHA-1"); 
byte[] passbyte; 
passbyte = "abcdef12".getBytes("UTF-8"); 
passbyte = md.digest(passbyte); 

字符串爲十六進制的轉換就是採用這種方法來完成由許多SHA1-Hash在線生成器和PHP SHA1()返回的密碼 - 功能:d253e3b d69ce1e7ce6074345fd5faa1a3c2e89ef

這裏的密碼通過消息摘要作爲編碼:d253e3bd69ce1e7ce674345fd5faa1a3c2e2030ef

我是不是忘了什麼東西?

伊戈爾。

編輯:我發現有人有類似的問題:C# SHA-1 vs. PHP SHA-1...Different Results?。解決方案是更改編碼..但我不能更改服務器端的編碼,因爲該SQL表中的密碼不是由我的應用程序創建的。 我使用JavaScript SHA1類(更精確地說:Google Web Toolkit類)使用客戶端SHA1編碼。它的工作原理,並預期編碼字符串,但顯然使用ASCII字符..

回答

3

它與編碼無關。輸出將完全不同。

對於初學者,您的功能convertStringToHex()不輸出前導零,也就是07只變成7

其餘的(更改892030)也可能與該功能有關。嘗試在passbyte = md.digest(passbyte);之後查看passbyte的值。

+0

謝謝!你的答案解決了我的問題。我無法正確地將字節數組轉換爲十六進制字符串!我使用@stivlo的方法,它效果很好!我打算將這個回答標記爲正確的,但在這種情況下,我希望我可以將兩個回答都標記爲正確回答!謝謝你們倆! – Igor

5

我有同樣的摘要作爲PHP與我的Java SHA-1散列函數:

public static String computeSha1OfString(final String message) 
    throws UnsupportedOperationException, NullPointerException { 
     try { 
       return computeSha1OfByteArray(message.getBytes(("UTF-8"))); 
     } catch (UnsupportedEncodingException ex) { 
       throw new UnsupportedOperationException(ex); 
     } 
} 

private static String computeSha1OfByteArray(final byte[] message) 
    throws UnsupportedOperationException { 
     try { 
      MessageDigest md = MessageDigest.getInstance("SHA-1"); 
      md.update(message); 
      byte[] res = md.digest(); 
      return toHexString(res); 
     } catch (NoSuchAlgorithmException ex) { 
      throw new UnsupportedOperationException(ex); 
     } 
} 

我已經添加到我的單元測試:

String sha1Hash = StringHelper.computeSha1OfString("abcdef12"); 
assertEquals("d253e3bd69ce1e7ce6074345fd5faa1a3c2e89ef", sha1Hash); 

該類的完整源代碼是on github

+0

事實上 - 你的代碼產生正確的SHA1(或者更確切地說:與php的SHA1相同)。但是,我正在編寫一個必須登錄到現有數據庫的應用程序。該數據庫不是由我自己創建的(也不是密碼加密)。但**它使用MessageDigest,就像我的示例**中所寫,因此在該String上運行Base64.decode會返回不同的結果(在我的示例中指定的結果),而不是您的正確結果,我也使用JavaScript SHA1-類。有什麼方法可以比較它們嗎?我不知道MessageDigest如何返回其他結果。 – Igor

2

試試這個 - 這是爲我工作:

MessageDigest md = MessageDigest.getInstance(algorithm); 
md.update(original.getBytes()); 
byte[] digest = md.digest(); 
StringBuffer sb = new StringBuffer(); 
for (byte b : digest) { 
    sb.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1)); 
} 
return sb.toString(); 

問候, Konki

2

或者試試這個:

MessageDigest md = MessageDigest.getInstance("SHA-1"); 
md.update(clearPassword.getBytes("UTF-8")); 
return new BigInteger(1 ,md.digest()).toString(16)); 

乾杯羅伊