2011-04-19 49 views
23

我試圖創建一個二進制文件(FLV/F4V等)的校驗和來驗證服務器和客戶端計算機之間的文件的內容。在客戶端計算機上運行的應用程序是基於python的,而服務器使用的是PHP。Python和PHP之間的MD5哈希差異?

PHP代碼如下:

$fh = fopen($filepath, 'rb'); 
$contents = fread($fh, filesize($filepath)); 
$checksum = md5(base64_encode($contents)); 
fclose($fh); 

Python代碼如下:

def _get_md5(filepath): 
    fh = open(filepath, 'rb') 
    md5 = hashlib.md5() 
    md5.update(f.read().encode('base64')) 
    checksum = md5.hexdigest() 
    f.close() 
    return checksum 
特定的文件我測試

,在PHP和Python的MD5哈希字符串是如下,分別爲:

cfad0d835eb88e5342e843402cc42764 
0a96e9cc3bb0354d783dfcb729248ce0 

服務器正在運行CentOS,而客戶端是MacOSX環境。我將不勝感激任何幫助理解爲什麼這兩個產生不同的哈希結果,或者如果我忽視了一些(我對Python相對來說比較新......)。謝謝!

[驗屍:問題最終是Python和PHP的base64編碼變種之間的區別。 MD5在兩個腳本平臺之間工作原理是相同的(至少在Python中使用.hexdigest())。]

+1

我敢肯定的是,文件的Base64表示是不同的,而不是md5算法,可以檢查? – htf 2011-04-19 16:19:36

+7

爲什麼要用base64呢?爲什麼不只是md5的原始二進制文件? – 2011-04-19 16:22:09

+2

任何你第一次對文件內容進行base64編碼的原因? md5函數也會高興地突破原始二進制數據。正如htf所示,從等式中刪除base64,看看會發生什麼。如果出於某種原因,python和php行包裝base64數據(例如,用於電子郵件插入),並選擇一個不同的包裝點,這將拋出散列,並且你永遠不會知道,因爲你沒有檢查base64輸出爲了平等第一。 – 2011-04-19 16:22:09

回答

25

我寧願假設的base64實現不同。

編輯

PHP:

php -r 'var_dump(base64_encode(str_repeat("x", 10)));' 
string(16) "eHh4eHh4eHh4eA==" 

的Python(注意尾隨換行符):

>>> ("x" * 10).encode('base64') 
'eHh4eHh4eHh4eA==\n' 
+6

對問題的評論提出了另一個重要問題:需要base64,如果你想要一個散列,你可以直接散列字符串。 – soulmerge 2011-04-19 16:27:34

4

問題似乎是,您的base-64編碼文件數據,改變了二進制數據的結構,在PHP我belive,它不base_64編碼文件。

給這個一展身手:

def md5_file(filename): 
    //MD5 Object 
    crc = hashlib.md5() 
    //File Pointer Object 
    fp = open(filename, 'rb') 

    //Loop the File to update the hash checksum 
    for i in fp: 
     crc.update(i) 

    //Close the resource 
    fp.close() 

    //Return the hash 
    return crc.hexdigest() 

並在PHP中使用md5_file,看看有沒有相應的工作。

蟒蛇摘自:http://www.php2python.com/wiki/function.md5-file/

4

Python使用.encode時,字符串附加換行'\ n',因此md5函數的輸入字符串是不同的。在Python bug跟蹤器中的This問題詳細解釋它。見下面是它的要點:

>>> import base64 
>>> s='I am a string' 
>>> s.encode('base64') 
'SSBhbSBhIHN0cmluZw==\n' 
>>> base64.b64encode(s) 
'SSBhbSBhIHN0cmluZw==' 
>>> s.encode('base64')== base64.b64encode(s)+'\n' 
True