密碼生成與驗證工具
產生強密碼與口令短語,支援批次生成、唯一性、強度與策略驗證,並提供多語言程式碼範例與實用知識。
密碼雜湊速查表
Argon2id
- 使用 Argon2id,並設定合理的記憶體硬參數
- 迭代次數 ≥ 2 次,記憶體 ≥ 64MB(依環境調校)
- 每位使用者儲存獨立鹽值;可選在應用層使用 pepper
PBKDF2
- 選擇 SHA-256 或 SHA-512,疊代次數 ≥ 210k(依需求調校)
- 每個雜湊使用獨特鹽值;支援參數升級
- 使用者下次登入時遷移至更高成本參數
BCrypt
- 成本值 10–14,視伺服器能力而定
- 避免截斷問題;應對完整密碼進行雜湊
- 對驗證端點進行限流與監控
參考:NIST SP 800-63B、OWASP ASVS。參數需與硬體能力及 SLO 匹配。
密碼強度評估
強度估算基於熵值:entropy = log2(字元池大小) × 長度。更大的字元池與更長的長度能提升抗猜測能力。
- 弱: < 50 bits —— 僅適用於一次性/低價值場景
- 普通: 50–80 bits —— 適合低風險場景
- 強: 80–110 bits —— 推薦的預設目標
- 極強: > 110 bits —— 適用於管理員/關鍵帳戶
提示:真實攻擊模型可能有所不同;請避免密碼重複使用,並啟用多重驗證(MFA)。
使用說明
- 選擇長度與字元集(小寫/大寫/數字/符號);必要時啟用「避免相似字元」與「必須包含每類」
- 需要更精細控制時:排除特定字元或字元組,或選取符號分組
- 點擊生成;如需多組結果,啟用批次生成並可一鍵複製全部
- 想驗證現有密碼,請使用「策略測試器」;想建立易記口令,請使用「口令短語生成器」
功能特性
- 安全隨機來源(Web Crypto)
- 可設定字元集與符號分組
- 相似字元過濾與自訂排除
- 批次生成、唯一性保障與去重統計
- 強度與熵值指標
- 策略測試器與口令短語生成器
- 多語言程式碼範例 (JS、Python、PHP、Go、Java、C#、Rust)
- 一鍵複製(單條/全部)
密碼知識庫
1) 密碼強度與熵
- 熵 ≈ log2(字元池大小) × 長度;長度的貢獻通常更大
- 建議目標:一般帳號 ≥ 80 bits;高權限/財務帳戶 ≥ 110 bits
- 更大的字元池 + 更長的長度 → 更能抵抗猜測
2) 長度 vs 複雜度
- 盲目堆疊符號不如增加長度有效
- 避免固定且可預測的模式(例如每次都「首字母大寫+結尾數字!」)
- 優先確保足夠長度,再適度提升字元多樣性
3) 常見誤區與反模式
- 鍵盤序列(如 qwerty)、重複區塊、生日/年份等易被規則命中
- 「根密碼+網站後綴」是變體複用,風險集中且容易被猜出
- 不要在多個網站重複使用同一密碼
4) 密碼管理建議
- 使用密碼管理器;每個網站使用唯一密碼;重要帳戶啟用 MFA
- 避免在公開管道明文傳遞密碼;必要時使用「發音友好型」口令
- 發現洩露或重複使用時,立即更換並確保唯一性
5) 口令短語(Passphrase)指南
- 四至六個詞的組合通常既強壯又易記
- 混合分隔符、首字母大寫、插入數字可提升強度與可讀性
- 避免直接拼接常見短語、歌詞或名言
密碼安全實踐指南
最佳實踐
- 盡量使用足夠長度:一般帳戶 16+,關鍵帳戶 24+
- 記憶需求可優先使用口令短語;隨機高強度密碼建議交由密碼管理器保存
- 儘可能開啟多因素認證(MFA)
- 不同網站不要重複使用密碼,每個帳戶都應唯一
熵與強度
熵反映基於長度與字元池大小的不可預測性,熵位數越高通常越強。
- 優先增加長度以獲得最大效益
- 在可行情況下使用多種字元集
- 過度排除字元會縮小字元池、降低強度
策略與輪換
- 比起複雜的組成規則,更偏向長度與禁用常見/洩露密碼的黑名單
- 避免頻繁強制輪換;僅在出現洩露或風險時才更改
- 使用洩露密碼名單阻止常見/洩露密碼
口令短語
- 使用 4–6 個隨機詞並用分隔符連接,例如 lake-CARROT-planet_7
- 避免引用名句/歌詞等常見短語;隨機性比「機智」更重要
- 關鍵帳戶建議使用密碼管理器保存真正高熵的隨機密碼
生成設定提示
- 「Require each selected set」可確保每類至少出現一次
- 「Avoid similar」提升可讀性,但會略微降低字元池大小
- 符號可限制為目標系統可接受的子集
伺服器端儲存
- 切勿明文儲存;使用強哈希(Argon2id/PBKDF2/BCrypt)並配鹽
- 合理設定參數(記憶體/時間/成本),必要時使用 pepper
- 限制速率並監控失敗嘗試;遭受攻擊時新增驗證碼或裝置校驗
多因素與找回
- 優先使用 TOTP/硬體金鑰;盡量避免 SMS
- 保護找回流程:採用多因子或郵件驗證並設定冷卻期
- 提供備用恢復碼並建議用戶妥善保管
暴力破解防護
- 使用漸進式延遲/鎖定與 IP/裝置風險評分
- 為 API 與登入表單配置 WAF/限流
- 監測撞庫並鼓勵用戶使用唯一密碼
本地儲存與處理
- 使用可靠的密碼管理器進行保存與自動填入
- 不要透過聊天/郵件明文分享密碼;團隊請使用機密管理工具
- 如需離線記錄,請確保實體安全
聲明:本工具在瀏覽器本地使用 Web Crypto 產生密碼;不會將資料傳送至伺服器。
如何透過程式語言產生密碼
JavaScript(Web Crypto)
function randomPassword(length = 16, sets = {lower:true, upper:true, digits:true, symbols:true}) {
const pools = {
lower: 'abcdefghijklmnopqrstuvwxyz',
upper: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
digits: '0123456789',
symbols: '!@#$%^&*+-=_~`|/?()[]{}<>,.;:\'\"'
};
let pool = '';
for (const k of Object.keys(sets)) if (sets[k]) pool += pools[k];
if (!pool) throw new Error('No charset');
const bytes = new Uint32Array(length);
crypto.getRandomValues(bytes);
let out = '';
for (let i = 0; i < length; i++) out += pool[bytes[i] % pool.length];
return out;
}
Python(secrets)
import secrets
def random_password(length=16, lower=True, upper=True, digits=True, symbols=True):
pools = {
'lower': 'abcdefghijklmnopqrstuvwxyz',
'upper': 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'digits': '0123456789',
'symbols': '!@#$%^&*+-=_~`|/?()[]{}<>,.;:\'\"'
}
pool = ''.join(v for k, v in pools.items() if locals()[k])
if not pool:
raise ValueError('No charset')
return ''.join(secrets.choice(pool) for _ in range(length))
PHP(random_int)
function random_password($length = 16, $sets = ['lower'=>true,'upper'=>true,'digits'=>true,'symbols'=>true]) {
$pools = [
'lower' => 'abcdefghijklmnopqrstuvwxyz',
'upper' => 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'digits' => '0123456789',
'symbols' => '!@#$%^&*+-=_~`|/?()[]{}<>,.;:\'\"'
];
$pool = '';
foreach ($sets as $k => $on) if ($on) $pool .= $pools[$k];
if ($pool === '') throw new Exception('No charset');
$out = '';
for ($i = 0; $i < $length; $i++) {
$out .= $pool[random_int(0, strlen($pool)-1)];
}
return $out;
}
Go(crypto/rand)
package main
import (
"crypto/rand"
"math/big"
)
func RandomPassword(length int, pool string) (string, error) {
out := make([]byte, length)
for i := 0; i < length; i++ {
nBig, err := rand.Int(rand.Reader, big.NewInt(int64(len(pool))))
if err != nil { return "", err }
out[i] = pool[nBig.Int64()]
}
return string(out), nil
}
Java(SecureRandom)
import java.security.SecureRandom;
public class Pw {
static final String POOL = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*+-=_~`|/?()[]{}<>,.;:'\"";
static final SecureRandom SR = new SecureRandom();
static String randomPassword(int length) {
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i++) {
int idx = SR.nextInt(POOL.length());
sb.append(POOL.charAt(idx));
}
return sb.toString();
}
}
C#(.NET RandomNumberGenerator)
using System;
using System.Security.Cryptography;
public static class Pw {
public static string RandomPassword(int length, string pool) {
using var rng = RandomNumberGenerator.Create();
var bytes = new byte[length];
rng.GetBytes(bytes);
var chars = new char[length];
for (int i = 0; i < length; i++) {
chars[i] = pool[bytes[i] % pool.Length];
}
return new string(chars);
}
}
Rust(rand + getrandom)
use rand::rngs::OsRng;
use rand::RngCore;
fn random_password(length: usize, pool: &str) -> String {
let mut bytes = vec![0u8; length];
OsRng.fill_bytes(&mut bytes);
let chars: Vec = pool.chars().collect();
bytes
.iter()
.map(|b| chars[(*b as usize) % chars.len()])
.collect()
}
fn main() {
let pool = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*+-=_~`|/?()[]{}<>,.;:'\"";
let pw = random_password(16, pool);
println!("{}", pw);
}