2011-01-22 67 views
4

我發現自己需要將網站平臺從Java更改爲PHP,但我想保留所有用戶的密碼...你能在PHP中獲得這個相同的Java SHA-1嗎?

我有此代碼在寫哈希值之前先進行密碼散列密碼的網站:

MessageDigest md = null; 
md = MessageDigest.getInstance("SHA"); 
md.update(plaintext.getBytes("UTF-8")); 
byte raw[] = md.digest(); 
hash = new Base64().encodeToString(raw).replaceAll("\n", "").replaceAll("\r", ""); 

我認爲Java代碼做了密碼SHA-1散列只是在此之前,它是字節編碼成UTF-8,之後它被Base64編碼。

我想有一個PHP代碼做同樣的事情,即返回相同的哈希值與Java中相同的密碼,只有看起來我做的SHA-1哈希值的PHP代碼不會返回相同的SHA(-1,而不是Base64編碼,我認爲?)值與哈希值的Java Base64解碼值相比......這可能與我在PHP中的密碼不是UTF-8首先進行字節編碼(以及如何在PHP中執行此操作)?

p.s.

另一個奇怪的事情......我在Java中的密碼都是28characters長(通常是這樣的rnwn4zTNgH30l4pP8V05lRVGmF4=)......但這些密碼哈希的Base64().decode(hash)值(一個例子[[email protected])長10個字符。

我認爲Base64爲每3個章程(28或27,除了padding = charter,還有比這10個字符大三分之一多一個字符)做了額外的1個字符,所以我在做解碼調用錯誤莫名其妙嗎? ??

最重要的是,在PHP中,SHA-1密碼哈希值是40個字符(在UTF-8 mysql數據庫中),比如dd94709528bb1c83d08f3088d4043f4742891f4f

+0

您需要正確格式化您的代碼。在每一行之前放置四個空格或一個製表符。 – Donovan 2011-01-22 16:26:53

+0

@Alberteddu:可以通過選擇代碼並點擊'{}'圖標完成。 – SyntaxT3rr0r 2011-01-22 16:35:52

回答

5

[[email protected]絕對不是散列。這是隱含從byte[]轉換爲String的結果。

它看起來像你做這樣的事情:

String decodedHash = Base64().decode(hash); // Produces [[email protected] 

然而,散列的正確表示是一個字節數組:

byte[] decodedHash = Base64().decode(hash); 
3

我通常使用Java做些什麼來計算SHA與sha1()函數完全相同的-1哈希值如下所示。關鍵是toHexString用於以可打印的方式顯示原始字節。如果您使用PHP函數並希望獲得相同結果的卷積進程,則需要在PHP中使用參數$ raw_output爲true以獲取原始字節並應用Base64。 Full source code

/** 
* Compute a SHA-1 hash of a String argument 
* 
* @param arg the UTF-8 String to encode 
* @return the sha1 hash as a string. 
*/ 
public static String computeSha1OfString(String arg) { 
    try { 
     return computeSha1OfByteArray(arg.getBytes(("UTF-8"))); 
    } catch (UnsupportedEncodingException ex) { 
     throw new UnsupportedOperationException(ex); 
    } 
} 

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

private static String toHexString(byte[] v) { 
    StringBuilder sb = new StringBuilder(v.length * 2); 
    for (int i = 0; i < v.length; i++) { 
     int b = v[i] & 0xFF; 
     sb.append(HEX_DIGITS.charAt(b >>> 4)).append(HEX_DIGITS.charAt(b & 0xF)); 
    } 
    return sb.toString(); 
} 
1

PHP的sha1()編碼輸出作爲默認使用十六進制的每個字節,但是你可以通過true作爲第二個參數得到的原始輸出:

$digest = sha1($password, true); // This returns the same string of bytes as md.digest() 

然後通過消化來base64_encode並完成:

base64_encode(sha1($password, true)); 

這將返回與您的java代碼完全相同的SHA-1散列值。