def crypt(word, salt=None):
"""Return a string representing the one-way hash of a password, with a salt
prepended.
If ``salt`` is not specified or is ``None``, the strongest
available method will be selected and a salt generated. Otherwise,
``salt`` may be one of the ``crypt.METHOD_*`` values, or a string as
returned by ``crypt.mksalt()``.
"""
if salt is None or isinstance(salt, _Method):
salt = mksalt(salt)
return _crypt.crypt(word, salt) 打开glibc源文件中crypt目录下的crypt-entry.c文件,我们可以看到根据盐值前三个字符进行哈希算法选择的代码:
/* Define our magic string to mark salt for MD5 encryption
replacement. This is meant to be the same as for other MD5 based
encryption implementations. */
static const char md5_salt_prefix[] = "$1$";
/* Magic string for SHA256 encryption. */
static const char sha256_salt_prefix[] = "$5$";
/* Magic string for SHA512 encryption. */
static const char sha512_salt_prefix[] = "$6$";
/* For use by the old, non-reentrant routines (crypt/encrypt/setkey) */
extern struct crypt_data _ufc_foobar; 在测试过程中最开始下载的是glibc2.6,这个版本并没有$5$和$6$对应的sha256/sha512算法,只有MD5,然后下载了最新的glibc2.18版本才看到了这两个算法,可以猜出使用glibc2.6版本及以前的版本的linux系统中,shadow文件并不是现在这样的。本Ubuntu系统的gblic版本是2.11(ldd --version查看),该版本glibc也支持sha256/sha512。我们给出的例子里前三个字符是“$6$”,我们可以知道系统使用的哈希算法是sha512。由于python调用的是glibc中的crypt算法,所以自然可以知道在windows平台下python的这个算法是无法调用的。现在使用python写一些脚本来测试一下:
在crypt函数中输入两个参数,一个是我们的登陆密码,另一个是盐值,我们可以看到输出的结果和shadow文件中经过处理的密码字符串相同。
shadow文件默认只能由root用户访问,一般用户没有访问权限,非法入侵者通过一定途径获得该文件后通过暴力尝试密码就有可能获得原始的明文密码,所以用户在设置密码的时候尽量包含多种字符(大小写、数字、特殊符号)并超过一定的长度,以此来提升系统的安全性。