ランダムトークン生成

ブラウザの CSPRNG からシークレットを生成 — 16 進数、base64url、独自の文字集合、EFF ダイスウェアのパスフレーズ。エントロピーをビットで表示。

生成中…
エントロピー192.0 ビット

3 通りの推測速度での、平均発見時間です。速度間の開きは、秘密そのものが生むどんな差よりも大きくなります。

  • レート制限のあるログインに対して — 毎秒 10 回10^49 年
  • 漏洩した低速ハッシュ (bcrypt、argon2) に対して — 毎秒 10⁴ 回10^46 年
  • 漏洩した高速ハッシュ (SHA-256、MD5) に対して — 毎秒 10¹² 回10^38 年

64 文字から選ぶため、1 文字あたり 6.00 ビットを持ちます。

このツールの役割

シークレットを生みます: 唯一の防御が、誰も推測できないことである値です。API キーやデータベースのパスワードには文字セットと長さを選び、人が打たねばならないものには、公開された単語リストから引くパスフレーズに切り替えます。すべての結果はブラウザ内で生成され、その強さを正直に記述する一つの数とともに示されます。

これはこのサイトの UUID 生成器とは別の仕事です。UUID は、二つのレコードが決して衝突しないよう一意でなければなりません。シークレットは推測できてはならず、それはより強い要件で異なる失敗です。予測可能な識別子は無害です。予測可能なシークレットは開いた扉です。

乱数はどこから来るか

ここではすべてが crypto.getRandomValues、ブラウザの暗号論的に安全な乱数生成器から引き、それは OS のエントロピープール — openssl rand と /dev/urandom が使うのと同じ源 — から種を得ます。

代わりの Math.random はセキュリティ関数ではなく、そうだと主張したこともありません。小さな内部状態を持つ高速な擬似乱数生成器で、現行のすべてのエンジンでその状態は短い出力の連なりから復元でき、その後、過去と未来のすべての値が知られます。それで作られたトークンは本物とまったく同じくらいランダムに見えます。違いは、誰かがわざわざ見たときにだけ現れます。

もっともな問いは、Web ページが本番のシークレットを生成する正しい場所かどうかです。生成そのものは健全です: プラットフォームの CSPRNG で、ページは静的で、何も送信されません。考える価値があるのはその周りの部分です — クリップボードを通るシークレットはほかのアプリケーションに読めることがあり、端末に貼り付けたものはたいていシェル履歴に残ります。それらはほかのどの方法とも同じ考慮事項です。

明白な実装に隠れる偏り

ランダムなバイトを文字に変えるのは一行に見えます: バイトを取り、文字セットの大きさで割った余りを取り、文字セットに添字を引く。それは、大きさが 256 を割り切らないすべての文字セットで微妙に誤りで、出力はその兆しを何も与えません。

62 の英数字では、256 は割り切れません: 62 は 256 に 4 回入り、8 余ります。それら 8 個の余ったバイト値 — 248 から 255 — は文字セットの最初の 8 文字に折り返るので、それらは 256 のうち 5 回の機会を得、残りは 4 回です。最初の 8 文字はほかより約 25% 出やすくなります。

直し方は棄却サンプリングです: 余りの尾に落ちた draw を折り返さず捨てて引き直します。62 文字の文字セットで 32 回に約 1 回の余分な draw を要し、16 進数や base64url — 大きさが 2 の累乗で尾を持たない — にはまったく何も要しません。このツールは棄却します。効果はどの単一のトークンにも見えず、だからこそ述べる価値があります。

唯一の正直な尺度であるエントロピー

ビットでのエントロピーは、等しく起こりうるシークレットの空間がどれだけ大きいかを言います: n ビットは 2^n の可能性を意味します。加法的で比べやすく、誰がその空間をどれだけ速く探せるかについては何も言いません — それは特徴です。その部分が、生成器が知りえないものに依存するからです。

計算は意図的に単純です。各文字が log2(文字セットの大きさ) ビットを、各単語が log2(単語リストの大きさ) を寄与するので:

  • 16 進数の文字は 4 ビットなので、32 文字の 16 進数トークンはちょうど 128 ビット — 書き出された AES-128 鍵です。
  • base64url の文字は 6 ビットなので、22 文字が 128 ビットを、43 文字が 256 ビットを越えます。
  • 英数字の文字は約 5.95 ビット。そっくり文字を除くと文字セットが 58 に、文字が 5.86 に落ち、12 文字ごとに約 1 文字の長さの費用がかかります。
  • EFF ロングリストの単語は 12.925 ビットです。リストに 7776 の項目 — 6^5、5 回のサイコロ振り — があるからです。
  • EFF ショートリストの単語は 10.34 ビットで、1296 の項目 — 6^4 — からです。

よくある目標は 128 ビットで、総当たりが単に高価であることをやめ戦略でなくなるところです。それは 32 の 16 進数文字、22 の base64url 文字、または EFF ロングリストの 10 単語です。

なぜ単一の「解読時間」がないのか

シークレットに解読時間はありません。シークレットとそれを守る何かの対に一つあり、守るものがシークレットよりはるかに重要です。ログインフォームを通して見つけるには宇宙が存在してきたより長くかかる同じ値が、ソルトなしの SHA-256 として保存されデータベースが漏れれば、午後のうちに落ちます。

だから一つの数ではなく三つの速度が示され、それぞれ名付けられます:

  • 毎秒 10 回の推測、レート制限のあるログインに対して。これは、あなたのサービスを通らねばならない攻撃者にとっての現実的な天井です。
  • 毎秒 1 万回の推測、遅いように作られた漏洩したパスワードハッシュ — 現代のコストの bcrypt、または argon2 — に対して。その遅さがそれらの関数の全目的です。
  • 毎秒 1 兆回の推測、パスワード用に決して意図されなかった漏洩したハッシュに対して。SHA-256 と MD5 は高速に設計され、GPU の装備は実に高速です。

速度は意図的に 10 の累乗に丸められます。より精密なものは、有用な情報が最初の行と最後の行の間の 11 桁であるときに、一人の特定の攻撃者の測定を示唆するでしょう。シークレットが三つすべてで快適なら、正確な数字を要さず問いは決着します。

各数字は平均で、それは全部ではなく空間の半分です — 探索は平均して途中で答えを見つけます。そして 100 万年を超えると答えは桁で与えられます。「400 兆年」は誰も比べられる長さではないからです。宇宙は約 10^10 歳で、そこまで届く行に有用な錨になります。

パスフレーズと、その強さが実際にどこから来るか

パスフレーズが強いのはちょうど一つの理由です: いくつかの単語が大きなリストからランダムに選ばれたこと。長いから強いのではなく、言語のように見えるから強いのでもありません。7776 語のリストからの 6 つのランダムな単語は約 77 ビットで、人が思いついた 6 語ははるかに価値が低いです。人は一様に選ばず、攻撃者はよくある句についてあなたと同じことを知っているからです。

ここの二つのリストは EFF から来た、公開された diceware リストで、変えずにダウンロードされました。ここで組み立てたリストではなく、それが重要です: 誰かが考え出した単語リストは、大きさが不明で、ほかのリストとの重なりが不明で、それについてなされたエントロピーの主張を確かめる方法がありません。

  • ロングリストは 7776 語で、5 つのサイコロの各出目に一つで、1 単語あたり 12.925 ビットを与えます。
  • ショートリストは 1296 語で、4 つのサイコロの各出目に一つで、1 単語あたり 10.34 ビットを与えます。その単語はより短く — どれも 5 文字を超えません — 打ちやすくする代わりに、同じ強さに、より多くの単語を要します。

パスフレーズの繰り返される単語は欠陥ではなく、ここでは生成し直されません。各 draw は独立なので、どの特定の単語の対もほかと同じくらい起こりやすく、繰り返しを拒めば可能なパスフレーズの空間を縮め、それらをより強くではなくわずかに弱くします。

両方の EFF リストには一握りのハイフン付きの項目 — t-shirt、yo-yo、drop-down、felt-tip — が含まれます。区切りもハイフンなら、そのうちの一つを含むパスフレーズは単語に一意に分け直せません。セキュリティではなく表示の問題で、区切りにスペースかピリオドを選ぶとまるごと避けられます。

エントロピーを費やす選択肢と、費やさないもの

そっくり文字を除くことは強さを読みやすさと引き換え、その引き換えは見えます。0・O・I・l を取り除くと、英数字の文字セットを 62 から 58 文字にし — それはちょうど Bitcoin が使う base58 文字セットで、同じ理由です。各文字が 5.95 から 5.86 ビットに落ちるので、トークンは同じ強さを保つのに 12 文字ごとに約 1 文字を余分に要します。画面から読んでどこかに打つものには、たいていそれだけの価値があります。

選択肢はそれが意味を持つところでだけ提供されます。16 進数と base64url は符号化であって文字集合ではありません: それらの文字セットは仕様で固定され、0 なしの 16 進数はもはや 16 進数ではなく — 何もそれをデコードできないでしょう。

パスフレーズの各単語の先頭を大文字にすることはまったく何も加えず、ここの強さの数字はオンにしても意図的に動きません。毎回適用される同じ変換なので、単一の新しい可能性も作りません: 句が大文字化されていると知る攻撃者は、始めたところにちょうどいます。選択肢が存在するのは、パスワード欄が今も大文字を要求するからで、それが役立つからではありません。

長さを選ぶ

マシンが扱うもの — API キー、セッショントークン、Webhook シークレット、データベースのパスワード — には、けちる理由はありません。32 の 16 進数文字か 22 の base64url 文字が 128 ビットを与え、さらに進んでも設定ファイルのバイトしか費やしません。

人が打つものには、制約が異なり、パスフレーズがたいていよりよい形です。ロングリストの 6 語は、12 文字のランダムなパスワードより強く、一度で正しく入れるのが劇的に易しく、それは聞こえるより重要です: 人が打ち間違えるシークレットは人が書き留めるシークレットです。

数値のコードには、正直な読みは、4 桁が 13 ビットで、レート制限していない何かに数秒で使い尽くされうる、ということです。PIN が安全であるのは、その周りのロックアウトポリシーのおかげだけで、決してそれ自身の強さのおかげではありません。

よくある質問

API キーはどれくらいの長さであるべきですか?
128 ビット以上のエントロピーを目指してください。総当たりが戦略でなくなるところです。それは 32 の 16 進数文字、22 の base64url 文字、または 256 ビットが欲しければ 43 の base64url 文字です。ソフトウェアだけが扱う値には、長いほうの選択肢は何も費やしません。
これは Math.random でシークレットを生成するより安全ですか?
はい、そして違いは程度の問題ではありません。Math.random は小さな状態を持つ擬似乱数生成器で、現行のエンジンはそれを短い出力の連なりから復元でき、その後それが生むすべての値が知られます。このツールは crypto.getRandomValues、プラットフォームの CSPRNG を使い、それは openssl rand が引くのと同じ源です。
なぜ単一の「解読時間」を示さないのですか?
そのような数がないからです。同じシークレットが、レート制限のあるログインの背後では届かず、漏洩した高速ハッシュの背後では速く落ちます — 11 桁離れています。単一の数字は一つの仮定を選んでそれを隠さねばならず、読み手は仮定ではなく数を覚えます。三つの名付けられた速度が、仮定を見えるところに置きます。
パスフレーズはランダムな文字列より弱いですか?
いいえ — 強さは、どれだけ大きなリストからいくつの単語が引かれるかだけに依存し、両方が示されます。EFF ロングリストの 6 語は約 77 ビットで、10 文字のランダムなパスワードより多いです。パスフレーズを弱めるのは、単語を自分で選ぶことで、これらはそうではありません。
そっくり文字を除くべきですか?
人がシークレットを画面から読んでどこかに打つなら、はい: 費用は小さく、読み間違えたトークンはサポートチケットです。ソフトウェアだけが扱うなら、理由はありません。0・O・I・l を取り除くと文字セットを 62 から 58 文字にし、それはちょうど base58 文字セットで、12 文字ごとに約 1 文字の長さを費やします。
パスフレーズを大文字化すると強くなりますか?
いいえ。毎回適用される同じ変更なので、パスフレーズの空間に単一の新しい可能性も加えません。ここのエントロピーの数字はオンにしても留まり、それが正確な振る舞いです。選択肢があるのは、一部のパスワード欄が大文字を要求するからです。
私が生成したものはサーバーに送られますか?
いいえ。生成はプラットフォームの乱数生成器を使って完全にブラウザ内で動き、何もアップロードも記録もされず、ネットワーク接続なしで動きます。トークンはどこにも保存されません — ページを再読み込みすると新しいものが生まれ、古いものは消えます。