首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP生成隨機密碼:可配置字符集、長度、熵源、加密安全的最佳實踐

     編輯:PHP 相關知識

隨機密碼生成:拒絕 `rand()`/`mt_rand()`,擁抱 `random_bytes()`/`random_int()`

PHP 7+ 提供密碼學安全的隨機源:**嚴禁在安全相關場景使用 `rand()`、`mt_rand()`、`shuffle()`、`uniqid()`、時間戳**。

核心函數:安全、可配置、無偏差

<?php
/**
 * 生成加密安全的隨機密碼
 * @param int $length 密碼長度 (建議 12-32)
 * @param string $charset 字符集 (默認含大小寫字母、數字、符號)
 * @param bool $requireAll 是否強制包含各類字符至少一個
 * @return string
 */
function generateSecurePassword(
    int $length = 16,
    string $charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*_-+=',
    bool $requireAll = true
): string {
    if ($length < 8) throw new InvalidArgumentException('Length must be >= 8');
    $charsetLen = strlen($charset);
    $bytes = random_bytes($length * 2); // 獲取足夠熵
    $password = '';
    $hasLower = $hasUpper = $hasDigit = $hasSymbol = false;
    $symbolSet = '!@#$%^&*_-+=';

    for ($i = 0; $i < $length; $i++) {
        // 無偏差採樣:拒絕採樣法
        $maxValid = (256 / $charsetLen) * $charsetLen - 1;
        do {
            $byte = $bytes[$i * 2] | ($bytes[$i * 2 + 1] << 8);
        } while ($byte > $maxValid);
        $char = $charset[$byte % $charsetLen];
        $password .= $char;

        if (ctype_lower($char)) $hasLower = true;
        elseif (ctype_upper($char)) $hasUpper = true;
        elseif (ctype_digit($char)) $hasDigit = true;
        elseif (str_contains($symbolSet, $char)) $hasSymbol = true;
    }

    // 強制包含各類字符
    if ($requireAll && !($hasLower && $hasUpper && $hasDigit && $hasSymbol)) {
        return generateSecurePassword($length, $charset, $requireAll); // 遞歸重試 (極少發生)
    }
    return $password;
}

// 使用
echo generateSecurePassword(16);           // 默認字符集
echo generateSecurePassword(20, 'abcdefghijklmnopqrstuvwxyz0123456789'); // 易輸入字符集
echo generateSecurePassword(32, '0123456789abcdef'); // 十六進制密鑰

進階:可發音/易記密碼(Diceware 風格)

function generatePassphrase(int $words = 4, string $separator = '-'): string {
    // 內建 EFF 大詞表精簡版 (實際用完整 7776 詞)
    $wordlist = ['apple','banana','cherry','dolphin','eagle','forest','guitar','horizon','island','journey',
                 'kangaroo','lemon','mountain','nebula','ocean','planet','quantum','river','sunset','tiger',
                 'umbrella','valley','waterfall','xenon','yacht','zebra'];
    $count = count($wordlist);
    $bytes = random_bytes($words * 2);
    $pass = [];
    for ($i = 0; $i < $words; $i++) {
        $idx = ($bytes[$i*2] | ($bytes[$i*2+1] << 8)) % $count;
        $pass[] = $wordlist[$idx];
    }
    return implode($separator, $pass);
}
echo generatePassphrase(5); // eagle-horizon-kangaroo-ocean-tiger

熵計算與強度評估

function passwordEntropy(string $password, int $charsetSize): float {
    return strlen($password) * log($charsetSize, 2); // bits
}
function passwordStrength(float $entropy): string {
    return match(true) {
        $entropy < 30 => 'Very Weak',
        $entropy < 60 => 'Weak',
        $entropy < 80 => 'Fair',
        $entropy < 100 => 'Strong',
        default => 'Very Strong',
    };
}
$pwd = generateSecurePassword(16);
echo "Entropy: " . passwordEntropy($pwd, 72) . " bits - " . passwordStrength(passwordEntropy($pwd, 72)) . "\n";

常見錯誤對照

最佳實踐清單

  • **註冊/重置密碼**:生成 16-20 位安全密碼,郵件發送,**強制首次登入修改**。
  • **API Key / Token**:`bin2hex(random_bytes(32))` (64 位十六進制) 或 `base64_encode(random_bytes(32))` (URL 安全)。
  • **加密密鑰**:`random_bytes(32)` 直接作為 AES-256 金鑰。
  • **存儲**:**永不**存儲明文密碼,僅存 `password_hash()` 結果。
  • **傳輸**:HTTPS 強制,密碼僅在 POST Body 傳輸,不在 URL/日誌中出現。

一行 `random_bytes()`,換來系統級安全基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
錯誤代碼問題修正
`substr(str_shuffle($charset), 0, $len)``str_shuffle` 使用 `mt_rand`,非加密安全`random_bytes` + 拒絕採樣
`$charset[mt_rand(0, $len-1)]`模運算偏差 + `mt_rand` 可預測拒絕採樣法
`uniqid('', true)`基於微秒時間,熵極低,可暴力枚舉永不用於密鑰/密碼
`md5(time().rand())`時間+偽隨機,完全不可用同上