パスワード生成器
長さと文字セットをカスタマイズして強力なランダムパスワードを生成
パスワード生成器とは?
パスワード生成器は、ユーザーアカウント・API キー・データベース認証情報・暗号化シークレットとして使用するためのランダムな文字列を生成するツールです。人間が考えたパスワードとは異なり、生成されたパスワードは可能な文字の組み合わせ空間全体から無作為に選択されるため、辞書攻撃やパターンに基づく推測に対して高い耐性を持ちます。このツールはブラウザに組み込まれた暗号的乱数生成器を使用して、オンラインで強力なランダムパスワードを生成します。
パスワードの強度は「長さ」と「文字の多様性」という2つの要素に依存します。大文字・小文字・数字・記号を組み合わせた20文字のパスワードは、約131ビットのエントロピーを持ちます。その水準では、1秒間に1兆回の推測を行うブルートフォース攻撃でも、すべての組み合わせを試し終えるのに宇宙の年齢より長い時間が必要です。計算式はシンプルです: エントロピー = 文字数 × log2(文字セットのサイズ)。
NIST SP 800-63B などの標準規格は、検証者が上限を設けず少なくとも8文字のパスワードを推奨しており、「記号を1つ必ず含む」といった強制的な構成ルールは避け、より長いパスフレーズを優先するよう促しています。マシン間認証やサービスアカウントの認証情報には、大多数のセキュリティフレームワークおよびコンプライアンス基準において、完全な文字セットから選択した20文字以上のランダムな文字列が受け入れられる基準となっています。
パスワード生成器を使う理由
人間は優れた乱数生成器ではありません。パスワードを使い回したり、辞書に載っている単語を選んだり、文字を予測可能なパターンで置き換えたり(@ を a の代わりに、3 を e の代わりに使うなど)、短い文字列にしがちです。パスワード生成器は、このプロセスから人間のバイアスを取り除きます。
パスワード生成器の活用シーン
パスワードエントロピーの参考値
エントロピーはパスワードの予測困難さをビット数で表したものです。log2(文字セットのサイズ ^ 文字数) で計算されます。エントロピーが高いほど、攻撃者が試すべき組み合わせが多くなります。NIST および OWASP は高セキュリティのアプリケーションには少なくとも80ビットのエントロピーを推奨しています。
| 文字数 | 文字セット | エントロピー | ブルートフォース所要時間 |
|---|---|---|---|
| 8 | lower + digits | ~41 bits | Minutes to hours |
| 12 | lower + upper + digits | ~71 bits | Centuries (offline) |
| 16 | all character sets | ~105 bits | Beyond brute-force |
| 20 | all character sets | ~131 bits | Beyond brute-force |
| 32 | all character sets | ~210 bits | Beyond brute-force |
| 64 | all character sets | ~419 bits | Beyond brute-force |
解読時間は最新の GPU を使ったオフライン攻撃で1秒間に1兆回の推測を想定しています。レートリミットのかかったオンライン攻撃はこれより何桁も遅くなります。
CSPRNG と Math.random() — パスワード生成における違い
乱数の生成源はパスワードの長さと同じくらい重要です。予測可能な乱数生成器で生成されたパスワードは、アルゴリズムとシードの状態を知っている攻撃者によって復元される可能性があります。このツールは crypto.getRandomValues() を使用しています。これはすべてのモダンブラウザに組み込まれた暗号的安全な疑似乱数生成器(CSPRNG)です。
コード例
さまざまな言語でプログラム的にパスワードを生成する例です。以下のすべての例では、Math.random() や同等の脆弱な PRNG ではなく、暗号的に安全な乱数生成源を使用しています。
// Generate a random password in the browser or Node.js 19+
function generatePassword(length = 20) {
const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*'
const values = new Uint32Array(length)
crypto.getRandomValues(values)
return Array.from(values, v => charset[v % charset.length]).join('')
}
console.log(generatePassword()) // → "kR7!mZp$Xw2&nLq9@Yf3"
console.log(generatePassword(32)) // → "Hd4%tNx!Qw8#mKp2Rv6&Zj0*Ls3Yb7@"import secrets
import string
def generate_password(length: int = 20) -> str:
"""Generate a cryptographically secure random password."""
alphabet = string.ascii_letters + string.digits + string.punctuation
return ''.join(secrets.choice(alphabet) for _ in range(length))
# Single password
print(generate_password()) # → "kR7!mZp$Xw2&nLq9@Yf3"
# Batch of 5 passwords
for _ in range(5):
print(generate_password(24))
# Ensure at least one char from each category
def generate_strong(length: int = 20) -> str:
required = [
secrets.choice(string.ascii_uppercase),
secrets.choice(string.ascii_lowercase),
secrets.choice(string.digits),
secrets.choice(string.punctuation),
]
remaining = length - len(required)
alphabet = string.ascii_letters + string.digits + string.punctuation
all_chars = required + [secrets.choice(alphabet) for _ in range(remaining)]
secrets.SystemRandom().shuffle(all_chars)
return ''.join(all_chars)# OpenSSL — generate 32 random bytes, base64-encode openssl rand -base64 32 # → "x7Kp2mNqR4wZ8vLs1Yb0Hd6tFj3Xc9Ga5eUi+Wo=" # /dev/urandom with tr — alphanumeric + symbols, 20 chars tr -dc 'A-Za-z0-9!@#$%^&*' < /dev/urandom | head -c 20; echo # → "kR7!mZp$Xw2&nLq9@Yf3" # pwgen (install: apt install pwgen / brew install pwgen) pwgen -sy 20 5 # Generates 5 passwords, 20 chars each, with symbols
package main
import (
"crypto/rand"
"fmt"
"math/big"
)
func generatePassword(length int) (string, error) {
charset := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()"
result := make([]byte, length)
for i := range result {
idx, err := rand.Int(rand.Reader, big.NewInt(int64(len(charset))))
if err != nil {
return "", err
}
result[i] = charset[idx.Int64()]
}
return string(result), nil
}
func main() {
pwd, _ := generatePassword(20)
fmt.Println(pwd) // → "kR7!mZp$Xw2&nLq9@Yf3"
}