crypt —检查 Unix 密码的Function

源代码: Lib/crypt.py


该模块实现了* crypt(3) *例程的接口,该例程是基于修改后的 DES 算法的单向哈希函数;有关更多详细信息,请参见 Unix 手册页。可能的用途包括存储哈希密码,以便您可以在不存储实际密码的情况下检查密码,或try使用字典破解 Unix 密码。

注意,此模块的行为取决于正在运行的系统中* crypt(3) *例程的实际实现。因此,当前实现上可用的任何扩展也将在此模块上可用。

Availability:Unix。在 VxWorks 上不可用。

Hashing Methods

版本 3.3 中的新Function。

crypt模块定义了哈希方法列表(并非所有方法在所有平台上都可用):

  • crypt. METHOD_SHA512

    • 一种基于 SHA-512 哈希函数的具有 16 个字符的盐和 86 个字符的哈希的模块化加密格式方法。这是最强的方法。
  • crypt. METHOD_SHA256

    • 另一种基于 SHA-256 哈希函数的具有 16 个字符的盐和 43 个字符的哈希的模块化地穴格式方法。
  • crypt. METHOD_BLOWFISH

    • 另一种基于 Blowfish 密码的具有 22 个字符的盐和 31 个字符的哈希的模块化地穴格式方法。

3.7 版中的新Function。

  • crypt. METHOD_MD5

    • 另一种基于 MD5 哈希函数的具有 8 个字符的盐和 22 个字符的哈希的模块化地穴格式方法。
  • crypt. METHOD_CRYPT

    • 传统方法使用 2 个字符的盐和 13 个字符的哈希。这是最弱的方法。

Module Attributes

版本 3.3 中的新Function。

  • crypt. methods
    • 可用密码哈希算法的列表,以crypt.METHOD_*个对象表示。此列表从最强到最弱进行排序。

Module Functions

crypt模块定义以下Function:

  • crypt. crypt(* word salt = None *)
      • word 通常是在提示或图形界面中键入的用户密码。可选的 salt 可以是从mksalt()返回的字符串,crypt.METHOD_*值之一(尽管并非所有平台上都可以使用),也可以是此函数返回的包含 salt 的完整加密密码。如果未提供 salt *,则将使用最强的方法(由methods()返回)。

通常pass将纯文本密码作为* word *传递,并将先前的crypt()调用的完整结果传递给密码,从而完成密码检查,该结果应与此调用的结果相同。

  • salt *(一个随机的 2 或 16 个字符串,可能以$digit$表示该方法),将用于扰乱加密算法。 * salt *中的字符必须位于集合[./a-zA-Z0-9]中,但以$digit$为前缀的 Modular Crypt Format 除外。

以字符串形式返回哈希密码,该密码由与 salt 相同字母的字符组成。

由于一些* crypt(3) extensions 允许 salt *中具有不同大小的不同值,因此建议在检查密码时使用完全加密的密码作为盐。

在版本 3.3 中进行了更改:除* salt *的字符串外,还接受crypt.METHOD_*个值。

  • crypt. mksalt(方法=无,***,回合=无)
    • 返回指定方法的随机生成的盐。如果没有给出方法,则使用methods()返回的最强方法。

返回值是一个字符串,适合作为参数传递给crypt()

  • rounds *指定METHOD_SHA256METHOD_SHA512METHOD_BLOWFISH的回合数。对于METHOD_SHA256METHOD_SHA512,它必须是1000999_999_999之间的整数,默认值为5000。对于METHOD_BLOWFISH,它必须是16(24)和2_147_483_648(231)之间的 2 的幂,默认值为4096(212)。

版本 3.3 中的新Function。

在 3.7 版中进行了更改:添加了* rounds *参数。

Examples

一个简单的示例说明典型用法(需要进行恒定时间比较操作以限制对定时攻击的暴露.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")