PHP 中的 == 和「隱式轉換」

引言

最近,在 Hacker News 上有一篇帖子(https://news.ycombinator.com/item?id=9484757),提到了一種探測網站密碼加密方式的方法。php

<?php
var_dump(md5('240610708') == md5('QNKCDZO'));
var_dump(sha1('aaroZmOk') == sha1('aaK1STfY'));
var_dump('0x1234Ab' == '1193131');

結果都是:函數

bool(true)
bool(true)
bool(true)

若是在一個網站,使用240610708做爲密碼,而後用QNKCDZO登錄,結果能夠登陸的話,說明密碼是以MD5方式保存的。相似的,若是用aaroZmOk做爲密碼,而後用aaK1STfY登錄,結果能夠登陸的話,說明密碼是以sha1方式保存的。第三種固然就是明文存儲了。網站

分析

以第一組數爲例:加密

md5('240610708') 的結果是:0e462097431906509019562988736854
md5('QNKCDZO') 的結果是:0e830400451993494058024219903391

因爲 PHP 是弱類型語言,在使用 == 號時,若是比較一個數字和字符串或者比較涉及到數字內容的字符串,則字符串會被轉換爲數值而且比較按照數值來進行。此規則也適用於 switch 語句。上述例子中的兩個字符串剛好以 0e 的科學記數法開頭,字符串被隱式轉換爲浮點數,實際上也就等效於 0×10^0 ,所以比較起來是相等的。code

相似

<?php
var_dump( 0 == "a" );
var_dump( "0" == "a" );

第一個返回的是 true,第二個返回的是 falsemd5

結論

PHP中的Hash校驗,應該使用「===」,而不該該使用「==」。另外若是生產環境版本足夠高的話(PHP >= 5.6.0),最好使用 hash_equals() 函數。字符串

hash_equals() 在比較兩個字符串,不管它們是否相等,函數的時間消耗是恆定的,能夠用來防止時序攻擊。get

相關文章
相關標籤/搜索