加密與編碼是 Web 安全的基石。PHP 內置了多種函數,但它們的適用場景、安全性、可逆性差異巨大。本文系統梳理 5 大常用函數的原理、參數、代碼示例及最佳實踐,助你避開安全坑。
string md5 ( string $str [, bool $raw_output = false ] )
raw_output=true 時輸出 16 字節二進制。md5(md5($pwd).$salt)、或配合 hash_hmac('md5', $data, $key),但仍不如 bcrypt/Argon2。<?php $pwd = 'jellybool.com'; echo md5($pwd); // 7bf02cf0f4af6da4accbc73d2a175476 echo md5(md5($pwd)); // 864704bb35754f8cd0232cba6b91521b 雙重增加破解難度 ?>
string crypt ( string $str [, string $salt ] )
$1$ 開頭為 MD5、$2y$ 為 Blowfish/bcrypt)。crypt($pwd, '$2y$10$' . $salt) 使用 bcrypt,成本因子 10,抗 GPU 破解。password_hash() / password_verify(),它們封裝了 bcrypt/Argon2 並自動處理鹽值。<?php $pwd = 'jellybool.com'; echo crypt($pwd); // $1$Fe0.qr5.$WOhkI4/5VPo7n7TnXHh5K (MD5-based) echo crypt($pwd, 'je'); // je7fNiu1KNaEs (DES-based, 僅前 2 字符有效,極不安全) echo crypt($pwd, '$1$jellybool$'); // $1$jellyboo$DxH7wF7SygRpWb6XBBgfH/ (MD5-based, 鹽值 8 字符) ?>
string sha1 ( string $str [, bool $raw_output = false ] )
md5(sha1($str)) 略微增加破解成本,但本質未變。string urlencode ( string $str ) string urldecode ( string $str )
-_.)轉為 %XX 格式,空格變 +。確保 URL 參數不破壞結構。?=>%3F, ==>%3D, %=>%25, &=>%26, 空格=>+。<?php $url = 'jellybool.com?jellybool=true + 4-3%5= \& @!'; $encoded = urlencode($url); // jellybool.com%3Fjellybool%3Dtrue+%2B+4-3%255%3D+%5C%26+%40%21 echo urldecode($encoded); // 完美還原 // 解決參數值包含 & 導致解析錯誤 $username = 'jelly&bool'; $safeUrl = "jellybool.com?username=" . urlencode($username) . "&password=jelly"; ?>
string base64_encode ( string $data ) string base64_decode ( string $data )
A-Z a-z 0-9 + / =。<?php $imgUrl = 'https://example.com/logo.png'; $data = file_get_contents($imgUrl); $base64 = base64_encode($data); // 輸出: data:image/png;base64,$base64 可直接用于?>
| 需求 | 推薦方案 | 禁用/慎用 |
|---|---|---|
| 用戶密碼存儲 | password_hash($pwd, PASSWORD_BCRYPT/ARGON2ID) + password_verify() | MD5, SHA1, Crypt(手動), 明文 |
| API 簽名/防篡改 | hash_hmac('sha256', $data, $secret_key) | 單純 MD5/SHA1 |
| URL 參數傳遞 | urlencode() / http_build_query() | 手動拼接 |
| 二進制嵌入文本 | base64_encode() | 無 |
| 文件完整性校驗 | hash_file('sha256', $file) | MD5 (大文件碰撞風險) |
<?php
// 註冊/修改密碼
$hash = password_hash($_POST['password'], PASSWORD_ARGON2ID); // PHP 7.2+
// 存入資料庫 $hash (包含算法、成本、鹽值)
// 登錄驗證
if (password_verify($_POST['password'], $dbHash)) {
// 成功
// 可選:檢查是否需要重新哈希 (算法升級、成本調整)
if (password_needs_rehash($dbHash, PASSWORD_ARGON2ID)) {
$newHash = password_hash($_POST['password'], PASSWORD_ARGON2ID);
// 更新資料庫
}
}
?>
這組 API 自動處理鹽值生成、算法標識、驗證、升級,是 PHP 5.5+ 版本處理密碼的**唯一正確方式**。