このブログには、物事はこうあるべきだと説明する記事が十二本ある。長さは記号より重い こと、パスワードマネージャーは便利さではなく唯一その規則を守れる手段であること、パ ーセントは何も語らないこと。
それを書くのは簡単だ。居心地が悪くなるのは、同じ物差しを自分のサイトに当てたとき だ。当ててみたら、三つ悪いところがあった。 それを暴いた数字ごと、まるごとここ に書く。自分の当たりだけを公開するセキュリティのサイトは、かなり値打ちが落ちるから だ。
チェッカーは入力中に固まっていた
チェッカーは zxcvbn であなたのパスワードを解析 する。大文字を数えるのではなくパターンを探すライブラリだ。よくできていて、その代わ り代償がある。一気に、ページを描くのと同じスレッドの上で走るのだ。走っているあ いだ、ブラウザーは他に何もできない。
その代償は長さとともに急に大きくなる。サイトが配っているのと同じ束で、しかも人が実
際に打つ種類のパスワード——単語、西暦、a の代わりの @——で計測した。
| 長さ | 一回の実行 |
|---|---|
| 16 文字 | 45 ms |
| 20 文字 | 121 ms |
| 32 文字 | 273 ms |
| 64 文字 | 843 ms |
| 128 文字 | 3,621 ms |
ここまでは普通だ。問題は、それを何回起動していたかだった。
入力欄には input と keyup という二つの別々の監視が付いていた。普通のキーは
その両方を発火させる。つまり一文字打つたびに、完全な解析が二回走っていた。16 文
字のパスワードで 90 ms、32 文字なら半秒だ。
しかも止めるものが何もなかった。タイマーも、長さの上限も、別スレッドもない。二十文 字を超えたあたりから、ブラウザーが解析にかける時間のほうが、あなたが次のキーを押す までの時間より長くなる。打鍵は二度と空にならない待ち行列に積み上がり、入力中にペ ージが反応しなくなっていた。長いパスワードを貼り付ければ数秒固まった。
直し方は小さな変更が二つ。keyup の監視を外した。input だけで入力も貼り付けも削
除もマネージャーの自動入力も拾えるからだ。見えるものは何ひとつ変わらないまま、仕事
の半分が消える。そして 150 ミリ秒の待ちを入れた。打っているあいだは何も解析せず、手
を止めた瞬間に解析する。それに気づくほどゆっくり打つ人はいない。
結果は同一だ。Barcelona1992$ は今も同じことを言う。「barcelona」は辞書にあり、1992
は西暦に見え、一秒とかからず落ちる、と。
説明文は十五の言語で文の途中で切れていた
こちらはもっと間抜けで、もっと恥ずかしい。
検索結果でタイトルの下に出る一文——メタディスクリプション——が、チェッカーの十八言 語のうち十五で切れていた。無事だったのはスペイン語、韓国語、日本語だけ。誰かがど こかで長さを理由に刈り込み、単語の途中で切り、その後だれも見なかった。
三つの言語では、切れ目がちょうど特殊文字の真ん中に落ちた。つまり Google に出してい たのはこれだ。
| 言語 | 配っていたもの | 本来 |
|---|---|---|
| ポルトガル語 | …datas e padr&o |
padrões |
| トルコ語 | …arıyor ve ger&cced |
gerçekten |
| ベトナム語 | …chúng tôi tra mật kh&# |
mật khẩu |
目を引くのはその場所だ。サイト全体でいちばん成果の出ているページである。チェッ カーはジェネレーターよりはるかによく機能していて、しかも壊れた説明文のままそうして いた。十五本とも埋めた。
ついでに韓国語・日本語・ベトナム語では、ブランドをタイトルの先頭から末尾へ移した。 検索結果ではドメインが別に表示されるのだから、「password.es ·」で始めるのは、いちば ん重い場所を捨てているだけだった。
一億分の一の偏り
ジェネレーターは各文字を crypto.getRandomValues() で選ぶ。ブラウザーのまともな乱数
源だ。ところが、その巨大な数を「アルファベット上の位置」に変えるのに剰余を使ってい
た。ここに古典的な罠がある。2³² は 83 の倍数ではないので、アルファベットの先頭の
位置が、末尾より ほんのわずかに よく出ていた。
どのくらい「わずか」か。最大 89 文字のアルファベットで、一億分の一の桁だ。何も変わ らない。あなたのパスワードを測れるほど弱くはしない。まったく近づきもしない。
それでも直した。三行だ。4,294,967,296 通りのうち余る 45 個を捨てて引き直す。パスワ ードのサイトで、取り除くのがその程度で済むのに「無視できる」は偏りを残す理由になら ない。
足りなかったもの——約束をブラウザーに守らせること
あなたのパスワードはここから出ないと 説明する記事がまるごと一本ある。本当のことだったが、それでもこちらの一文にすぎなか った。注入されたスクリプトが別のことをするのを、技術的に妨げるものは何もなかった。
いまはどのページもコンテンツセキュリティポリシーを積んでいる。効くのは二つ。
- 構築時にページになかったスクリプトは動かない。 正規のスクリプトはそれぞれ指紋 で署名されている。注入されたものは一致せず、ブラウザーが実行を拒む。
connect-src 'none'。 このサイトは JavaScript から一度もネットワーク要求をし ない。それをいまはブラウザーが強制する。いつか何かがあなたの打った文字をどこかへ 送ろうとしても、外へは出ない。
約束は宣言をやめ、規則になった。
いまも直っていないこと
**8月31日の追記。**この節の三つは、この記事が出たその日のうちに直りました。十五の言語は本当のエンジンを説明するようになり、二つの尺度は一つになり、チェッカーのよくある質問が記号の件を説明しています。それでも書いたまま残します。何が間違っていたかの記録は、非の打ちどころのないサイトの写真より値打ちがあるからです。
この記事が席を得るのはここからだ。
十五の言語がいまだにチェッカーを古いエンジンとして説明している。 そのページの文
章は、PasswordMeter の古典的ロジックを再現している、と言う。もう違う。あのエンジン
は Password1! を「非常に強い」と呼び、五語のパスフレーズを落としたから取り替えら
れた。言うべきことのちょうど逆だ。スペイン語・韓国語・日本語は更新済み、残る十五は
そのままだ。
同じ家に二つの尺度がある。 トップページはビット数でパスワードの強さを決め、チェ ッカーは破るのにかかる時間で決める。別々の基準なのに、どこにも書いていない。
ジェネレーターとチェッカーは同じ記号を数えていない。 一方は 27 を使い、もう一方 は 33 を仮定している。差は小さいが、ある。
三つとも重大ではない。三つとも負債であり、誰かに見つけられるのを待つより、ここに書 かれているほうを選ぶ。
このバージョンの変更履歴
リポジトリが公開ではないので、変更履歴はここに全部書く。0.2.0、2026 年 8 月 31 日。
追加。 ページごとのコンテンツセキュリティポリシー。各スクリプトの指紋つき。保存 したパスワードがどこにあるかの記事を十八言語で。何を書くかを決め、空になったら何も 公開するなと命じる編集キュー。
修正。 チェッカーの説明文。十五言語で文の途中で切れ、うち三つは文字が半分に割れ ていた。入力中のタブの凍結。抽選の偏り。そして前の記事に欠けていた写真。
変更。 韓国語・日本語・ベトナム語でのチェッカーのタイトル。デプロイ。いまは構築 済みのサイトが存在してから起動する。一分前ではなく。そしてベトナム語・ヒンディー語 ・アラビア語の翻訳は、いちばん弱いままではあるが、公開を止めなくなった。
この記事の数字は推定ではなく実測である。zxcvbn の時間はサイトが配るのと同じ束と、単 語や置き換えを含むパスワードで計測した。抽選の偏りは 32 ビット整数の 4,294,967,296 通りの値の上で計算した。チェッカーのエンジンはオープンソースの zxcvbn。
写真: Ernandes Alves · Pexels