crypt
— 检查 Unix 密码的函数¶
源代码: Lib/crypt.py
自 3.11 版本弃用,将在 3.13 版本中移除:crypt
模块已弃用(有关详细信息和备选方案,请参阅 PEP 594)。hashlib
模块是某些用例的潜在替代方案。passlib 包可以替代此模块的所有用例。
此模块实现了 crypt(3) 例程的接口,这是一个基于修改后的 DES 算法的单向哈希函数;有关更多详细信息,请参阅 Unix 手册页。可能的用途包括存储哈希密码,以便您可以在不存储实际密码的情况下检查密码,或尝试使用字典破解 Unix 密码。
请注意,此模块的行为取决于正在运行的系统中 crypt(3) 例程的实际实现。因此,当前实现中可用的任何扩展也将在本模块中可用。
可用性:Unix,不包括 VxWorks。
可用性:不包括 Emscripten,不包括 WASI。
此模块在 WebAssembly 平台 wasm32-emscripten
和 wasm32-wasi
上无法使用或不可用。有关更多信息,请参阅 WebAssembly 平台。
哈希方法¶
在版本 3.3 中添加。
crypt
模块定义了哈希方法的列表(并非所有方法在所有平台上都可用)
- crypt.METHOD_SHA512¶
一种模块化加密格式方法,具有 16 个字符的盐和基于 SHA-512 哈希函数的 86 个字符的哈希。这是最强大的方法。
- crypt.METHOD_SHA256¶
另一种模块化加密格式方法,具有 16 个字符的盐和基于 SHA-256 哈希函数的 43 个字符的哈希。
- crypt.METHOD_BLOWFISH¶
另一种模块化加密格式方法,具有 22 个字符的盐和基于 Blowfish 密码的 31 个字符的哈希。
在版本 3.7 中添加。
- crypt.METHOD_MD5¶
另一种模块化加密格式方法,具有 8 个字符的盐和基于 MD5 哈希函数的 22 个字符的哈希。
- crypt.METHOD_CRYPT¶
传统方法,具有 2 个字符的盐和 13 个字符的哈希。这是最弱的方法。
模块属性¶
在版本 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$
为前缀。将哈希密码作为字符串返回,该字符串将由与 salt 相同字母表中的字符组成。
由于一些 crypt(3) 扩展允许不同的值,salt 中的大小也不同,因此建议在检查密码时使用完整的加密密码作为 salt。
在版本 3.3 中更改:除了 salt 的字符串之外,还接受
crypt.METHOD_*
值。
- crypt.mksalt(method=None, *, rounds=None)¶
返回指定方法的随机生成的 salt。如果没有给出 method,则使用
methods
中可用的最强方法。返回值是一个字符串,适合作为 salt 参数传递给
crypt()
。rounds 指定
METHOD_SHA256
、METHOD_SHA512
和METHOD_BLOWFISH
的轮数。对于METHOD_SHA256
和METHOD_SHA512
,它必须介于1000
和999_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")