crypt — 检查 Unix 密码的函数 — Python 文档

来自菜鸟教程
Python/docs/3.9/library/crypt
跳转至:导航、​搜索

crypt — 检查 Unix 密码的函数

源代码: :source:`Lib/crypt.py`



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

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

散列方法

3.3 版中的新功能。


crypt 模块定义了散列方法列表(并非所有方法都适用于所有平台):

crypt.METHOD_SHA512
基于 SHA-512 散列函数的具有 16 个字符盐和 86 个字符散列的模块化密码格式方法。 这是最强的方法。
crypt.METHOD_SHA256
另一种基于 SHA-256 散列函数的模块化密码格式方法,具有 16 个字符的盐和 43 个字符的散列。
crypt.METHOD_BLOWFISH

另一种基于 Blowfish 密码的模块化密码格式方法,具有 22 个字符的盐和 31 个字符的散列。

3.7 版中的新功能。

crypt.METHOD_MD5
另一种基于 MD5 散列函数的模块化密码格式方法,具有 8 个字符的盐和 22 个字符的散列。
crypt.METHOD_CRYPT
使用 2 个字符的盐和 13 个字符的哈希的传统方法。 这是最弱的方法。


模块属性

3.3 版中的新功能。


crypt.methods
可用密码散列算法的列表,作为 crypt.METHOD_* 对象。 此列表从最强到最弱排序。


模块功能

crypt 模块定义了以下函数:

crypt.crypt(word, salt=None)

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

检查密码通常是通过将明文密码作为 word 和之前 crypt() 调用的完整结果传递来完成的,这应该与这次调用的结果相同.

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

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

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

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

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

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

返回值是一个适合作为 salt 参数传递给 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 版中的新功能。

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

要使用最强的可用方法生成密码的哈希值并对照原始方法进行检查:

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