このプロジェクトのWiki

このプロジェクトのSourceForge.JPプロジェクトWikiページへようこそ。

SourceForge.JPでは、各プロジェクトごとにWikiシステムが利用できます。 このページも含め、あなたのプロジェクトに合わせて自由に書き換えてください。 デフォルトでは、このプロジェクトに参加しているユーザだけでなく、全てのSourceForge.JPのユーザがこのWikiスペースへの編集権を持っています。プロジェクトでの利用法に合わせて、適切に権限を設定しましょう!

このWikiシステムは現在継続的に開発中です。Wiki本体に関して、問題点や要望などがありましたら、 チケットを利用して報告お願い致します。 その前に、「Wikiってなに?」という方は、Wikipedia の「ウィキ」のページを参考にしてください。

文法などのドキュメントは、サイドバーに標準で入っているリンクか、SourceForge.JP プロジェクト内の Wikiガイド を参照してください。

開発の動機

とある金融機関からのメールに、自分とこのアカウントにはよそで使ってる のと同じ ID とパスワードを使わないでくれ、と書かれていました。まぁ、確 かにその通りです。でも、、、

そんなのムリ!

その時、把握しているものだけでも100以上のサイト / サービスを利用して いました (現在ではさらに増えてます)。これらを全部別々のパスワードに設定 するのは不可能ですよね。

という訳で、サイト毎、ユーザー毎 (そしてある種の制約への対処とより安 全性を向上させるために塩も) に異なるパスワードを生成するツールを作ろう と思い立ちました。

ちなみに、この日が来るまではどうしてたかと言うと、サービスの重要性に 応じて、いくつかのパスワードを用意して使い回していました。捨てアカウン トも使っていました。ただ、ほとんどのサイトではアカウントは共通になって いました。

ハードウェア・トークンを使わせるサイトもありました (三つ)。でも、 100以上のサイトが全部別のトークンを配ってたらすごいことになりますね。

これは何?

このツールはサイト毎に個別のパスワードを使うために、パスワードを自動 生成するものです。

自動生成のためにハッシュ関数を用いています。簡単に言うと、 (生の) パ スワードをハッシュ関数にかけ、ハッシュ値を (自動生成された) パスワード として使います。

実際には、サイト毎に個別のパスワードを人間が覚えるのは難しいと思いま すので、生のパスワードだけでなく、サイト情報も一緒にハッシュ関数にかけ ています。さらに、同じサイトで異なる ID (アカウント) を使う場合もあると 思いますので、ユーザー情報も一緒にハッシュ関数に加えています。さらにさ らに、同じサイト・ユーザーであっても、異なるパスワードを使う局面 (パス ワードの有効期限が切れた。 (生成された) パスワードが漏洩した、等々) が あると思いますので、塩 (salt) も加えています。

生のパスワード (生肉) + サイト情報 (野菜1) + ユーザー情報 (野菜2) + 塩 (塩)
↓
ハッシュ関数 (調理)
↓
パスワード (ハッシュドビーフもとい、肉野菜炒め)

ちなみに、サイトによってはパスワードとして有効な文字に制約がある場合 があります。例えば、 Yahoo! 等は特定の文字の並びは使えないようです。そ ういう場合にも塩を変えるだけで異なるパスワードが生成されますので、一応、 回避できます。人間系の運用ですが。(^^;

ハッシュ値をパスワードとして使うこと自体が安全かどうかは検証が必要で す。が、見た目は人間が考えるよりもランダムなパスワードが生成されていま す。

なお、 128bit (MD5) または 160bit (SHA-1) 程度のかなり長いパスワード が作られますので、長さという意味では安全性は高いと言えるでしょう。が、 先の通り、ハッシュ値であるという事実がありますので、ハッシュ値の安全性 に依存しています。

既に書いてますが、ハッシュ関数は今のところ MD5 を使っています。MD5 にはある種の脆弱性があるようなので SHA-1 も使えるようにしています。この 辺りの詳細については、安全性の項をご覧下さい。

ゴタクを並べても、とりあえず使ってみないとよく分からないでしょう。ま ずは、使ってみて下さい。

ご意見・ご感想をお待ちしています。

やりたいこと

  • 調査
    • RFC 2898 (PKCS #5: Password-Based Cryptography Specification Version 2.0) の調査:

      秘密鍵のような機密情報をパスワード・ベースの暗号方式で保護することに ついて書かれたもののようだ。

      パスワードから鍵を生成する方法として PBKDF (password-based key derivation function) というものを規定している。この鍵を共通鍵暗号の鍵と して秘密鍵の保護に使おうとしている?

      機密性が非常に高いと思われるが、パスワードから別の鍵を導出している点 は参考にできるかも知れない。つまり、導出された鍵をパスワードとして用い ることができるかも知れない。

      なお、機密性の高さは、 PGP のパス・フレーズを本システムで生成する程 度の安全性・妥当性を与えてくれるかも知れない。が、非常に回りくどい (パ スワード (→ 鍵) → パス・フレーズ → 秘密鍵を保護する鍵 → 秘密鍵 → 共通鍵 → 暗号 / 復号) 気もする。

      おそらく本来の用途はパス・フレーズから秘密鍵を保護する鍵を生成する部 分に使われるものだと思う (つまり、 PGP のようなソフト自体を作るためのも の)。

    • IKE における疑似乱数生成処理の調査 (RFC 4894 及び IKE 仕様):

      IPA で [http://www.ipa.go.jp/security/fy19/reports/Secure_Hash_Evaluation/ ハッ シュ関数安全性評価手法の開発に関する報告書]を見付けた。

      日立 富士通が報告しているが、この内、富士通からの報告の中で、ハッシュ関 数の脆弱性によって IKE / IPsec がどういう影響を受けるかについて、ハッシュ 関数の用途ごとに書かれている (p. 23)。

      これによると、疑似乱数生成について影響無し、とされていた。

      本システム (→ indivpas のこと) では、ハッシュ値を疑似乱数と見做して ランダムなパスワードが生成されることを期待しているが、このような使い方 であれば、発見されている脆弱性は問題にならないという予測は正しいのかも 知れない。

      ただし、この部分の記述はさらっと流されていて、詳細 (どういう風にハッ シュ関数を疑似乱数として扱うのか) や判断の根拠が不明である。この部分の 記述は RFC 4894 を元にしているようなので、その原文を参照すると共に、必 要に応じて IKE におけるハッシュ関数の利用法を調査したい。

    • 類似ツールの調査:

      方式と安全性について比較

  • 安全性の検証:

    識者の力を借りたい。

    SF.jp で公開したのも、単に個人ページ等で公開するよりも多くの人の目 (それも技術的に高度な) に触れ易いと思ったから

  • プラットフォームの拡充:

    特にケータイや PDA で利用したい (Web 上で実装 or Flash か)。

    ホーム環境とモバイル環境という運用形態も考慮したい。

  • SSO や OpenID 等のアカウント統合サービスへのスマートな対応:

    現状でもヒューリスティックにやれてます。

  • 実装方法の変更:

    現状はすぐに利用することを念頭にスクリプトで、しかも、様々な処理系を 混在させて実装している。

    システムの安全性を高めるためにはできるだけシンプルにしたい (スクリプ トであるとしても単一の言語処理系で閉じたい)。

    ただし、現状は非常に枯れた技術を用いているという認識であり、その点で は安全性が低いという訳ではない。

  • データ構造の検討:

    現状は site, user, password, salt の4つ組を明示的に分離して管理して いるが、全部引っ括めて nonce 等として扱うこともできるだろう。 (つまり、 アカウントを識別できれば、 "SF.jp に '09/11/17 に登録したアレだよ" のよ うな自然言語を nonce にしても良い)

    逆に、認証領域 (realm) を完全に記述すべきかも知れない。

  • サイト / サービスごとの文字種のデータベースの整備
  • データ管理のインターフェイス整備:

    特に、パスワードの変更等のよくある (しかし、煩雑) 運用シナリオを確実 に実行できるようにする。

  • パフォーマンス:

    性能よりも安全性を取りたいが、安全性が同等なら性能を向上させたい。

    現状では全く問題ありませんが

  • インストーラー
  • (G)UI:

    個人的に GUI は不要ですが、 UI 面で考慮することはありますね。

  • その他:

    Web 2.0 的な何か? (システム間の高度な連係に伴う…)

    ひとまづ、 URL と MIME type、拡張子は次のようなものを考えています。

    • URL:
      indivpas://user:pass@host/#salt
      

      salt にサーバー由来のもの、クライアント由来のものがある場合は以下の ようになりますか。

      indivpas://user:pass@host/s_salt#c_salt
      
    • MIME type (CT):
      application/x-indivpas
      または、
      text/x-indivpas
      
    • 拡張子:
      .indivpas
      

使い方

ますは、ソースとサンプルのデータ一式を取得します。

% svn checkout http://svn.sourceforge.jp/svnroot/indivpas/trunk indivpas
% cd indivpas

lib/indivpas.tsv がデータです。おそらく次のような内容になっているで しょう。

# SF.jp
sourceforge.jp	runshiwa		0	sha1sum-base62.sh	32
  • 全体はタブ区切りテキスト形式です。
  • # で始まる行は無視されます。
  • 以下はデータ行のフィールドの説明です。
    1. サイト:

      WWW のサービスなら URL のドメイン部等を指定すると良いでしょう。もし くは、より分かりやすい名称でも良いです。

    2. ユーザー:

      ユーザー ID を指定します。本物のユーザー ID である必要はありませんが、 一致させておいた方が便利でしょう。

      例では私の SF.jp のアカウントが書かれていますね。 (悪用しないように!)

    3. パスワード:

      通常は空にしておきます。何かを書いておくとそれが使われます。

      サイトによってはサイトが発行した固定のパスワードしか使えない場合もあ るので、それへの対処のためです。

      いわゆる "秘密の質問" を書いておいても良いかもしれません。

    4. 塩:

      暗号処理でよく使われるアレです。同じサイト、同じユーザー、同じ (生) パスワードであっても、生成されるパスワードを異なるものにするための乱数 です。

      適当なものを設定しておきましょう。数値じゃなくても大丈夫です。

    5. 方式:

      パスワードを生成するコマンドを指定します。大抵は配布物の src 下にあ るもの (後述) を指定することになります。

      上の例では、 SHA-1 を用い、数字・英大文字・英小文字からなるパスワー ドを生成します。

      上のパスワード欄に生のパスワードを指定した場合は、 "cat" コマンドを 指定しておけばそのまま出力されます。

    6. パスワード長:

      安全な方が良いでしょうから、そのシステムが許容可能な最大のパスワード 長を指定します。

      生成したパスワードから、この文字数分だけを切り出して使う、という指定 になります。

      ちなみに32文字というのは SF.jp の仕様とは違うかもしれません。日本語 サイトでは明記されていないのですが、本家 SF.net では32文字なので同じだ ろうということで32にしています。

それでは実行してみます。

その前に、データ・ファイルが参照できるように再構成します。例えば、

% cd src
% make PREFIX=~ configure

この例ではデータ・ファイルは ~/lib 配下に置くことになります。

構成し終わったら、 src 配下にある全てのファイルを起動できるようにパ スを通すか、パスの通った場所にコピーして下さい。例えば、

% cd ..
% cp -i src/*.{awk,pl,sh} ~/bin

データ・ファイルも先程指定した場所に配置します。

% cp -i lib/* ~/lib

これで準備は整いました。

まずは、リスト機能から、

% indivpas.awk -v mode=list lib/indivpas.tsv
runshiwa@sourceforge.jp

コマンドラインが煩雑ですが、それは今後の課題ということで。

次にパスワードを生成してみます。リストの出力を直接使えないインターフェ イスになっていますが、それも今後の課題ということで。

% indivpas.awk -v site=sourceforge.jp -v user=runshiwa lib/indivpas.tsv
runshiwa@sourceforge.jp
Password: 

(データのパスワード欄が空なので) パスワードを聞いてきたと思います。

自分の心の中だけにある本当のパスワードを入力します。

% indivpas.awk -v site=sourceforge.jp -v user=runshiwa lib/indivpas.tsv
runshiwa@sourceforge.jp
Password: hoehoe ← エコー・バックされません。
90aW7jcborQBPXI1BevEigbw2WH

表示された "90aW7jcborQBPXI1BevEigbw2WH" を SF.jp 用のパスワードとし て使うことになります。

次の例は自分の心の中のパスワードを変えた場合です。

% indivpas.awk -v site=sourceforge.jp -v user=runshiwa lib/indivpas.tsv
runshiwa@sourceforge.jp
Password: moemoe ← エコー・バックされません。
Wb1DD1CvqGL7c9OIZtliyKMkuyG

はい、さっきとは違うパスワードが生成されました ("90aW7jcborQBPXI1BevEigbw2WH" → "Wb1DD1CvqGL7c9OIZtliyKMkuyG")。

さらに別の例です。今度は塩を変えてみます。心の中のパスワードは変えま せん。

データは次のようにしてみましょう。

# SF.jp
sourceforge.jp  runshiwa                1       sha1sum-base62.sh       32

塩を "0" から "1" にしました。

データを変えたら、早速実行してみましょう。

% indivpas.awk -v site=sourceforge.jp -v user=runshiwa lib/indivpas.tsv
runshiwa@sourceforge.jp
Password: hoehoe ← エコー・バックされません。
957K806S4AfR9ynHaFNa6Tug2EY

同じサイト、同じユーザーでもパスワードを更新できました ("90aW7jcborQBPXI1BevEigbw2WH" → "957K806S4AfR9ynHaFNa6Tug2EY")。これ はパスワードの有効期限が切れた場合とかに使えますね。

という感じで、心の中のパスワードは全てのサイトで共通にしても、サイト ごと、ユーザーごと (そして塩ごと) に異なるパスワードを生成することがで きます。もちろん、心の中のパスワードをいくつか使い回しても良いですね。

src 配下の説明

  • indivpas.awk:

    本体です。

    主にデータの操作を行います。今のところ照会系のみできます。

  • genpas.awk:

    indivpas.awk からのデータを元に、ハッシュ値を計算し、パスワード文字 列を生成します。

    indivpas.awk はデータの集合を扱います。 genpas.awk は単一のデータを 扱います。

  • getpas.sh:

    ユーザーの頭の中にある真のパスワードを取得します。

    現状は端末ベースの UI なので、エコー・バックを禁止した上でプロンプト を出しています。

  • digit.pl:

    数値列を文字列に変換するフィルターです。 lib/*.digit というファイル を読み込んで、各桁に相当する文字を出力します。

    lib/*.digit は単純なテキスト・ファイルです。

    1行ごとに文字コードを記述しています。行数 = その桁の値・重さになりま す。つまり、 N 進数用の文字集合は N 行のデータになります。

    実際には各行には1文字以上記述できます。その場合はその桁の文字表現と して、改行までを全て出力します。これは多バイト文字に対応するためと、各 桁を単語で表現することも考慮しています。

  • md5sum-*.sh:

    MD5 というハッシュ関数を用いてパスワードを生成する処理です。

    出力する文字種によって何パターンか存在します。

    ハッシュ値の計算には md5sum を用いています。

    文字種の変換には digit.pl を用いています。

  • sha1sum-*.sh:

    SHA-1 というハッシュ関数を用いてパスワードを生成する処理です。 (MD5 には脆弱性があるということで、こちらの方を使った方が良いと思います。た だ、 SHA-1 も攻撃される可能性があるようです)

    ハッシュ値の計算には sha1sum を用いている以外は MD5 系と同じです。

実装の詳細

処理の主要部分は AWK で記述されているのでほぼ自明ですが、ハッシュ関 数への入力と出力がどのようにパスワード文字列に変換されるかを解説してお きます。

ハッシュ関数への入力

ずばり、

<サイト> <ユーザー> <生パスワード> <塩> "\n"
をこの順で単純に文字として連結したものです。

上の例 (塩が 0 でパスワード hoehoe) で言えば、

sourceforge.jprunshiwahoehoe0\n
になります。

ハッシュ値の算出

システムに付属していると思われる md5sum または sha1sum を使っていま す。この部分は小細工していません。

上の例 (sha1sum) で言えば、次の出力が得られます。

3f249c45b61f3ec3fa98a7bfe12f20e7b7076019  -

ハッシュ値からパスワード文字列への変換

*sum 系の出力は2カラムになっています。

1カラム目がハッシュ値です。2カラム目はファイル名ですが、入力をパイプ で標準入力で渡しているので "-" が出力されています。よって、ハッシュ値と して有効な1カラム目を抽出します。この処理は、現在の実装では AWK を用い ています。

3f249c45b61f3ec3fa98a7bfe12f20e7b7076019

また、 *sum の出力するハッシュ値は16進数表記になっています。使われる 文字は 0-9a-f です。

これは一般的にはパスワードとしては使えませんので、基数 = 文字種を変 換してやります。

考えられる基数としては、例えば、 0-9A-Za-z の62文字とか、 Base64 と 同等の記号を加えたものとか、記号を許可したものとかが考えられます。場合 によっては平仮名・片仮名を使っても良いかも知れません (ドラクエの復活の 呪文のよう)。

基数の変換には bc を用いています。

なお、 bc は16進数を処理できますが、 *sum 系が出力する英小文字は理解 できないので、 0-9A-F に変換しています。この処理は tr を用いています。

bc によって基数が変換されると、次のような形式で出力されます。

<数値> " " <数値> ...

具体的には、基数を99以上に変えた場合、

99 99 99 ...
というような出力が得られます。

16進数だと10以上の数の桁を表現する時にアルファベットの a-f を割り当 てて表現することが多いですが、基数が99にもなるとアルファベットでは足り ません (大文字・小文字の違いを含めても)。なので、このように1つの位を数 値 (この数値は10進数で表現される) で表現しています。

よって、この数値に対応した文字を1文字づつ出力すれば良いことになりま す。この部分の処理は Perl で行っています (文字種のバリエーションを切り 替えるのにシェル・スクリプトも併用しています)。

hoehoe~の例だと次のようになります。

3f249c45b61f3ec3fa98a7bfe12f20e7b7076019
↓
3F249C45B61F3EC3FA98A7BFE12F20E7B7076019
↓
 09 00 36 32 07 45 38 37 50 53 26 11 25 33 18 01 11 40 57 14 44 42 37 58 02 32 17
↓
90aW7jcborQBPXI1BevEigbw2WH

ちなみに、 bc の出力はもうちょっと厄介で、一行の最大桁数を固定値で持っ ているようなのです。この最大値を越えた場合、 "\" と改行文字が出力される ので、これも取り除いています。

例えば、 SHA-2 で最もビット長の大きな sha512sum を使うとこんな感じに なります。

 17 23 55 08 26 04 52 31 50 41 13 39 29 33 33 07 05 04 50 31 01 44 3\
0 34 45 46 00 22 09 32 06 45 38 22 16 57 24 30 20 13 46 25 08 47 34 \
53 01 42 41 36 07 37 24 39 16 01 30 19 07 33 17 42 38 16 18 46 37 57\
 53 58 32 51 43 08 01 03 10 46 46 55 05 10 27 42 08 10
↓
HNt8Q4qVofDdTXX754oV1iUYjk0M9W6jcMGvOUKDkP8lYr1gfa7bOdG1UJ7XHgcGIkbvrwWph813Akkt5ARg8A

これらの処理を終えると、使い方のところで示したようなパスワードっぽい 文字列が得られます。

あ、そうそう。最後にパスワードとして使用可能な文字数分だけを切り出し ています。この部分は最初の AWK スクリプト内に記述されています。hoehoe~ の例では実際には27文字のパスワードしか得られていませんけどね。

現在の実装の安全性について

次のことが言えると思います。

  • ファイルとして保存されるデータには秘密の情報が含まれない。

    ただし、生のパスワードを書くこともできて、その場合には秘密の情報が含 まれてしまいます。

    また、秘密情報ではありませんが、改竄された場合には以前利用していた生 成パスワードが復元できなくなってしまいます (特に塩が乱数なので、ユーザー が復元することが困難)。

    さらに、リモート等に置いて完全に公開してしまう場合、当該サイトにその ユーザーのアカウントが存在する可能性が暴露されます。

  • データ内に指定した任意のコマンドを実行できるようにしているので、デー タを操作される可能性がある場合は危険
  • 複数のコマンドを PATH 経由で呼び出している。

    PATH やその先のコマンドを細工できる場合、安全ではない。

    類似の脅威として、共有ライブラリーを介した攻撃もある。

    ただ、実行しているホストがローカルであるなら、信用したいところではあ る。

  • コマンドの一つはシェル・スクリプト (Bourne shell) である。

    一般的には、シェルは高機能なので、危険な処理を割り込ませることが比較 的容易です。

    ただし、今回の実装で利用している機能は余り多くないため、危険性は少な いのかも知れません (余り検証してませんが)。

  • 複数のコマンド間のデータのやり取り (IPC) にはパイプが使われている。

    一般的には安全と言えると思いますが (例えば、ファイルやコマンド・ライ ンや環境変数等でデータをやり取りするものより)、割り込まれる隙がない訳で はありません。

  • ハッシュ関数の入力データに明示的な区切りがない。

    上で説明した通り、要素を単純に連結している。

    これによって、例えば "site | user | pass | salt" と "siteu | ser | pass | salt" や "sit | euser | pass | salt" は連結後は同一の入力となる ため、同一のハッシュ値を生成する。

    同一のハッシュ値は、パスワード生成パラメーター (文字種や長さ) が同じ だと、同一のパスワードを生成してしまう。

    ただし、これが本当に安全でないのかは良く分からない。

    必要であれば、適当なセパレーターを明示的に置くことができる。

    例えば、

    user ":" pass "@" site "#" salt
    
    または、
    # site # user # pass # salt
    

    ただし、 # は直後のフィールドの長さを示す数値または数値に対応した文 字。

    また、入力の内のいくつかは、リモートのサイト (攻撃者に成り得る) 主導 で決めることが予想される (例えば、 site と user の文字列は攻撃者にとっ て恣意的なものにすることが容易)。

    salt は基本的にはローカルで勝手に決めるものだが、これは公開情報とす ることができる。

    salt の決定に当たって、将来リモート側との協調動作 (何らかの認証プロ トコルに組み込む等) の可能性もあるため、ある程度は攻撃者の意志が反映さ れる可能性がある。

    このことが本当に問題になるのかどうか確信していないが、暗号化に対する 差分解読のような攻撃に利用される可能性があるのかも知れない。

  • ハッシュ関数に MD5 または SHA-1 を用いている。

    MD5 には強衝突耐性を突破する手法が確立しているようです。

    SHA-1 にも強衝突耐性を突破する攻撃があるようですが、 MD5 ほど容易で はないようです (MD5 に対する攻撃の容易さ・困難さを把握していませんが)。

    ただし、データ内で任意のコマンドを指定できるので、別のハッシュ関数に 変更することは容易です (現時点の配布物に含まれていないという事)。

    実際、 Linux 等では SHA-2 を算出するコマンドも利用できますので、すぐ に変更することができます。

    なお、今回のハッシュ関数の用途は、データを検証するためのものではなく、 一方向性を利用して (擬似) 乱数を得るためのものなので、 MD5 / SHA-1 の脆 弱性・攻撃可能性は問題とならない可能性があります。

  • ハッシュ関数への入力が高々テキスト1行 (<100文字) 程度しかない。

    MD5 / SHA-1 の特性にも依りますが、最終的に生成されるハッシュ値をパス ワードとして利用するのに十分な初期ベクトルとなっているかは未確認です。

    別途、エントロピー源となるような入力を設けた方が良いのかも知れません (例えば、数 MB 程度の乱数ファイル)。

  • ハッシュ関数の出力を直接利用すること自体が (パスワードとして。また はその元となる乱数として) 安全ではない可能性がある。

    用途はパスワードであるが、共通鍵暗号系におけるセッション鍵の生成と似 たような問題と捉えられるかも知れない。

    例えば、 Wikipedia のこのエントリーには、

    暗号プリミティブに基づく設計
    
    暗号論的に安全なハッシュ関数も、場合によってはCSPRNGとして利用可能である。この場合、カウンタの初期値をランダム化して秘密にしなければならない。カウンタが多倍長整数であれば、このCSPRNGはほぼ無限に乱数を生成できる。しかし、これについて安全ではないとする者もいる[3]。
    
    とあり、肯定も否定もされている ([3] は "Young and Yung, Malicious Cryptography, Wiley, 2004, sect 3.2" だが、原文へのリンクはない)。

    ここにあるカウンターというのは IV (初期ベクトル) 程度の意味だと思わ れるが、本システムではユーザーの頭の中にある秘密のパスワードと塩の組み 合わせが相当することになる。

    また、 Linux の Secure Programming for Linux and Unix HOWTO には以下の記述があった。

    10.3. 乱数
    
    PRNG の出力として、暗号化ハッシュ機能(たとえば、SHA-1)の利用も検討してもよいと思います。ハッシュアルゴリズムを使えば、PRNG の出力が推測できるようになったとしても、攻撃者は、さらにハッシュ機能も片づけなければならないからです。
    

    ここでは、単にハッシュ関数を使うのではなく、 PRNG の出力をさらにハッ シュ関数にかけることについて言及している。

    この部分の記述が、ハッシュ関数を単独で利用することを否定しているとは 言えないとは思われる。

    この他、単独でハッシュ関数を用いない方式としては以下のようなものが考 えられると思う。

    • ハッシュ関数を単独で使用する。

      H(host | user | pass | salt)

    • ハッシュ関数を多段で使用する。

      H(H(...H(host | user | pass | salt)...))

    • 異なるハッシュ関数を多段で使用する。

      H(H'(...H''''''(host | user | pass | salt)...))

    • 擬似乱数を使用する。

      R(host | user | pass | salt)

    • 疑似乱数をハッシュ関数にかける。

      H(R(host | user | pass | salt))

    • ハッシュ関数の出力を種として疑似乱数を生成する。

      R(H(host | user | pass | salt))

    • 暗号化する。

      C(host | user | pass | salt, key)

    • 暗号データをハッシュ関数にかける。

      H(C(host | user | pass | salt, key))

    • ハッシュ値を暗号化する。

      C(H(host | user | pass | salt), key)

    • 暗号データを疑似乱数の種とする。

      R(C(host | user | pass | salt, key))

    • 疑似乱数を暗号化する。

      C(R(host | user | pass | salt), key)

    • ハッシュ値を暗号化の鍵とする。

      C(nonce, H(host | user | pass | salt))

    • 乱数を暗号化の鍵とする。

      C(nonce, R(host | user | pass | salt))

    • もっと複雑な組み合わせ

      関数及び、どこにパラメーター (特に salt) を添加するか、等々

    それぞれの得失、または安全性 (or 脆弱性) は不明

    逆に、もし安全性が定量的に量れるなら、必要な安全性が保証される範囲内 でパスワードの更新を行う運用もできる。 (例えば、3番目の方法だと1週間が 限度なので毎週 salt を更新する、等々)

    ちなみに、組み合わせという意味においては、 UNIX の crypt(3) の内部処 理は、 DES 版で25 回MD5 版 では1000回もの反復を含んでいるようだ。

    25及び1000という回数の安全性の根拠は不明 (Wikipedia によ ると、 DES 版の処理は当時の計算機で1秒以上かかっていた (On the earliest Unix machines it took over a full second to compute a password hash.) とのこと)

  • 生成されたパスワードは本当に安全か?

    ハッシュ関数が完全であれば、ハッシュ値は乱数であると見做せると思う (ただ、これ自体に確信は得られていない)。

    乱数であること自体には問題ないが、その結果として、パスワード文字列に 現われる文字種が限定される場合、例えば全部数字だけから成るパスワードが 生成される可能性も有り得る。

    この場合、限られた文字種を対象とした総当たり攻撃に看破される可能性が 高い。

    ただし、パスワード中に使われる文字種の数や割り合いに制約を設けること が、却ってパスワード空間を狭めてしまう可能性はある。

    生成したパスワードを検定するべきかも知れない。

    なお、実際にそういう脆弱なパスワードが生成された場合、塩を変えること によって別のパスワードを生成して回避することは可能である。

  • ハッシュ関数の一方向性の使い方

    現状の実装では一方向性を乱数に見える数値を生成するためだけに利用して いる。このような利用法は、厳密には一方向性を活用しているとは言わないの かも知れない。

    crypt(3) の反復処理では、処理の各段階を強固なものにするのに使われて いると言える (かも知れない)。

    この他、例えば S/KEY のように、複数の認証回に使われるパスワードの系 列を保護するために一方向性を利用する例もある。

  • 数値を基数変換したものを文字列に置き換え、そのままパスワードにして いる。

    基数変換自体はおそらく問題はないのだと思いますが、確証は得ていません。

    なお、最上位桁 (表示上は一桁目で、パスワードにも採用される) は基数に よっては出現する文字種が減少してしまいますので、除くべきかも知れません が、現状では対処してません。

    これに関連して、現在の実装では bc で基数変換をしていますが、上位桁の 0の出力が抑制されています。

    つまり、可変長の出力になっていますが、本来であれば固定長 (0も出力す る) であるべきでしょう。 (ただし、連続する文字がパスワード中に現れるこ と自体がパスワードの強度を損う可能性があるので、一考の余地があるかも知 れません)

  • ハッシュ値の一部を利用することの是非

    MD5 の出力する 128bit の数値をアルファベット及び数字から成る 62 種の 記号 (62進数) で表わした場合、 log(2^128^) / log(62) = 21.5 より 22 桁 の数値 (文字列) が得られる。

    この内、実際にシステムに入力可能な文字数分 (例えば8文字) だけを切り 出して使うことになるが、これがどの程度安全なのかが分かっていない。

    なお、現状の実装では上位桁から連続した文字を利用しているが、上位と下 位 (または任意の部分) で安全性に差異があるのかは未確認 (疑似乱数等では、 下位を使うのは良くないこととされている実装が存在しますね)

  • 生成したパスワードを利用する際のセキュリティーが考慮されていない。

    今の所、端末にそのまま表示しています (覗き見に注意!)。

    ユーザーが端末の表示をコピペする場合はクリップボード等の安全性を考え る必要があります。

    ユーザーが HTML のフォームにコピペまたは入力した後は、 WWW のセキュ リティーに従うことになります。

  • 認証ダイアログ / フォームを提示しているサイト / サービスを認証して いない。

    この辺りは、現状、人任せです。

  • パスワードの更新系は、現時点では本システムに含まれていない。

    安全性はサイトごとのパスワード更新手順に依存する。

    ただ、サイトごとに独立した (ように見える) パスワードを利用しているた め、パスワード文字列が暴露されることによる危険性はサイトに限定される。

  • その他