crypt ---用于检查Unix密码的功能

源代码: Lib/crypt.py


此模块实现与 crypt(3) 例程,它是基于修改后的DES算法的单向hash函数;有关详细信息,请参阅Unix手册页。可能的用途包括存储hash密码,这样您就可以在不存储实际密码的情况下检查密码,或者尝试使用字典破解UNIX密码。

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

Availability UNIX。VXWorks上不可用。

散列法

3.3 新版功能.

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

crypt.METHOD_SHA512

一种基于sha-512散列函数的16字符盐和86字符散列的模块化密码格式方法。这是最有力的方法。

crypt.METHOD_SHA256

另一种基于sha-256散列函数的模块化密码格式方法,具有16个字符的salt和43个字符的散列。

crypt.METHOD_BLOWFISH

另一种模块化密码格式方法,含22个字符的盐和31个字符的hash。

3.7 新版功能.

crypt.METHOD_MD5

另一种基于MD5散列函数的8字符盐和22字符散列的模块化密码格式方法。

crypt.METHOD_CRYPT

传统的方法有2个字符的盐和13个字符的hash。这是最薄弱的方法。

模块属性

3.3 新版功能.

crypt.methods

可用密码散列算法列表,如 crypt.METHOD_* 物体。此列表从最强到最弱排序。

模块功能

这个 crypt 模块定义以下功能:

crypt.crypt(word, salt=None)

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

检查密码通常通过将纯文本密码作为 word 以及之前的全部结果 crypt() 调用,应与此调用的结果相同。

salt (随机2或16个字符串,可能以 $digit$ 指示方法),它将用于干扰加密算法。中的字符 salt 必须在集合中 [./a-zA-Z0-9] ,除了模块化密码格式,它的前缀是 $digit$ .

以字符串形式返回hash密码,该字符串将由与salt相同的字母表中的字符组成。

由于少数 crypt(3) 扩展允许不同的值,在 salt ,建议在检查密码时使用完全加密的密码作为salt。

在 3.3 版更改: 接受 crypt.METHOD_* 除字符串之外的值 salt .

crypt.mksalt(method=None, *, rounds=None)

返回指定方法的随机生成的盐。如果没有 方法 如果给定,则返回 methods() 使用。

返回值是一个字符串,适合作为 salt 参数 crypt() .

rounds 指定的轮数 METHOD_SHA256METHOD_SHA512METHOD_BLOWFISH . 为了 METHOD_SHA256METHOD_SHA512 它必须是介于 1000999_999_999 ,默认为 5000 . 为了 METHOD_BLOWFISH 它必须是两个之间的力量 16 (二)42_147_483_648 (二)31 )默认为 4096 (二)12

3.3 新版功能.

在 3.7 版更改: 增加了 rounds 参数。

实例

一个简单的例子说明了典型的使用(需要一个持续的时间比较操作来限制暴露于定时攻击中)。 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

要使用最强大的可用方法生成密码的hash并对照原始方法进行检查,请执行以下操作:

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")