2014-07-14 47 views
4

我可以在PHP與鹽簡單地散列:在java中完全相同的哈希PHP與鹽? (SHA-256)

$orig_pw = "abcd"; 
$salt = 5f8f041b75042e56; 
$password = hash('sha256', $orig_pw . $salt); 

(這不是我如何實現它,這只是一個例子鹽是每個人不同)

而且與此相關,存儲的口令是:

bc20a09bc9b3d3e1fecf0ed5742769726c93573d4133dbd91e2d309155fa9929 

但是,如果我嘗試做在Java中一樣,我得到不同的結果。我試圖String password = "abcd";

byte[] salt = hexStringToByteArray("5f8f041b75042e56"); 

try { 
    System.out.println(new String(getHash(password, salt))); 
} catch (NoSuchAlgorithmException e1) { 
    e1.printStackTrace(); 
} 

而且,這兩個方法:

public byte[] getHash(String password, byte[] salt) throws NoSuchAlgorithmException { 
     MessageDigest digest = MessageDigest.getInstance("SHA-256"); 
     digest.reset(); 
     digest.update(salt); 
     try { 
      return digest.digest(password.getBytes("UTF-8")); 
     } catch (UnsupportedEncodingException e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 


public byte[] hexStringToByteArray(String s) { 
     int len = s.length(); 
     byte[] data = new byte[len/2]; 
     for (int i = 0; i < len; i += 2) { 
      data[i/2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) 
           + Character.digit(s.charAt(i+1), 16)); 
     } 
     return data; 
    } 

結果是:

/¬1¶ĆĽëüFd?[$?¶»_9ËZ»ç¶S‘Ęŗש 

其中編碼爲十六進制甚至沒有接近它:

2fac31b6434c14ebfc46643f5b243fb6bb5f39cb5abb10e7b65391454c97d7a90d0a 

任何人都可以埃爾普與此?

回答

6

除了交換順序之外,它看起來像在PHP中將鹽值視爲附加到密碼的文字字符串,而在Java中,您先對鹽進行十六進制轉換,然後使用結果字節更新MessageDigest。這顯然會產生不同的結果。如果只考察鹽:

PHP:鹽 - >要字節(文字) - > SHA-256
的Java:鹽 - >要字節(UNHEX) - > SHA-256

我只是嘗試了你的Java代碼,而且它絕對沒問題。我也嘗試在PHP中對Java中的相同值進行哈希處理,並給出了相同的結果。

Java的等同於你的PHP代碼如下:

String password = "abcd"; 
String salt = "5f8f041b75042e56"; 

try { 
    MessageDigest digest = MessageDigest.getInstance("SHA-256"); 

    return digest.digest((password + salt).getBytes("UTF-8")); 
} catch (UnsupportedEncodingException | NoSuchAlgorithmException e) { 
    return null; 
} 

詛咒它返回以下結果字節後:

60359BC8A0B09898335AA5A037B1E1B9CE3A1FE0D4CEF13514901FB32F3BCEB0 

而在PHP做:

<? 
echo hash('sha256', "abcd"."5f8f041b75042e56"); 
?> 

返回完全相同。

+0

我不明白每一個字(不是英文)。那麼我應該改變java中的salt嗎? (如:byte [] salt =「5f8f041b75042e56」.getBytes();)另外,我如何在java中交換它們? – RuntimeException

+0

我不知道你的實際PHP代碼是什麼樣子的(你發佈的代碼將不會運行,因爲它只有十六進制字符串)。但似乎你在哈希''abcd「。」5f8f041b75042e56「'。要做到Java中的等價物,你必須做'(「password」+「salt」)。getBytes(「UTF-8」),然後消化它。 –

+0

對代碼抱歉,這不是它的實現。實際的代碼得到一個隨機數:$ salt = dechex(mt_rand(0,2147483647))。 dechex(mt_rand(0,2147483647)); – RuntimeException

2

我覺得

digest.update(salt); 
digest.digest(password.getBytes("UTF-8")); 

等同於:

hash('sha256', $salt . $orig_pw); 

所以哈希和鹽交換。你能證實這一點嗎?

+0

是的,他們交換我認爲。 (如果可能的話,保持這種方式) – RuntimeException

+0

你不能只交換它們,輸入必須在PHP和Java中相同。 – Halcyon

+0

我的意思是保持它在PHP中交換,並在Java中交換它。 – RuntimeException