首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >hashlib与Python中的crypt.crypt()。为什么结果不同?

hashlib与Python中的crypt.crypt()。为什么结果不同?
EN

Stack Overflow用户
提问于 2014-01-11 15:21:33
回答 3查看 14.4K关注 0票数 10

我在学Python。我不明白为什么hashlib.sha512(salt + password).hexdigest()没有给出预期的结果。

(我花了一段时间才弄清楚我在找什么。)

根据我的Ubuntu12.04系统上的crypt手册页,crypt使用的是SHA-512 (因为字符串以$6$开头)。

多么?

下面的代码显示了我遇到的问题:

代码语言:javascript
复制
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()调用符合这一点。

下面是那些不想运行代码的人的输出:

代码语言:javascript
复制
051f606027bd42c1aae0d71d049fdaedbcfd28bad056597b3f908d22f91cbe7b29fd0cdda4b26956397b044ed75d50c11d0c3331d3cb157eecd9481c4480e455
$6$qwerty$wZZxE91RvJb4ETR0svmCb69rVCevicDV1Fw.Y9Qyg9idcZUioEoYmOzAv23wyEiNoyMLuBLGXPSQbd5ETanmq/

这里是基于初始反馈的另一次尝试。目前还没有成功:

代码语言:javascript
复制
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))
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-01-13 01:51:24

这就是解决方案。关于另一个问题还有更多细节:Python implementation of sha512_crypt.c,其中显示passlib的后端包含sha512_crypt的纯Python实现(如果crypt.crypt()在操作系统上不可用,则调用Python实现)。

$ sudo pip安装passlib

代码语言:javascript
复制
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))

下面是输出:

代码语言:javascript
复制
$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

票数 11
EN

Stack Overflow用户

发布于 2014-01-12 10:18:56

crypt的手册是不精确的(甚至具有误导性)。crypt使用的带有“MD5”、“SHA-256”或“SHA-512”绰号的算法实际上就是基于这些原语构建的算法。它们是使用散列执行key strengtheningpassword-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

票数 8
EN

Stack Overflow用户

发布于 2014-01-11 16:19:52

您的密码长度不同,这是因为crypt()输出是base64编码的,并且您对value1使用十六进制。

而不是十六进制,您应该尝试这样做

代码语言:javascript
复制
value1 = crypt_base64(hashlib.sha512(salt + password))

bash implementation一样,crypt_base64doHash()函数的最后一部分。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21090312

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档