背景
インターネットを彷徨っているとたまたまパスワード付きのZipを某サービス経由で公開している人がいました。
単にパスワード付きのZipなら特に何も思わなかったのですが、ちょっと調べてみるとパスワードのヒントが載っていたのでこれは現実的に破ることができるのか試してみました。
暗号強度
パスワードに使われるのアルファベットの大文字小文字・数字・記号が使われることが多いです。
記号がASCIIに準拠していれば32パターンなので、それぞれ一文字あたりの候補数は52, 62, 94となり、七文字以上の組み合わせは以下の表になります。
| 文字数 | 大小英字のみ (52) | 英数字 (62) | 英数字+記号 (94) |
|---|---|---|---|
| 7 | 1.0×10^12 | 3.5×10^12 | 6.5×10^13 |
| 8 | 5.3×10^13 | 2.2×10^14 | 6.1×10^15 |
| 9 | 2.7×10^15 | 1.3×10^16 | 5.7×10^17 |
| 10 | 1.4×10^17 | 8.4×10^17 | 5.4×10^19 |
英字のみと英数字のみは思ったほど強くなっていないので、何らかの理由でセキュリティ向上のためにパスワードを変えたいなとなった場合には単に数字も必須にするくらいなら最小パスワード長を一文字増やしたほうが効率が良いということになります。
解読速度
$ john --test --format=PKZIP
Benchmarking: PKZIP [32/64]... DONEMany salts: 29361K c/s real, 29073K c/s virtualOnly one salt: 16613K c/s real, 16613K c/s virtualうちにあるM3 Maxで実行したところ複数ファイルなら一秒に3000万件、単一ファイルなら1600万件くらいということがわかりました。
解析には
zip2johnを利用しました
| 文字数 | 大小英字のみ (52) | 英数字 (62) | 英数字+記号 (94) |
|---|---|---|---|
| 7 | 約0.001年(約9時間) | 約0.003年(約1.3日) | 約0.065年(約24日) |
| 8 | 約0.05年(約19日) | 約0.22年(約2.6か月) | 約6年 |
| 9 | 約2.7年 | 約13年 | 約570年 |
| 10 | 約140年 | 約840年 | 約5.4万年 |
パスワードが英数字だけということがわかっていたとしても八文字以上だと、そこまでコストをかけてやるかどうかは微妙なラインになってきます。もちろん、マシンのスペックを上げればこの辺りは解決できますが、一文字増えるごとに50~100倍くらい組み合わせが増えるので、文字数が10文字を超えると現実的ではありません。
手がかり
が、ここで大きなヒントがあることに気が付きます。
なんと、パスワードは大小英字のみ、かつ七文字であることが明記されていたのです。これなら、最悪九時間くらいのリソースを割けばいいので、パソコンが暖房代わりになる冬であれば十分計算能力を投資する意味があります(もちろん、中身にそれなりの価値があればですが)
更に都合の悪いことに、更にヒントがあり先頭だけが大文字であることも書かれていました。
こうなると大小英字であることは全く意味がなく、単に26^7通りしか組み合わせがないことが確定してしまいます。
計算すると26 × 26⁶ = 26⁷ = 8,031,810,176となり、約80億通りしかありません。これなら五分くらいで割れる可能性があるので、試してみることにしました。
解読方法
$ zip2john encrypted.zip > hash.txt
Created directory: /Users/devonly/.johnencrypted.zip/secret/ is not encrypted!ver 2.0 encrypted.zip/ is not encrypted, or stored with non-handled compression typever 2.0 encrypted.zip/secret.txt PKZIP Encr: cmplen=188, decmplen=183, crc=FD43E6DAとして、ハッシュファイルを作成します。
すると何やら英数字が並んだテキストファイルが作成されます。
あとは、パスワードを全通り試してハッシュを生成し、これと合致するパスワードが見つかれば良いです。ハッシュでチェックするのでfcrackzipのように毎回unzipを走らせる必要もないので極めて高速に動作します。
$ john --mask='?u?l?l?l?l?l?l' hash.txtUsing default input encoding: UTF-8Loaded 1 password hash (PKZIP [32/64])Press 'q' or Ctrl-C to abort, almost any other key for statusXxxxxxx (encrypted.zip/secret.txt)1g 0:00:00:03 DONE (2026-01-17 03:35) 0.3278g/s 15606Kp/s 15606Kc/s 15606KC/s Xxxxxxx..XxxxxxxUse the "--show" option to display all of the cracked passwords reliablySession completedとなり、運が良かったのもありますが、たったの三秒でパスワードが割れてしまいました。
まとめ
パスワードのヒントを書いてしまうと一気に強度が下がってしまうので避けること。
どうしてもユーザーの利便性を考えて書かなければいけないような場合には、ヒントを与えても十分な強度が得られるくらいにパスワードを長くすること。
という教訓が得られました。
記事は以上。