POSTD PRODUCED BY NIJIBOX

POSTD PRODUCED BY NIJIBOX

ニジボックスが運営する
エンジニアに向けた
キュレーションメディア

Antoine Beaupré

本記事は、原著者の許諾のもとに翻訳・掲載しております。

  1. 信頼性の高いパスワードの特徴とは?
  2. 安全なパスワードを生成
  3. セキュリティトークンを生成
  4. まとめ

パスワードは、現代生活の様々な場面で使用されています。Eメールアカウントから銀行のカードまで、重要なセキュリティインフラは、利用者がパスワードを”知っている”ことに依存していると言ってもいいでしょう。しかし、信頼性の高いパスワードの生成方法を記した規格文書などは、ほとんどありません。そんな方法をまとめたものがあったら興味深いと思いませんか。この記事では信頼性の高いパスワードの特徴とは何か、そしてそれを生成するための、いくつかのツールについて説明します。

近年、パスワードへの依存が、根本的なセキュリティ上の欠陥を招いているという懸念が高まっています。例えば、パスワードは人間に依存しますが、人間は圧力をかければ秘密情報を明かすこともあり得ます。更に、パスワードは”再生可能”です。もしパスワードが漏れたり盗まれたりした場合、あなたに成り代わった誰もが、そのパスワードで重要な情報資産にアクセスできてしまうのです。そのため、大きな組織では、単一のパスワード認証を廃止する動きが広がっています。例えば、Googleでは 従業員向けに2段階認証を実施しており 、加えて スマートフォンでのパスワード 廃止も検討(問題が多いその変化は、いまだ実現には至っていないものの)しているようです。

しかし、現実的には、何か他の選択肢が見つかるまでは、目の前にあるパスワードをこれからも使い続けることになるでしょう。なお、この記事では、ユーザーが自分の身元を証明するために提供する一部のテキストとして、”PIN”や”パスフレーズ”の代わりに”パスワード”という用語を使用します。

信頼性の高いパスワードの特徴とは?

“信頼性の高いパスワード”とは、人によってその意味合いが異なる場合がありますが、私の考えでは以下の特性を有しています。

  • 高エントロピー:マシンにとって推測が難しい
  • 転送可能:人間にとって伝えやすい、あるいはコンピュータにとって様々なプロトコル間で転送しやすい
  • 記憶可能:人間にとって覚えやすい

高エントロピーとは、攻撃者にとってパスワードがあらゆる実用的な目的において予測不可能であるべきということを意味します。パスワードを作成する時、自分が知っている何か他の物事をベースにしがち(そして、よくあるやり方)ですが、残念ながらそのようなやり方だと、それが自分ではどれだけ”秘密”だと思っていても、往々にして推測されやすいパスワードになってしまいます。攻撃者が十分に時間をかければ、あなたの誕生日も初恋の人の名前も、母親の旧姓も、あるいは昨年の夏にいた場所やその他の秘密と思っている事柄も把握できてしまうでしょう。

これに対する唯一の解決策は、無作為に生成されたパスワードを利用するか、パスワードの総当たり攻撃が、事実上、不可能な”エントロピー性”を保つ、ランダムに生成されたパスワードを使用することです。現代の製品版グラフィックカードが、 hashcat のようなフリーソフトを使って毎秒数百万のパスワードを推測できることを考慮すると、一般的な”8″文字のパスワード要件では、もはや十分ではないことが容易に想像できると思います。適切なハードウェアを用いれば、強力なリグでこうしたパスワードを1日以内にクラックしてオフラインにできるでしょう。 アメリカ国立標準技術研究所(NIST) の草稿では、いまだに最低8文字の方法を 推奨 していますが、最近では 12文字 または 14文字 の方がいいという声もちらほら聞かれるようになってきました。

パスワードはまた、簡単に”転送可能”でなければなりません。 &! のような一部の文字はWebやシェル上で特別な意味を持っており、転送する際に大きな混乱を招く恐れがあります。こうした理由により、特定のソフトウェアの中にも一部の特殊な文字を 拒絶 (または要求)するような方針を有しているものがあります。ややこしい文字は、人間が音声チャネルを通じて、あるいは異なる文化的背景を超えてパスワードを伝えることの弊害にもなります。極端な例ですが、人気の高いSignalのソフトウェアでは、 数字だけを使って 鍵指紋を転送しています。(言語に固有の単語を使うことに反して)、数字は “ローカライズが容易”で”視覚的に区別しやすい” と彼らは述べています。

ただし、より重要なのは”記憶可能”の部分です。ランダムな文字列を生成するのは簡単ですが、そうしたパスワードを人間が覚えるのは大変です。 “20年の努力の末、私たちは、誰もが覚えているのは難しいが、コンピュータが推測しやすいパスワードを全員が使うよう訓練した” と述べています。 xkcdのコミックの言葉です 。この漫画は、ある単語の一部の文字を変えたものよりも、連語の方が信頼性の高いパスワードだということを説明しています。

当然のことですが、全てのパスワードを覚える必要はありません。一部をパスワードマネージャで管理してもいいですし(これについては、また別の記事で触れたいと思います)、カードなどに書き留めてもいいでしょう。そうした場合、必要なのはパスワードというよりも、”トークン”あるいはDebian開発者のDaniel Kahn Gillmor(dkg)が個人メールで言うところの “高エントロピー、コンパクトで転送可能な文字列” と呼べるようなものになります。特定のAPIは、トークンの使用を前提として作られており、例えば OAuth は、サービスへのアクセスを提供するランダムな文字列、”アクセストークン”を生成します。しかしこの記事では、”トークン”をより広い意味で使うつもりです。

ところで先ほどの文章で、”記憶可能な”の特性を削除し、”コンパクトな”の特性を追加したのに気付きましたか? 制限のあるパスワードの条件に対応するためには、最大のエントロピーを効率的に最短のパスワードに変換することが求められます。例えば、銀行のカードの中には5桁のセキュリティPINしか許容されないものがありますし、ほとんどのWebサイトでは、パスワードの長さに上限があります。ちなみに”コンパクトな”という特性は、パスワード自体よりもトークンに適用されるものでしょう。なぜなら、パスワードは、恐らく限定された場面(パスワードマネージャ、SSHとOpenPGPのキー、コンピュータのログイン、および暗号化キー)でしか使わないだろうからです。その他のパスワードについては、全てパスワードマネージャに保存するべきで、こうしたツールを使えば、コンパクトな特性がそれほど重要な意味を持たないような、大きなパスワードも管理できるようになります。

安全なパスワードを生成

それでは、強力で、転送可能で、覚えやすいパスワードを生成する方法を見ていきましょう。ほとんどの場合、他の設定で使用されるセキュリティトークンが実際には画面に表示されないよう、扱うパスワードです。コピーアンドペーストや、フォームで自動的に入力する必要があります。ここで説明するパスワードジェネレータは、全てをコマンドラインから操作します。多くの場合、パスワードマネージャにはパスワードジェネレータが組み込まれていますが、通常はvault自体のパスワードを簡単に生成する方法はありません。

先ほど紹介したxkcdの漫画は、恐らくセキュリティクラウドにおける共通の文化的参考資料で、私は、良好なパスフレーズの選択方法を説明する際によく使わせてもらっています。そんな中、誰かが実際にxkcdの著者であるRandall Munroeの提案を xkcdpass というプログラムに実装したことが分かりました。

    $ xkcdpass
    estop mixing edelweiss conduct rejoin flexitime

冗長モードでは、生成されたパスフレーズの実際のエントロピーが表示されます。

    $ xkcdpass -V
    The supplied word list is located at /usr/lib/python3/dist-packages/xkcdpass/static/default.txt.
    Your word list contains 38271 words, or 2^15.22 words.
    A 6 word password from this list will have roughly 91 (15.22 * 6) bits of entropy,
    assuming truly random word selection.
    estop mixing edelweiss conduct rejoin flexitime

ちなみに、上記のパスワードは91ビットのエントロピーを持っており、使用される文字が大文字、小文字、数字、および10個の記号からランダムに選択されたと仮定すると、15文字のパスワードが持つエントロピーと同程度になります。

    log2((26 + 26 + 10 + 10)^15) = approx. 92.548875

また、これがbase64でエンコードされた15文字のパスワードのエントロピーに近いことも興味深い点です。各文字は6ビットなので、結果的には90ビットのエントロピーになります。xkcdpassはスクリプト化が可能で使いやすく、異なるコマンドラインオプションを使用してワードリストや区切り文字などをカスタマイズすることもできます。初期状態では 12 dicts2 of 12 ワードリストが使われていますが、これはパスワード生成に特化したものではなく、”共通ワード”や異なるサイズのワード用にまとめられたものです。

別の選択肢として挙げられるのは、 dicewareのシステム で、サイコロの出た目に基づいて単語を検索するワードリストによって動きます。例えば、5つのサイコロで”1 4 2 1 4″が出ると単語は”bilge”となり、これを5回繰り返せば、ランダムかつ記憶可能な5つの単語のパスワードが生成できるというわけです。紙とサイコロが以前ほど普及しなくなったのを見かねてか、誰かが文字通り diceware(サイコロウェア) という名前のプログラムを作成しました。こちらは、パスワードがデフォルトの状態で、スペースで区切られていない点を除けば、同様の方法で動作します。

    $ diceware
    AbateStripDummy16thThanBrock

dicewareでは、xkcdpassと類似するよう出力を変更することもできますが、コンピュータのエントロピーソースを当てにしない人のために、実際にサイコロの出た目を受け入れることもできます。

    $ diceware -d ' ' -r realdice -w en_orig
    Please roll 5 dice (or a single dice 5 times).
    What number shows dice number 1? 4
    What number shows dice number 2? 2
    What number shows dice number 3? 6
    [...]
    Aspire O's Ester Court Born Pk

dicewareにはいくつかのワードリストが付属しており、デフォルトのリストは、パスワード生成のために意図的に作成されたものです。これは標準のdicewareリストから派生したもので、 SecureDropのプロジェクト から追加されています。また、よりよい認識ができるよう選択された単語を含む EFFのワードリスト も付属しています。こちらはサイコロでパスワードを生成する際のdiceware推奨リストですが、デフォルトでは有効になっていません。その理由として、EFFのリストが 後になって 追加されたためで、現在はデフォルトにすることを 検討している ようです。

dicewareの欠点として、実際に生成されたパスワードがどの程度のエントロピーを持っているか分からない点が挙げられます。知りたい場合には自分で計算するしかありません。実際の数値はワードリストによって異なります。デフォルトのワードリストは、1ワードにつき13ビットのエントロピーを持っているので(正確には8192ワード長)、デフォルトの6つの単語のパスワードは、78ビットのエントロピーを持つことになります。

    log2(8192) * 6 = 78

上に紹介した両プログラムはどちらも比較的新しく、最近の安定したリリースを経てDebianに参入したようなツールのため、配布用としては直接的に利用できないかもしれません。マニュアルのdicewareは、サイコロとワードリストさえあれば可能なので、これについては携帯性に優れているでしょう。dicewareとxkcdpassのインストールは、 pip で行えます。これが難しい場合は、 Openwallのpasswdqc を見てみてください。こちらは歴史も古く、広い範囲で利用可能です。覚えやすいパスフレーズが生成でき、エントロピーのレベルも良好に制御できます。

    $ pwqgen
    vest5Lyric8wake
    $ pwqgen random=78
    Theme9accord=milan8ninety9few

passwdqc は、何らかの理由でパスワードのエントロピーを24から85ビットの範囲で制限しています。カスタマイズの範囲も他の2つに比べると狭く、ここに記載したものが、そのまま得られるという感じです。4096語のワードリストもC言語のソースコードにハードコード化されています。そのルーツは、1997年の Usenet sci.cryptの投稿 まで遡ります。

xkcdpassとdicewareの鍵となる特徴は、自分のワードリストを作成できることです。これにより、辞書ベースの攻撃をより困難にします。実際のところ、このような単語ベースのパスワードジェネレータでは、パスワードをクラックする唯一の実行可能な方法は辞書攻撃です。文字ベースで検索を徹底的にするとなると、パスワードが長すぎるため終わるまでに何世紀もかかってしまいます。従って、デフォルトの辞書から変更してやれば、攻撃者に対する耐性の向上につながります。また、これは別の”security through obscurity”の方法ですが、母国語にローカライズされた辞書(私の場合ならフランス語)を使うという手もあります。このアプローチは、あなたへの基本的なリサーチが不十分な攻撃者を阻止することはできるでしょう。しかし、徹底的な攻撃者に対しては、そのメリットはすぐに失われてしまいます。

なお、パスワードのエントロピーは、どのワードリストが選択されたかではなく、その長さに依存することに注意してください。また、より大きな辞書は、検索空間を対数的にのみ拡張します。つまり、ワードリストの長さを2倍にしても、エントロピーは1ビットしか追加されません。ワードリストに1単語を追加するよりは、パスワードにその単語を追加した方がはるかに優れていると言えます。

セキュリティトークンを生成

前述したように、ほとんどのパスワードマネージャは、それぞれの方針(シンボルや長さなど)に基づいた強力なセキュリティトークンを生成する方法を備えています。通常、訪問するサイトのトークンを生成するには、パスワードマネージャのパスワード生成機能を使用する必要があります。しかし、それらの機能はどのように実行されるのでしょうか? あるいはパスワードマネージャ(例えば、Firefoxの マスターパスワード機能 )がパスワードを生成しない場合、どうすればいいのでしょうか?

UNIXの標準パスワードマネージャである pass は、このタスクを有名な pwgen プログラムに委譲しています。しかし pwgen は、セキュリティ上の問題に関してかなり悪い実績があり、特にデフォルトの”phoneme(音素)”モードでは、不均一に分散したパスワードが生成されます。 pass は、より”安全な” -s モードを使用していますが、私はデフォルトモードにおける pwgen の使用を妨げるため、そのオプションを削除してみようと考えました。そして、正しくパスワードを生成するような簡単なパッチを作成しました。詳細は、この Eメール に記載されています。結果的に、これをスキンする方法がたくさんあることが分かり、パスワードを生成するために次のようなパイプラインを提案しました。

    head -c $entropy /dev/random | base64 | tr -d '\n='

上記のコマンドは、 base64 アルゴリズムを使ったカーネル( head -c $entropy /dev/random )のエンコードから特定のバイト数を読み込んで、末尾の等号と改行を削除します(大きなパスワードの場合)。これは、Gillmorが言うところの “高エントロピー、コンパクトで転送可能/記憶可能な文字列” です。この場合の優先順位は、所定のエントロピーで、できるだけコンパクトなトークンを持つこと、そして同時に、使用できる文が制限されるサイトでは、できるだけ問題が起きない文字セットを使用することにあります。Gillmorは、 Assword パスワードマネージャの共同管理者で、そのパスワードマネージャにはbase64を選択しています。その理由は、base64が広く利用され、知識も共有され、スペースの占有がオリジナルの8ビットバイナリエンコーディングから33%しか増えないからです。passの管理者であるJason A. Donenfeldは、長い議論の末、次のパイプラインを選びました。

    read -r -n $length pass < <(LC_ALL=C tr -dc "$characters" < /dev/urandom)

上記は、 tr を直接使ってカーネルから文字を読み出すこと、そして文字と数字の [:alnum:] 、そしてシンボルの [:graph:] の構成物として、先に定義した特定の文字セット( $characters )をユーザの構成に応じて選択することを除けば、類似しています。次に、 read コマンドが選択された文字数を出力から抽出し、その結果を pass 変数に格納します。これについて、メーリングリストの参加者であるBrian Candlerは、base64と比較すると、 tr の使用により エントロピーをほとんど得ずに /dev/urandom からビットが破棄されるため、エントロピーが無駄になると 主張 しました。しかし最終的に保守管理者は、 /dev/urandom からの読み込みはLinuxの /proc/sys/kernel/random/entropy_avail には影響がない” と主張し、その異議を棄却しました。

パスワードマネージャをもう1つ。 KeePass は独自のルーチンを使用してトークンを生成しますが、手順は同じです。カーネルのエントロピーソース(およびKeePassの場合はユーザ生成のソース)から読み込み、そのデータを転送可能な文字列に変換します。

まとめ

パスワード管理には多くの側面がありますが、今回はユーザと開発者が安全かつ利用しやすいパスワードを生成するための様々な手法に焦点を当ててきました。強力で覚えやすいパスワードを生成することは、 pwgen ソフトウェアのセキュリティ上の脆弱性が明らかになったこともあり、決して無視できない問題です。自分のマシン任せに生成したパスワードは、時として熟練の攻撃者であれば、特にユーザのプロファイルが入手できる場合、簡単に推測されてしまうこともあります。ユーザが強力なパスワードを生成し、安全なトークンをパスワードマネージャに保存するよう促す簡単なツールを提供することは、私たちにとってとても重要なことなのです。

この記事の 初出Linux Weekly News です。