您的位置:首页 > 编程语言 > Python开发

Python 10.5 hashlib

2016-02-02 00:14 344 查看
hashlib
摘要算法简介:
Python的摘要算法提供了常见的摘要算法,如MD5,SHA1等。
什么是摘要算法呢?又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个固定长度的字符串(通常用16进制的字符串表示)。

摘要算法就是通过摘要函数f()对任意长度的数据data计算出固定长度的摘要digest,目的是为了发现原始数据是否被篡改。

摘要函数之所以能够指出数据是否被篡改,因为摘要函数是一个单向函数,计算f(data)很简单,但是通过digest反data却十分困难。而且,对原始数据做一个bit的修改,也会造成对digest的改变。

我们以常见的摘要算法MD5为例,计算一个字符串的MD5值:

import hashlib
md5 =hashlib.md5()

md5.update('how to use md5 in python hashlib?'.encode('utf-8'))

print(md5.hexdigest())

d26a53750bc40b38b65a520292f69306
如果数据量很大,可以分多次调用update,最后计算的结果是一样的:

import hashlib

md5 = hashlib.md5()
md5.update('how to use md5 in '.encode('utf-8'))
md5.update('python hashlib?'.encode('utf-8'))
print(md5.hexdigest())
试试改动的一个字母,看看结果.

MD5是最常见的摘要算法,速度很快,生成的是128bit字节,通常用一个32位的16进制字符串表示。
另外一种常见的摘要算法是SHA1,调用SHA1和MD5完全类似:
import hashlib

sha1 =hashlib.sha1()
sha1.update('how to use sha1 in python hashlib?'.encode('utf-8'))
print(sha1.hexdigest())
SHA1通常是一个160bit字节,通常使用40个16进制的字符串表示。
比SHA1更安全的算法是SHA256和SHA512,不过更安全的算法计算时间更长,摘要更长。

有没有两个不同的数据通过某个摘要算法得到相同的摘要呢?完全有可能,因为任何摘要算法都是把无限多的数据集合映射到一个有限集合中。这种情况称之为碰撞。这种情况出现的可能性很小。

摘要算法应用
摘要算法能用到哪呢?举个常用的例子:
任何允许用户登录的网站都会存储用户登录的用户名和密码。并且存储到数据库的表中:

name    | password
--------+----------
michael | 123456
bob     | abc999
alice   | alice2008
如果以明文保存用户名和密码,网站数据库一旦被黑,用户的数据将会很容易泄露.
正确的方式是,不存储用户的明文密码,而是存储用户口令的摘要,比如MD5摘要:

username | password
---------+---------------------------------
michael  | e10adc3949ba59abbe56e057f20f883e
bob      | 878ef96e86145580c38c87f0410ad153
alice    | 99b1c2188db85afee403b1536010c2c9
当用户登陆的时候,首先计算用户输入明文密码的MD5,然后与数据库存储的MD5值对比,如果相同则表明用户密码匹配,允许登陆。如果不一致,口令肯定是错误的。
存储MD5的好处是即使是运维人员能访问数据库,也无法获知用户的明文密码。

设计一个验证用户登录的函数,根据用户输入的口令是否正确返回True或者False。

db = {    'michael': 'e10adc3949ba59abbe56e057f20f883e',    'bob': '878ef96e86145580c38c87f0410ad153',    'alice': '99b1c2188db85afee403b1536010c2c9'}
def login(user, password):
pass
采用MD5存储口令是否就一定安全呢?假设你是一个***,拿到了存储MD5口令的数据库,如果通过MD5反推用户的明文口令呢?

考虑到这么个情况,很多用户喜欢使用123456,888888、abceddf等简单口令,于是,***可以事先计算出这些简单口令的MD5值,得到一个反推表:

'e10adc3949ba59abbe56e057f20f883e': '123456'
'21218cca77804d2ba1922c33e0151105': '888888'
'5f4dcc3b5aa765d61d8327deb882cf99': 'password'
这样,无需破解,只需要对比数据库的MD5值就可以获得使用常用口令的用户账号。
对于用户来讲,当然不要使用过于简单的口令。但是我们能否在程序设计商对简单口粮加强保护呢?

由于常用的MD5值很容易被计算出来,为确保存储的用户口令不是那些已经被计算出来的常用口令,这一方法通过对原始口令加一个复杂字符串来实现,俗称“加盐”:
def calc_md5(password):
return get_md5(password + 'the -salt')
经过salt处理的MD5口令,只要salt不被***知道,即使用户输入简单口令,也很难通过MD5反推明文口令。
但是如果两个用户都使用相同的明文口令,在数据库中将存储两条相同的MD5值,这说明两个用户的口令相同。有没有办法让两个使用相同口令的用户存储不同的MD5值呢?

如果假定用户名不能改变,则可以通过把用户名当作salt的一部分来计算MD5,从而实现相同口令的用户存储不同的MD5值。

练习:
根据用户输入的用户名和口令模拟用户注册,计算更安全的MD5:
db ={}

def register(username,password):
db[username] =get_md5(password + username +'the -salt')
然后根据修改后的MD5算法实现用户登录验证:
def login(username,password):
pass

小结:
摘要算法很多地方都会用到。要注意摘要算法不是加密算法,不能用于加密(因为无法通过摘要反推明文),只能用于防篡改,但是它的单项计算特性决定了可以在不存储明文口令的情况下验证用户口令。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  MD5 Python SHA1