35.5. "crypt" --- Unix パスワードをチェックするための関数
*********************************************************

**ソースコード:** Lib/crypt.py

======================================================================

このモジュールは修正 DES アルゴリズムに基づいた一方向ハッシュ関数であ
る *crypt(3)*  ルーチンを実装しています。詳細については Unix マニュア
ルページを参照してください。このモジュールは、実際に入力されたパスワー
ドを記録することなくチェック出来るようにするためのハッシュ化パスワード
を記録したり、Unix パスワードに (脆弱性検査のための) 辞書攻撃を試みる
のに使えます。

このモジュールは実行環境の *crypt(3)* の実装に依存しています。そのため
、現在の実装で利用可能な拡張を、このモジュールでもそのまま利用できます
。


35.5.1. ハッシュ化方式
======================

バージョン 3.3 で追加.

"crypt" モジュールはハッシュ化方式の一覧を定義しています (すべての方式
がすべてのプラットフォームで使えるわけではありません):

crypt.METHOD_SHA512

   16文字のソルトと86文字のハッシュ値を持つモジュラー暗号形式です。こ
   れが最も強い方式です。

crypt.METHOD_SHA256

   16文字のソルトと43文字のハッシュ値を持つモジュラー暗号形式です。

crypt.METHOD_MD5

   8文字のソルトと22文字のハッシュ値を持つモジュラー暗号形式です。

crypt.METHOD_CRYPT

   2文字のソルトと13文字のハッシュ値を持つモジュラー暗号形式です。これ
   が最も弱い方式です。


35.5.2. モジュール属性
======================

バージョン 3.3 で追加.

crypt.methods

   利用可能なパスワードのハッシュアルゴリズムのリストを、
   "crypt.METHOD_*" オブジェクトとして返します。 このリストは最も強い
   ものから弱いものの順で並べられています。


35.5.3. モジュール関数
======================

"crypt" モジュールは以下の関数を定義しています:

crypt.crypt(word, salt=None)

   *word* will usually be a user's password as typed at a prompt or
   in a graphical interface.  The optional *salt* is either a string
   as returned from "mksalt()", one of the "crypt.METHOD_*" values
   (though not all may be available on all platforms), or a full
   encrypted password including salt, as returned by this function.
   If *salt* is not provided, the strongest method will be used (as
   returned by "methods()").

   通常は、生の文字列のパスワードを *word* として渡し、前回の
   "crypt()" を呼び出した結果と今回の呼び出しの結果が同じになることで
   、パスワードの確認を行います。

   *salt* (2文字から16文字のランダムな文字列で、方式を示す "$digit$"
   が先頭に付いているかもしれません) は、暗号化アルゴリズムにぶれを生
   じさせるために使われます。 *salt* に含まれる文字は、モジュラー暗号
   形式の先頭にある "$digit$" を除いて、集合 "[./a-zA-Z0-9]" に含まれ
   ていなければいけません。

   ハッシュ化されたパスワードを文字列として返します。それは salt と同
   じアルファベット文字から構成されます。

   いくつかの拡張された *crypt(3)* は異なる値と *salt* の長さを許して
   いるので、パスワードをチェックする際には crypt されたパスワード文字
   列全体を *salt* として渡すよう勧めます。

   バージョン 3.3 で変更: 文字列に加え、 *salt* が "crypt.METHOD_*" 値
   も受け取るようになりました。

crypt.mksalt(method=None)

   指定された方式のランダムに生成されたソルトを返します。 *method* が
   与えられなかった場合は、 "methods()" で返される方式のうち最も強いも
   のが使われます。

   返り値は、 "crypt.METHOD_CRYPT" のための長さ2の文字列か、 "$digit$"
   の後に集合 "[./a-zA-Z0-9]" にあるランダムな16文字が続く長さ19の文字
   列で、 "crypt()" に *salt* 引数として渡せるものです。

   バージョン 3.3 で追加.


35.5.4. 使用例
==============

典型的な使い方を簡単な例で示します (タイミング攻撃に晒されないように、
一定時間の比較演算子を使う必要があり、 "hmac.compare_digest()" がこの
目的にちょうど良いです):

   import pwd
   import crypt
   import getpass
   from hmac import compare_digest as compare_hash

   def login():
       username = input('Python login: ')
       cryptedpasswd = pwd.getpwnam(username)[1]
       if cryptedpasswd:
           if cryptedpasswd == 'x' or cryptedpasswd == '*':
               raise ValueError('no support for shadow passwords')
           cleartext = getpass.getpass()
           return compare_hash(crypt.crypt(cleartext, cryptedpasswd), cryptedpasswd)
       else:
           return True

利用可能な方式のうち最も強い方式を使いパスワードのハッシュ値を生成し、
元のパスワードと比較してチェックします:

   import crypt
   from hmac import compare_digest as compare_hash

   hashed = crypt.crypt(plaintext)
   if not compare_hash(hashed, crypt.crypt(plaintext, hashed)):
       raise ValueError("hashed version doesn't validate against original")
