トークン生成

ブラウザ上で暗号学的に強いランダムトークン、APIキー、シークレット、ノンスを生成。長さ・文字セット・生成個数を選択できます。

予測不可能なランダムトークン。 すべての乱数はブラウザの crypto.getRandomValues 由来で、TLS鍵と同じソースです。端末の外には出ません。

安全なトークンの条件

ランダムと予測不能は違う

多くの言語には性質のまったく異なる 2 種類の乱数生成器があります。Math.random()rand() の類は速度重視の疑似乱数生成器で、時計のような安価な値をシードにします。プレイリストのシャッフルには十分ですが、トークン生成には致命的です。攻撃者は数個の出力を観測するだけで内部状態を復元し、その生成器が今後出力するすべての値を再現できることが少なくありません。

暗号論的に安全な生成器は、過去の出力から将来の出力が一切わからないように設計されています。ブラウザではそれが crypto.getRandomValues() で、OS のエントロピープールから値を取得します。このツールはこれだけを使います。自分のコードでトークンを生成するなら、対応するのは Python の secrets、Go の crypto/rand、Java の java.security.SecureRandom です。通常の random モジュールや Math.random() は決して使わないでください。

剰余バイアスを避ける

良質な乱数バイトを得ただけでは半分にすぎません。文字を選ぶ素朴な方法は bytes[i] % alphabet.length ですが、アルファベットのサイズが 256 を割り切れない場合、結果は静かに偏ります。62 文字のアルファベットでは先頭 8 文字が他よりわずかに多く出現します。小さな偏りですが実効エントロピーを下げ、しかも完全に回避可能です。

解決策は棄却サンプリングです。最後の不完全なブロックに落ちたバイトは捨てて引き直します。このツールはそれを行うため、選択したアルファベットのどの文字も等確率で現れます。

長さの決め方

エントロピーは log2(アルファベットサイズ) × 長さ ビットです。62 文字のアルファベットは 1 文字あたり約 5.95 ビットなので、22 文字のトークンは約 131 ビットとなり、総当たりの射程外です。実際のアクセスを守る用途では 128 ビットが通常の下限で、64 ビットを下回るあたりから、応答の速いエンドポイントを持つ攻撃者が現実的な脅威になります。

アルファベットの選択は主にトークンがどこを通るかで決まります。Base64url と 16 進は URL、ファイル名、ヘッダーをそのまま通過できます。紛らわしい文字を除いたアルファベットは 0/O や 1/l/I を外してあり、人が読み上げたり画面を見て打ち直したりする場面で有用です。

オープンソースに関する注記:ブラウザ標準の crypto.getRandomValues API で実装。サードパーティライブラリは使用していません。

よくある質問

トークンは自分の端末で生成されますか?
はい。crypto.getRandomValues() を使ってブラウザ内で完結します。サーバーへの送信もログ記録も行わないため、表示された値を知るのはあなただけです。
トークンはどのくらいの長さが必要ですか?
アクセスを守る用途なら最低 128 ビットのエントロピーを目安にしてください。62 文字の文字集合なら 22 文字、16 進なら 32 文字です。セキュリティ目的でない識別子はもっと短くても構いません。
なぜ Math.random() を使ってはいけないのですか?
時計のような安価な値をシードとする高速な擬似乱数生成器だからです。数個の出力を観測するだけで内部状態を復元され、以後のすべての値を予測されてしまいます。
「紛らわしい文字を除く」オプションは何のためですか?
0/O や 1/l/I を取り除きます。読み上げたり紙に書き写したり画面から打ち直したりしても、転記ミスが起きにくくなります。
パスワード再設定リンクに使えますか?
使えます。ただしトークンはハッシュだけを保存し、短い有効期限を設け、一度使ったら無効化してください。乱数の質はここで十分ですが、ライフサイクル管理はアプリ側の責任です。
同じトークンが再び出ることはありますか?
128 ビットのエントロピーがあれば重複は天文学的に低い確率です。ただし本ツールは履歴を保持しないため、生成間の一意性をこちらで検証することはできません。