# `crypt` --- Unix パスワードをチェックするための関数

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

バージョン 3.11 で非推奨、バージョン 3.13 で削除予定: The `crypt` module is deprecated (see PEP 594 for details and alternatives). The `hashlib` module is a potential replacement for certain use cases. The passlib package can replace all use cases of this module.

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

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

Availability: Unix, not VxWorks.

利用可能性: Emscripten でなく、WASI でもないこと。

このモジュールは WebAssembly プラットフォーム `wasm32-emscripten` と `wasm32-wasi` では動作しないか、利用不可です。詳しくは、WebAssemblyプラットフォーム を見てください。

## ハッシュ化方式

Added in version 3.3.

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

crypt.METHOD_SHA512

  A Modular Crypt Format method with 16 character salt and 86 character hash based on the SHA-512 hash function. This is the strongest method.

crypt.METHOD_SHA256

  Another Modular Crypt Format method with 16 character salt and 43 character hash based on the SHA-256 hash function.

crypt.METHOD_BLOWFISH

  Another Modular Crypt Format method with 22 character salt and 31 character hash based on the Blowfish cipher.

  Added in version 3.7.

crypt.METHOD_MD5

  Another Modular Crypt Format method with 8 character salt and 22 character hash based on the MD5 hash function.

crypt.METHOD_CRYPT

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

## モジュール属性

Added in version 3.3.

crypt.methods

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

## モジュール関数

`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 available in `methods` will be used.

  通常は、生の文字列のパスワードを 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, *, rounds=None)

  Return a randomly generated salt of the specified method. If no method is given, the strongest method available in `methods` is used.

  The return value is a string suitable for passing as the salt argument to `crypt()`.

  rounds specifies the number of rounds for `METHOD_SHA256`, `METHOD_SHA512` and `METHOD_BLOWFISH`. For `METHOD_SHA256` and `METHOD_SHA512` it must be an integer between `1000` and `999_999_999`, the default is `5000`. For `METHOD_BLOWFISH` it must be a power of two between `16` (24) and `2_147_483_648` (231), the default is `4096` (212).

  Added in version 3.3.

  バージョン 3.7 で変更: Added the rounds parameter.

## 使用例

典型的な使い方を簡単な例で示します (タイミング攻撃に晒されないように、一定時間の比較演算子を使う必要があり、 `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")