hashlib vs Python中的crypt.crypt().为何结果不同?

 jinglongyy70 发布于 2023-02-03 11:57

我正在学习Python.我无法弄清楚为什么hashlib.sha512(salt + password).hexdigest()不给出预期的结果.

我正在寻找相当于Ulrich Drepper的sha512crypt.c算法的纯Python实现.(我花了一些时间来弄清楚我在寻找什么.)

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

当我调用Python的系统crypt包装器(即crypt.crypt())时,下面的代码验证行为是否符合预期.我想使用hashlib.sha512或其他一些Python lib来产生与crypt.crypt()相同的结果.怎么样?

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

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

根据crypt手册页,SHA-512是86个字符.crypt()上面代码中的调用符合这一点.但是,hashlib.sha512的输出超过了86个字符,所以在这两个实现之间有所作为......

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

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

MountainX.. 11

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

$ sudo pip install 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有一个sha512_crypt的纯Python实现,它将在系统没有当前Linux系统具有的crypt实现时使用(例如,http://www.akkadia.org/drepper/SHA-crypt .txt).

请在此处查看PassLib文档:

passlib - 用于python的密码哈希库 - Google Project Hosting
https://code.google.com/p/passlib/

Passlib 1.6.2文档 - Passlib v1.6.2文档
http://pythonhosted.org/passlib/

passlib-users - 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-512 Crypt - Passlib v1.6.2文档
http://pythonhosted.org/passlib/lib/passlib.hash.sha512_crypt.html#passlib.hash.sha512_crypt

3 个回答
  • 您的密码长度不同,这是因为crypt() 输出是base64编码的,您使用hexdigest value1.

    而不是hexdigest,你应该尝试做类似的事情

    value1 = crypt_base64(hashlib.sha512(salt + password))
    

    crypt_base64喜欢的bash执行,最后的部分 doHash()功能.

    2023-02-03 12:01 回答
  • 手册crypt是不精确的(甚至是误导性的).所使用的算法crypt与"MD5","SHA-256"或"SHA-512"的绰号其实都是算法基于这些基础.它们是基于密码的密钥派生函数,使用哈希来执行密钥强化.

    一个好的密码哈希算法有两个属性:它必须将密码与一个独特的盐组合在一起(以防止一次破解许多密码的尝试),并且它必须很慢(因为攻击者需要比攻击者更多地伤害攻击者,因为攻击者需要尝试大量的组合).像MD5和SHA系列这样的日常哈希算法设计得尽可能快,同时仍具有所需的安全属性.构建密码哈希算法的一种方法是采用加密哈希算法并多次迭代.虽然这并不理想(因为有更好的技术使得构建专用硬件以进行密码破解变得更加困难),但它已经足够了.

    在维基百科的文章crypt(3)提供了一个简要的解释和有指向主要来源.Linux和FreeBSD的手册页很差,但是Solaris有足够的信息不会产生误导(按照链接crypt.conf(4)然后crypt_sha512和其他链接).您还可以在纯文本中阅读ubuntu 13.04中的用户密码吗?和是否有重复在Solaris 11哈希程序?我可以添加一些吗?

    计算cryptPython 输出的正确方法是调用crypt.crypt.

    2023-02-03 12:01 回答
  • 这是解决方案.在另一个问题上还有更多细节:sha512_crypt.c的Python实现,其中显示了passlib的后端包含sha512_crypt的纯Python实现(如果crypt.crypt()不可用,则调用Python实现OS).

    $ sudo pip install 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有一个sha512_crypt的纯Python实现,它将在系统没有当前Linux系统具有的crypt实现时使用(例如,http://www.akkadia.org/drepper/SHA-crypt .txt).

    请在此处查看PassLib文档:

    passlib - 用于python的密码哈希库 - Google Project Hosting
    https://code.google.com/p/passlib/

    Passlib 1.6.2文档 - Passlib v1.6.2文档
    http://pythonhosted.org/passlib/

    passlib-users - 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-512 Crypt - Passlib v1.6.2文档
    http://pythonhosted.org/passlib/lib/passlib.hash.sha512_crypt.html#passlib.hash.sha512_crypt

    2023-02-03 12:01 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有