把密码变成散列真能保证其唯一性吗?Python中hashlib模块的探究

上一篇我们探讨了Python中的可哈希对象(参见是哈希不是嘻哈,你真的了解散列吗?理解Python中可哈希对象概念),我们知道了,这种可哈希对象从产生到对象销毁能保证其唯一性,它的值一般是不可变化的。并且,通过这种可哈希对象数值不能逆推出对象本身内容。那么,问题来了,这样的对象有什么用呢?本篇我们从Python内部和外部两种应用来探讨下这种可哈希对象的价值。

有哪些应用价值呢?

有哪些应用价值呢?

可哈希对象在Python内的应用

我们知道,set集合的特点是它的内部实现了一种排重操作,当数据交给集合set时,如果数据重复,那么这种重复数据是不会添加到set集合内的。问题来了,set怎么判断数据是否重复呢?

集合的内部实现机制

集合的内部实现机制

聪明的小伙伴一定猜到了,就是通过内部算法实现,判断数据的hash值是否相等。如果相等(它的内部算法可以保证这种数据唯一性,内部有哪些算法呢?后面会讲到),那么就是真的相等了(废话)。对于字典键的判断,应该也是这个原理。内部应该会有很多这种利用hash判断值唯一性的方法,今天就不赘述了,改天专题研究一下。

那么,Python中有没有类似的模块能实现这种hash操作呢?

hashlib模块

Python中hashlib模块内置了各种hash算法,文档中hashlib是这样解释的:

A common interface to many hash functions(许多散列函数的公共接口)

我们来看一下Python提供了哪些hash算法接口

print([item for item in dir(hashlib) if not item.startswith('_')])

>>>['algorithms_available', 'algorithms_guaranteed', 'blake2b', 'blake2s', 'md5', 'new', 'pbkdf2_hmac', 'scrypt', 'sha1', 'sha224', 'sha256', 'sha384', 'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512', 'sha512', 'shake_128', 'shake_256']

提供的接口有很多,我们归类解释:

先看两个返回hash算法的接口

algorithms_available(可用算法):当前运行的python解释器支持的hash算法的名称集合。

algorithms_guaranteed(算法保证):所有平台的hashlib模块都支持的hash算法的名称集合。

比如,hashlib.algorithms_available看下当前Python解释器支持的算法名称,输出如下:

>>>

{'blake2b', 'blake2b512', 'blake2s', 'blake2s256', 'md4', 'md5', 'md5-sha1', 'mdc2', 'ripemd160', 'sha1', 'sha224', 'sha256', 'sha3-224', 'sha3-256', 'sha3-384','sha3-512', 'sha384', 'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512', 'sha512', 'sha512-224', 'sha512-256', 'shake128', 'shake256', 'shake_128', 'shake_256', 'sm3', 'whirlpool'}

可以实现这么多算法,我们来看一下具体如何使用。

如何使用呢?

如何使用呢?

1.使用new(name, [data])创建一个hashable对象(指定算法)

h = hashlib.new("sha256", b"Hello World")

# 返回对象摘要

h.digest()

# 结果如下

>>>b'\xa5\x91\xa6\xd4\x0b\xf4 @J\x01\x173\xcf\xb7\xb1\x90\xd6,e\xbf\x0b\xcd\xa3+W\xb2w\xd9\xad\x9f\x14n'

h.name # 返回加密算法名称

>>>'sha256'

h.digest_size # hash对象的字节长度

>>>32

h.block_size # hash对象的内部块大小

>>>64

2.使用update(data)传递类字节参数(通常是bytes)来更新hash对象。

重复调用update()等同于单次的拼接调用。

h.update(b'Python')

h.digest()

>>>b'\xfc\n\xe71\xc0\xaa1X\x98\xa1\xc9\xad\xe2\xe2V\x82\xe1tD[\xff\x13\\\x1fs\xebg\xa9l\xb7\xdbe'

# 把它变成十六进制表示

h.hexdigest()

>>>'fc0ae731c0aa315898a1c9ade2e25682e174445bff135c1f73eb67a96cb7db65'

内容改变后,两次返回对象的哈希值是不一样的。

3.使用提供的接口指定具体调用方式

data = b'Hello World'

h = hashlib.md5()

h.update(data)

上面代码等同于

h = hashlib.new('md5', data)

创建对象时,直接使用h = hashlib.XXX()来创建一个使用XXX加密算法的散列。

hash算法生成的散列值唯一就能保证密码的唯一性吗

我们知道,hash算法生成的散列值应该是唯一的(为什么用应该呢?因为部分算法之前被人破解成功过),但是随着这种加密算法的改进,比如SHA256算法,当生成的散列值越长,这种散列值破解难度会越大,被破解的几率就微乎其微了。

在很多网站后台使用的密码都是经过加密的(如md5、sha256等算法),当恶意入侵人员通过非正常途径(暴库等方法)得到这种加密的字符串后,也是可以破解的。一般途径是这样的:

比如:一串有规律的字符串a经过md5加密后生成的散列值是ABC(长度固定)

当知道加密方式后,如果我们拿ABC去倒推出字符串a的可能性也是存在的。

比如,我拿“123abc”这样字符串作为的密码,那么,经过md5加密后它是这样的,'a906449d5769fa7361d7ecc6aa3f6d28'。

如果我有一份类似:{'a906449d5769fa7361d7ecc6aa3f6d28':“abc123”, ...}这样的字典,我就可以将密码"abc123"破解出来了。

而这样的字典是可以使用我们的Python程序生成的,然后暴力使用Python进行比对,这样的密码很容易被破解了。

怎么样?现在知道使用数字、大小写字母、符号混合使用的密码的必要行了吗?密码越有规律,就越容易被破解。好了,我们回答标题的内容,密码变成散列可以保证密码的唯一性。但是,前提是我们的密码必须复杂,这样才能保证不被破解。

今天的内容就到这里了,还有哪些加密算法呢?欢迎大家留言讨论,感兴趣的小伙伴关注我,后续推出更精彩的内容。

转载请注明出处,百家号:Python高手养成

发表评论
留言与评论(共有 0 条评论)
   
验证码:

相关文章

推荐文章

'); })();