パスワードジェネレーター

安全なランダムパスワードを生成

「パスワード複雑性ルール」が間違っている理由(NIST SP 800-63B)

何十年もの間、パスワードに関する標準的なアドバイスは次のようなものでした — 大文字1つ以上、小文字1つ以上、数字1つ以上、特殊文字1つ以上。90日ごとに変更を強制。直近5個の再利用は禁止。ほとんどの企業のIT部門は今でもまさにこれを義務付けています。NIST — 連邦のサイバーセキュリティ指針を定める機関である米国国立標準技術研究所 — は2017年にSpecial Publication 800-63Bを公開し、2024年の大規模な改訂で明示的にこう述べています。それらはすべてやめなさい、と。 その根拠は、実世界の結果を測定したうえでの結論として、複雑性ルールと強制的なローテーションはパスワードを良くするどころか悪くする、というものです。「大文字+数字+特殊文字必須」を満たすよう強制されたユーザーの圧倒的多数がたどり着くのは、予測可能な変換 — Password1!、Password2!、Password3! — であり、人間の癖に基づく推測ツールはこれをいとも簡単に列挙します。90日ごとのローテーションを強制されると、ユーザーは直前のパスワードにカウンターを付け足すだけです。この「複雑性」は正規表現上は満たされているように見えますが、制約のない同等のパスワードと比べたエントロピーの増加は実質ゼロであり、その一方でユーザーの負担は急増し、パスワードは使い回されたり付箋に書かれたりします。 NIST SP 800-63Bのセクション5.1.1.2(memorized secrets)には現在こう書かれています。「検証者は、memorized secretに対して他の構成ルール(例: 異なる文字種の混在の要求)を課すべきではない(SHOULD NOT)。検証者は、memorized secretの恣意的な(例: 定期的な)変更を要求すべきではない(SHOULD NOT)。」変更が必要となるのは侵害の証拠がある場合のみです。最小長は8文字(ランダム生成なら6文字)、最大長は少なくとも64文字でなければならず(SHALL)、すべての印字可能なASCIIおよびUnicode文字を許可しなければなりません(MUST)。文字種の制限は撤廃されました。 複雑性ルールに取って代わるのはdenylist(拒否リスト)です。NISTは、パスワードを既知の侵害済み値のリストと照合することを義務付けています。すなわち、漏えいコーパスに現れたパスワード、辞書の単語、反復的なシーケンス(aaaaaaaa、qwerty)、コンテキスト固有の文字列(ユーザー名、サイト名)です。無料サービスのHave I Been Pwnedは、k-anonymity(k-匿名性)を用いて統合できるAPIを公開しています — SHA-1ハッシュの先頭5文字を送信し、そのプレフィックスを持つすべてのハッシュを受け取り、ローカルで照合します。2026年には何百万ものサービスがこれを利用しています。 以上から導かれる実用的なユーザー向けアドバイスは次のとおりです。長いランダムなパスワード(ジェネレーターで16文字以上)をサイトごとに1つずつ用意し、パスワードマネージャに保存する。あるいは覚えやすいパスフレーズ(リストからランダムに選んだ英単語4語以上、約50ビット以上のエントロピー)を使う。強制ローテーションはやめる。絵文字やUnicodeのブロックもやめる。特殊文字の強制もやめる。明らかに悪いものだけをブロックし、それを超える長さや形はユーザー自身に選ばせましょう。
// HIBP k-anonymity check (no full hash leaves your server)
async function checkPwned(password) {
  const hash = sha1Hex(password).toUpperCase();
  const prefix = hash.slice(0, 5);
  const suffix = hash.slice(5);
  const res = await fetch('https://api.pwnedpasswords.com/range/' + prefix);
  const text = await res.text();
  for (const line of text.split('\n')) {
    const [s, count] = line.trim().split(':');
    if (s === suffix) return parseInt(count, 10); // # of breaches
  }
  return 0;
}

// 2026 sign-up flow per NIST SP 800-63B
async function validateSignup(password) {
  if (password.length < 8) return 'too short';
  if (password.length > 64) return 'too long';
  if (/^(.)\1{4,}$/.test(password)) return 'too repetitive';
  const breached = await checkPwned(password);
  if (breached > 0) return `appeared in ${breached} breaches`;
  return null; // OK — no character-class checks
}

エントロピーの数学 — パスワードはどれくらいの長さにすべきか

パスワードの強度はShannonエントロピーで定量化されます — H = log2(N^L)。ここでNはアルファベットのサイズ、Lは長さです。単位はビットで、1ビット増えるごとに、攻撃者が必要とする平均推測回数は2倍になります。26文字のアルファベットから一様ランダムに選ばれた長さ10のパスワードは26^10 ≈ 1.4 × 10^14通りの値を取り得るため、log2(1.4 × 10^14) ≈ 47ビットのエントロピーを持ちます。同じ長さでも95文字の印字可能ASCIIアルファベットなら95^10 ≈ 6 × 10^19、約66ビットです。 鍵となる言葉は「一様ランダム」です。人間が選んだパスワードのエントロピーは、アルファベットが示唆する値よりはるかに低くなります。人間は空間のごく一部からしか選ばないからです。漏えいしたパスワードコーパス(RockYou、LinkedIn、Adobe)の研究は一貫して、人間が選んだ8文字のパスワードの実効エントロピーを18〜22ビットと推定しています — 50%の確率でクラックするのに必要な推測は約400万〜800万回で、単一のGPUなら数秒で十分に届く範囲です。同じ文字数をジェネレーターで生成すれば50ビット以上、約10^15回の推測が必要 — 専用ハードウェアでも年単位の時間になります。 較正のために現代の攻撃者の能力を挙げると、2026年、1枚のNvidia RTX 4090はbcrypt cost-5のハッシュを1日あたり約2000億回計算します。100枚のGPUからなる小規模クラスタなら20兆回に達します。クラウドで数時間レンタルしたhashcatクラスタなら、さらに桁違いの規模が可能です。パスワードハッシュアルゴリズムの防御的なwork factorは途方もなく大きな違いを生みます — bcrypt cost 12(現在のOWASP推奨)では同じハードウェアが1日約8万ハッシュしか計算できないため、総当たり攻撃を行う攻撃者はcost 5に比べて約2.5億倍の時間を要します。パスワードハッシュの選択が、パスワードの長さと少なくとも同じくらい重要である理由がここにあります。 2026年の運用指針(典型的なArgon2idのwork factorを前提) — 95記号のアルファベットから選んだ12文字のランダムなパスワードは約79ビットのエントロピーで、今後10年間は事実上クラック不可能です。16文字なら約105ビットで、国家主体級の予算をもってしても予見可能な将来にわたってクラック不可能です。パスフレーズの場合、7,776語のリスト(EFF wordlist)からランダムに選んだ4語はlog2(7776^4) ≈ 51ビット — 12文字のパスワードに匹敵しつつ、はるかに覚えやすいものです。5語なら65ビットで、人間が記憶して使う用途における実用上のスイートスポットです。 微妙な落とし穴があります — エントロピーは一様ランダムな選択を前提としています。ジェネレーターがMath.random()を使っているなら、そのエントロピーの主張は嘘です — V8のMath.random()はxorshift128+であり、攻撃者が出力をいくつか捕捉すれば予測可能な出力を生みます。パスワード級の出力には、必ずcrypto.getRandomValues(new Uint32Array(...))(ブラウザ)またはcrypto.randomBytes(...)(Node)を使ってください。その差は、79ビットのエントロピーとゼロの差です。
// Entropy table (assumes uniform random)
//
//  alphabet  | length | bits  | crack time at 1e9 guesses/sec
//  --------- | ------ | ----- | -----------------------------
//  26        |   8    |  37.6 |  2 minutes
//  62        |   8    |  47.6 |  1 day
//  95        |   8    |  52.5 |  ~50 days
//  95        |  12    |  78.7 |  ~10 million years
//  95        |  16    | 105.0 |  ~10^15 years (heat death of sun)
//
// — and remember: real cracking goes through Argon2id which is
//   ~10^6 to ~10^9 times slower than raw hashing.

// CORRECT: cryptographic random
function generate(length, alphabet) {
  const out = new Array(length);
  const r = new Uint32Array(length);
  crypto.getRandomValues(r);
  for (let i = 0; i < length; i++) out[i] = alphabet[r[i] % alphabet.length];
  return out.join('');
}

// WRONG: Math.random — predictable, NOT for passwords
function bad(length) {
  let s = '';
  for (let i = 0; i < length; i++) s += String.fromCharCode(97 + Math.floor(Math.random() * 26));
  return s;
}

// EFF passphrase
import wordlist from './eff_large_wordlist.json'; // 7776 words
function passphrase(n = 5) {
  const r = new Uint32Array(n);
  crypto.getRandomValues(r);
  return [...r].map(x => wordlist[x % 7776]).join('-');
}

Passkey、FIDO2、WebAuthn — パスワード後の世界

パスワードには、どれだけ長くしても、どれだけハッシュ化を工夫しても直せない構造的な問題があります — bearer secret(持参人秘密)であるという点です。ユーザーがそれを知り、サーバーがそのハッシュを保存し、ネットワークがそれを運びます。その秘密が存在するあらゆる場所で、フィッシング、漏えい、傍受、リプレイが起こり得ます。Passkey(パスキー)は、これに対する業界の足並みをそろえた答えです。 Passkeyは、ユーザーのデバイスで生成され、デバイスのセキュアエンクレーブ(Apple Secure Enclave、Android StrongBox、Windows HelloのTPM、YubiKeyのようなハードウェアFIDO2キー)に保存される公開鍵・秘密鍵のペアです。サインアップ時にデバイスが鍵ペアを生成し、公開鍵だけをサーバーに送信します。サインイン時には、サーバーがランダムなchallengeを送り、デバイスが秘密鍵でそのchallengeに署名し、サーバーが公開鍵で検証します。秘密鍵は決してデバイスを離れません。challengeはログインのたびに変わります。フィッシングの対象となる共有秘密は存在しません。 標準は次のとおりです — FIDO2(FIDO Allianceによる包括的枠組み)、WebAuthn(W3CのブラウザAPI、2019年からRecommendationステータス)、CTAP2(ブラウザと認証器ハードウェアの間のプロトコル)。Apple、Google、Microsoft、Mozillaは2022〜2023年に足並みをそろえてpasskeyサポートを出荷し、Apple iCloud KeychainとGoogle Password Managerはエンドツーエンド暗号化を用いてユーザーのデバイス間でpasskeyを複製します。2026年時点で、すべての主要サイト(Google、Apple、Microsoft、GitHub、PayPal、Amazon、Shopifyなど)がpasskeyのみのサインインをサポートしています。 フィッシング耐性は構造的なものです。WebAuthnの署名にはrelying party identifier(ドメイン名)が含まれ、ブラウザは誤ったoriginでのpasskeyの使用を拒否します。google.com.attacker.exampleにGoogleの資格情報を入力するようだまされたユーザーでも、そこでGoogleのpasskeyを使うことはできません — ブラウザがoriginを確認し、デバイスが署名を拒否するからです。FIDOが、消費者向けに出荷された中で単独で最も効果的なアンチフィッシング技術である理由はここにあります。 実装パターン(サーバー側) — サインアップ時にWebAuthnのregistration responseを受け取り、attestationを検証し、そのユーザーの公開鍵 + credential ID + counterを保存します。サインイン時にはランダムなchallengeを生成してクライアントに送り、署名されたassertionを受け取り、保存済みの公開鍵で署名を検証し、counterが単調増加していることを確認し(複製された認証器への耐性)、originが自分のドメインと一致することを確認します。ライブラリ — @simplewebauthn/server(Node)、webauthn-rs(Rust)、java-webauthn-server(Java)。 2026年にほとんどのアプリが採用している移行パターン — 後方互換性のためパスワードによるサインインは残しつつ、初回サインイン時にpasskeyの登録を提案し、以降のログインではpasskeyを優先します。GitHubがまさにこれを行っています。passkeyの提供開始から12〜18か月以内に、先行サイトはアクティブユーザーの60〜80%が少なくとも1つのpasskeyを登録し、それに応じてパスワードの使用が減少したと報告しています。最終形は「passkeyがデフォルト、パスワードは移行ケース向けのフォールバック」であり、究極的には新規アカウントのパスワードフリー認証です。
// Browser: register a passkey
const opts = await fetch('/passkey/register/options').then(r => r.json());
const cred = await navigator.credentials.create({
  publicKey: {
    challenge: base64ToArrayBuffer(opts.challenge),
    rp: { name: 'Acme', id: 'acme.example' },
    user: { id: opts.userId, name: 'alice', displayName: 'Alice' },
    pubKeyCredParams: [{ type: 'public-key', alg: -7 /* ES256 */ }],
    authenticatorSelection: { userVerification: 'preferred' },
  }
});
await fetch('/passkey/register', { method: 'POST', body: JSON.stringify(cred) });

// Browser: sign in with passkey
const opts2 = await fetch('/passkey/login/options').then(r => r.json());
const assertion = await navigator.credentials.get({
  publicKey: {
    challenge: base64ToArrayBuffer(opts2.challenge),
    rpId: 'acme.example',
  }
});
await fetch('/passkey/login', { method: 'POST', body: JSON.stringify(assertion) });

// Server: verify with @simplewebauthn/server (Node)
import { verifyAuthenticationResponse } from '@simplewebauthn/server';
const verify = await verifyAuthenticationResponse({
  response: req.body,
  expectedChallenge: storedChallenge,
  expectedOrigin: 'https://acme.example',
  expectedRPID: 'acme.example',
  authenticator: storedCred,
});
if (verify.verified) await db.users.updateCounter(userId, verify.authenticationInfo.newCounter);
最終更新:

ツールについて

パスワードジェネレーターは指定の長さと文字種(大文字・小文字・数字・記号)で暗号的に安全な文字列を生成します。人が考えたパスワードよりはるかに推測されにくく、パスワードマネージャと組み合わせるのが現代のベストプラクティスです。Web Crypto API を使い、すべてブラウザ内で動作します。

使い方

  1. 希望する長さを設定します — 16文字以上を推奨します。
  2. 含めたい文字種をオンに切り替えます。
  3. 手入力での書き写しが多い場合は、紛らわしい文字(l/1/I、O/0)を除外するオプションを有効にできます。
  4. Generate をクリックして新しいパスワードを生成します。
  5. 結果をコピーしてパスワードマネージャに保存します — 紙に書いたりチャットに貼り付けたりしないでください。

主な使用例

  • 新しいウェブサイトやサービス用の一意なパスワードの作成。
  • インシデント発生や人事異動の後のサービス資格情報のローテーション。
  • ボールトに保存するAPIトークンやWebhookシークレットの生成。
  • 共有デバイスや使い捨てアカウント用の一時パスワードの作成。
  • 保存時に暗号化されるCI/CDパイプラインシークレットのシーディング。
  • 一時的なゲストWi-Fiパスワードの発行。

よくある質問

Q. パスワードはどれくらいの長さにすべきですか?

A. ほとんどのアカウントでは、16文字以上のランダムなパスワードなら良い意味で十分すぎるほどです。今日のより大きな脅威は長さそのものではなく、使い回しとフィッシングです。

Q. これらのパスワードは暗号学的に安全ですか?

A. はい。このジェネレーターはMath.randomではなく、暗号学的に強力であるよう設計されたWeb Crypto APIのcrypto.getRandomValuesを使用しています。

Q. パスワードは暗記すべきですか?

A. パスワードマネージャ用の強力なマスターパスワードを1つだけ暗記してください。それ以外はすべてマネージャに生成・記憶させましょう。

Q. なぜ紛らわしい文字を除外するのですか?

A. 任意のオプションですが、人が画面からパスワードを書き写す必要がある場合に役立ちます — l、1、I、0、Oは混同しやすい文字です。パスワードマネージャにのみ保存するパスワードであれば、このオプションは不要です。