我在学Python。我不明白为什么hashlib.sha512(salt + password).hexdigest()没有给出预期的结果。
(我花了一段时间才弄清楚我在找什么。)
根据我的Ubuntu12.04系统上的crypt手册页,crypt使用的是SHA-512 (因为字符串以$6$开头)。
多么?
下面的代码显示了我遇到的问题:
import hashlib, crypt
ctype = "6" #for sha512 (see man crypt)
salt = "qwerty"
insalt = '${}${}$'.format(ctype, salt)
password = "AMOROSO8282"
value1 = hashlib.sha512(salt + password).hexdigest() #what's wrong with this one?
value2 = crypt.crypt(password, insalt) #this one is correct on Ubuntu 12.04
if not value1 == value2:
print("{}\n{}\n\n".format(value1, value2))根据加密手册页,SHA-512是86个字符。上面代码中的crypt()调用符合这一点。
下面是那些不想运行代码的人的输出:
051f606027bd42c1aae0d71d049fdaedbcfd28bad056597b3f908d22f91cbe7b29fd0cdda4b26956397b044ed75d50c11d0c3331d3cb157eecd9481c4480e455
$6$qwerty$wZZxE91RvJb4ETR0svmCb69rVCevicDV1Fw.Y9Qyg9idcZUioEoYmOzAv23wyEiNoyMLuBLGXPSQbd5ETanmq/这里是基于初始反馈的另一次尝试。目前还没有成功:
import hashlib, crypt, base64
ctype = "6" #for sha512 (see man crypt)
salt = "qwerty"
insalt = '${}${}$'.format(ctype, salt)
password = "AMOROSO8282"
value1 = base64.b64encode(hashlib.sha512(salt + password).digest())
value2 = crypt.crypt(password, insalt) #this one is correct
if not value1 == value2:
print("{}\n{}\n\n".format(value1, value2))发布于 2014-01-13 01:51:24
这就是解决方案。关于另一个问题还有更多细节:Python implementation of sha512_crypt.c,其中显示passlib的后端包含sha512_crypt的纯Python实现(如果crypt.crypt()在操作系统上不可用,则调用Python实现)。
$ sudo pip安装passlib
import passlib.hash, crypt
ctype = "6" #for sha512 (see man crypt)
salt = "qwerty"
insalt = '${}${}$'.format(ctype, salt)
password = "AMOROSO8282"
value1 = sha512_crypt.encrypt(password, salt=salt, rounds=5000)
value2 = crypt.crypt(password, insalt)
if not value1 == value2:
print("algorithms do not match")
print("{}\n{}\n\n".format(value1, value2))下面是输出:
$6$qwerty$wZZxE91RvJb4ETR0svmCb69rVCevicDV1Fw.Y9Qyg9idcZUioEoYmOzAv23wyEiNoyMLuBLGXPSQbd5ETanmq/
$6$qwerty$wZZxE91RvJb4ETR0svmCb69rVCevicDV1Fw.Y9Qyg9idcZUioEoYmOzAv23wyEiNoyMLuBLGXPSQbd5ETanmq/一个关键点是,Passlib有一个纯Python的sha512_crypt实现,当系统没有当前Linux系统所具有的加密实现(例如,http://www.akkadia.org/drepper/SHA-crypt.txt)时,它将使用它。
请参阅此处的PassLib 文档:
passlib - python的密码散列库- Google项目托管
https://code.google.com/p/passlib/
Passlib 1.6.2文档- Passlib v1.6.2文档
http://pythonhosted.org/passlib/
passlib-用户- Google组
https://groups.google.com/forum/#!forum/passlib-users
新应用程序快速入门指南- Passlib v1.6.2文档
http://pythonhosted.org/passlib/new_app_quickstart.html#sha512-crypt
passlib.hash.sha512_crypt -SHA-512Crypt- Passlib v1.6.2文档
http://pythonhosted.org/passlib/lib/passlib.hash.sha512_crypt.html#passlib.hash.sha512_crypt
发布于 2014-01-12 10:18:56
crypt的手册是不精确的(甚至具有误导性)。crypt使用的带有“MD5”、“SHA-256”或“SHA-512”绰号的算法实际上就是基于这些原语构建的算法。它们是使用散列执行key strengthening的password-based key derivation functions。
good password hashing algorithm有两个属性:它必须将密码与唯一的盐组合在一起(为了一次破解多个密码的尝试),并且它必须很慢(因为这对攻击者的伤害比对防御者的伤害更大,因为攻击者需要尝试大量的组合)。像MD5和SHA系列这样的日常散列算法被设计为快速,尽可能快,同时仍然具有所需的安全属性。构建密码散列算法的一种方法是采用加密散列算法并多次迭代它。虽然这个isn't ideal (因为有更好的技术使得构建用于密码破解的专用硬件变得更加困难),但它已经足够了。
Wikipedia article for crypt(3)提供了简短的解释,并提供了指向主要来源的指针。Linux和FreeBSD的手册页很差,但是Solaris's有足够的信息来避免误导(沿着crypt.conf(4)的链接,然后是crypt_sha512和其他)。您还可以阅读Is user password in ubuntu 13.04 in plain text?和Is there repetition in the Solaris 11 hash routine? Can I add some?
在Python语言中计算crypt输出的正确方法是调用crypt.crypt。
发布于 2014-01-11 16:19:52
您的密码长度不同,这是因为crypt()输出是base64编码的,并且您对value1使用十六进制。
而不是十六进制,您应该尝试这样做
value1 = crypt_base64(hashlib.sha512(salt + password))与bash implementation一样,crypt_base64是doHash()函数的最后一部分。
https://stackoverflow.com/questions/21090312
复制相似问题