Password 類別完整代碼
<?php
/**
* PHP 密碼產生器類別
* Version 1.0.0
*/
class Password {
protected $uppercase_chars = [];
protected $lowercase_chars = [];
protected $number_chars = [];
protected $special_chars = [];
protected $extra_chars = [];
protected $chars = []; // 最終字元池
public $length = 12;
public $uppercase = true;
public $lowercase = true;
public $number = true;
public $special = false;
public $extra = false;
public function __construct($length = 12) {
$this->length = $length;
$this->configure(true, true, true, false, false);
}
public function configure($uppercase = false, $lowercase = false, $number = false, $special = false, $extra = false) {
$this->chars = [];
$this->uppercase_chars = range('A', 'Z');
$this->lowercase_chars = range('a', 'z');
$this->number_chars = array_merge(range(0,9), range(0,9)); // 數字權重加倍
$this->special_chars = array('!','@','#','$','%','^','&','*','(',')');
$this->extra_chars = array('[',']','{','}','-','_','+','=','<','>','?','/','`','~','|',',','.',';',':');
if (($this->uppercase = $uppercase)) $this->chars = array_merge($this->chars, $this->uppercase_chars);
if (($this->lowercase = $lowercase)) $this->chars = array_merge($this->chars, $this->lowercase_chars);
if (($this->number = $number)) $this->chars = array_merge($this->chars, $this->number_chars);
if (($this->special = $special)) $this->chars = array_merge($this->chars, $this->special_chars);
if (($this->extra = $extra)) $this->chars = array_merge($this->chars, $this->extra_chars);
$this->chars = array_unique($this->chars);
}
public function generate() {
if (empty($this->chars)) return false;
$password = '';
$maxIndex = count($this->chars) - 1;
for ($i = 0; $i < $this->length; $i++) {
$password .= $this->chars[$this->random(0, $maxIndex)];
}
return $password;
}
// 加密安全隨機數
protected function random($min = 0, $max = 0) {
// PHP 7+ 建議用 random_int()
if (function_exists('random_int')) {
return random_int($min, $max);
}
// 相容舊版本:使用 openssl_random_pseudo_bytes
if (function_exists('openssl_random_pseudo_bytes')) {
$bytes = openssl_random_pseudo_bytes(4);
$val = unpack('L', $bytes)[1];
return $min + ($max - $min + 1) * $val / 0x100000000;
}
// 最後回退:mt_rand(非加密安全)
return mt_rand($min, $max);
}
}
使用範例
<?php
require_once 'Password.php';
// 預設:12 碼,大小寫+數字
$gen = new Password();
echo $gen->generate() . "\n"; // 例:K7mP9qW2zR4x
// 自訂:16 碼,全字元集
$gen2 = new Password(16);
$gen2->configure(true, true, true, true, true);
echo $gen2->generate() . "\n"; // 例:pK9@mL2#zX5!qW8~
// 只產生數字 PIN
$pin = new Password(6);
$pin->configure(false, false, true, false, false);
echo $pin->generate() . "\n"; // 例:839201
安全性分析與改進
| 原版問題 | 風險 | 改進 |
使用 uniqid(microtime().mt_rand()) 產生隨機種子 | 可預測,非加密安全 | 改用 random_int() (PHP 7+) 或 openssl_random_pseudo_bytes() |
sha1(md5()) 雜湊後取前 8 碼 | 熵損失,分布不均 | 直接使用 CSPRNG 產生整數 |
| 字元池權重不均(數字重複兩次) | 數字出現機率較高 | 明確權重配置或均等機率 |
現代化重寫(PHP 7.1+)
<?php
class SecurePasswordGenerator {
private $pools = [
'upper' => 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'lower' => 'abcdefghijklmnopqrstuvwxyz',
'digit' => '0123456789',
'special' => '!@#$%^&*()-_=+[]{}|;:,.<>?',
];
public function generate(int $length = 16, array $enabled = ['upper','lower','digit','special']): string {
$charset = '';
foreach ($enabled as $pool) {
if (isset($this->pools[$pool])) $charset .= $this->pools[$pool];
}
if (!$charset) throw new InvalidArgumentException('At least one pool required');
$bytes = random_bytes($length);
$password = '';
for ($i = 0; $i < $length; $i++) {
$password .= $charset[$bytes[$i] % strlen($charset)];
}
return $password;
}
}
線上工具參考