當前位置: 首頁> 最新文章列表> PHP hash_equals 函數與strcmp 的區別與優勢

PHP hash_equals 函數與strcmp 的區別與優勢

gitbox 2025-05-26

在PHP 中,當我們需要比較兩個字符串是否相等時,常用的方法是strcmp函數。但隨著安全需求的提升,PHP 5.6 引入了一個專門用於安全比較的函數hash_equals 。本文將詳細介紹這兩個函數的區別,並解釋為什麼在某些場景下推薦使用hash_equals


1. strcmp 和hash_equals 的基本功能對比

  • strcmp(string $str1, string $str2): int
    strcmp用於按字典順序比較兩個字符串。它返回一個整數值:

    • 0 表示兩個字符串完全相同

    • 負數表示第一個字符串小於第二個字符串

    • 正數表示第一個字符串大於第二個字符串

  • hash_equals(string $known_string, string $user_string): bool
    hash_equals專門用於比較兩個字符串是否完全相同,且比較過程是防止計時攻擊(Timing Attack)的安全方式。它返回布爾值:

    • true表示兩個字符串完全相等

    • false表示不相等


2. 計時攻擊(Timing Attack)及其風險

在某些安全場景下,比如驗證密碼哈希、API 密鑰、簽名等敏感數據時,攻擊者可能通過測量比較函數的執行時間,推斷出字符串中相同部分的長度,進而逐步猜測正確的密鑰。普通的字符串比較函數(如strcmp )在發現第一個不同字符時就會立即返回,導致比較時間與字符串相等的部分長度有關,容易洩漏信息。


3. hash_equals 的安全優勢

hash_equals設計時特別考慮了防止計時攻擊,其比較時間不會隨兩個字符串中相同部分的長度變化而變化,而是固定執行時間,從而降低洩漏信息的風險。


4. 實際代碼示例對比

<?php
// 使用 strcmp 比較兩個字符串
$known = 'securetoken123';
$userInput = 'securetoken124';

if (strcmp($known, $userInput) === 0) {
    echo "匹配成功(strcmp)";
} else {
    echo "匹配失敗(strcmp)";
}
?>
 <?php
// 使用 hash_equals 比較兩個字符串
$known = 'securetoken123';
$userInput = 'securetoken124';

if (hash_equals($known, $userInput)) {
    echo "匹配成功(hash_equals)";
} else {
    echo "匹配失敗(hash_equals)";
}
?>

注意,在上面代碼中的字符串比較, strcmp會在第一個不同字符時立即返回,而hash_equals會執行完整比較。


5. 何時推薦使用hash_equals?

  • 驗證密碼哈希:雖然大多數密碼驗證都通過password_verify ,但如果自己實現對比哈希時,推薦使用hash_equals

  • 比較加密簽名:例如HMAC、JWT 等,避免密鑰被猜測。

  • 比較安全令牌:API 密鑰、訪問令牌、驗證碼等。

簡單來說,任何安全相關的字符串比較,都建議使用hash_equals


6. 使用注意事項

  • hash_equals要求傳入的兩個參數類型為字符串,且長度相同,否則會直接返回false

  • 在使用hash_equals前,建議確保輸入字符串都為字符串類型且長度一致,避免意外錯誤。


結語

雖然strcmp是常用且功能強大的字符串比較函數,但在安全敏感的場合, hash_equals因其防止計時攻擊的特性,是更合適的選擇。正確使用hash_equals能有效提升應用的安全性,避免潛在的攻擊風險。