【一】什么是摘要算法
Python的hashlib提供了常见的摘要算法,如MD5、SHA1等等
摘要算法又称哈希算法、散列算法
它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)
摘要算法就是通过摘要函数f()对任意长度的数据data计算出固定长度的摘要digest
摘要算法之所以能指出数据是否被篡改过,就是因为摘要函数是一个单向函数
计算f(data)很容易,但通过digest反推data却非常困难
而且,对原始数据做一个bit的修改,都会导致计算出的摘要完全不同
【二】摘要算法(md5)
【1】加密数据
(1)一次性加密(同一段数据)
import hashlib
md5 = hashlib.md5()
md5.update(b'how to use md5 in python hashlib?' )
print (md5.hexdigest())
(2)分次加密(同一段数据)
import hashlib
md5 = hashlib.md5()
md5.update(b'how to use md5 in ' )
md5.update(b'python hashlib?' )
print (md5.hexdigest())
【2】获取加密数据
from hashlib import md5
import binascii
data = '你好'
encode_data = data.encode()
md5_obj = md5()
md5_obj.update(data.encode("utf-8" ))
result_16 = md5_obj.hexdigest()
print (result_16)
result_2 = md5_obj.digest()
print (result_2)
result_change = binascii.unhexlify(result_16)
print (result_change)
【三】摘要算法升级之加盐
任何允许用户登录的网站都会存储用户登录的用户名和口令。
如何存储用户名和口令呢?
name | password
michael | 123456
bob | abc999
alice | alice2008
如果以明文保存用户口令,如果数据库泄露,所有用户的口令就落入黑客的手里。
此外,网站运维人员是可以访问数据库的,也就是能获取到所有用户的口令。
正确的保存口令的方式是不存储用户的明文口令,而是存储用户口令的摘要,比如MD5:
username | password
michael | e10adc3949ba59abbe56e057f20f883e
bob | 878ef96e86145580c38c87f0410ad153
alice | 99b1c2188db85afee403b1536010c2c9
考虑这么个情况,很多用户喜欢用123456,888888,password这些简单的口令
于是,黑客可以事先计算出这些常用口令的MD5值,得到一个反推表:
'e10adc3949ba59abbe56e057f20f883e' : '123456'
'21218cca77804d2ba1922c33e0151105' : '888888'
'5f4dcc3b5aa765d61d8327deb882cf99' : 'password'
这样,无需破解,只需要对比数据库的MD5,黑客就获得了使用常用口令的用户账号。
对于用户来讲,当然不要使用过于简单的口令。
由于常用口令的MD5值很容易被计算出来
所以,要确保存储的用户口令不是那些已经被计算出来的常用口令的MD5
这一方法通过对原始口令加一个复杂字符串来实现,俗称“加盐”:
hashlib.md5("salt" .encode("utf8" ))
经过Salt处理的MD5口令,只要Salt不被黑客知道,即使用户输入简单口令,也很难通过MD5反推明文口令。
但是如果有两个用户都使用了相同的简单口令比如123456,在数据库中,将存储两条相同的MD5值,这说明这两个用户的口令是一样的。
有没有办法让使用相同口令的用户存储不同的MD5呢?
如果假定用户无法修改登录名,就可以通过把登录名作为Salt的一部分来计算MD5,从而实现相同口令的用户也存储不同的MD5。
摘要算法在很多地方都有广泛的应用。
要注意摘要算法不是加密算法,不能用于加密(因为无法通过摘要反推明文),只能用于防篡改,但是它的单向计算特性决定了可以在不存储明文口令的情况下验证用户口令。
【四】摘要算法模版
import hashlib
def get_md5_digest (salt,data ):
data = salt + data
b_data = data.encode('utf-8' )
encrypted_data = hashlib.md5(b_data)
return encrypted_data.hexdigest()
【五】SHA1
import hashlib
sha1 = hashlib.sha1()
sha1.update(b'how to use sha1 in ' )
sha1.update(b'python hashlib?' )
print (sha1.hexdigest())
【五】MD5加密在验证登录中的应用
import os
import hashlib
from verify_code import get_verify_code
file_path = 'Infos' + '\\' + 'user_pwd.txt'
if not os.path.exists(file_path):
with open (file_path, 'a' ) as f:
f.write('' )
def encrypt_decrypt (data ):
data = data.encode('utf-8' )
md5 = hashlib.md5()
md5.update(data)
encrypt_result = md5.hexdigest()
return encrypt_result
def write_read_data (data=None , cmd=0 ):
if cmd == 0 :
with open (file_path, 'a+' ) as f:
f.write(data)
else :
user_list = []
user_info_data = []
with open (file_path, 'r' ) as f:
for line in f:
user_data = {}
line = line.strip().split('|' )
username, password, salt_code = line[0 ], line[1 ], line[2 ]
user_data['username' ] = username
user_data['password' ] = password
user_data['salt_code' ] = salt_code
user_list.append(username)
user_info_data.append(user_data)
return [user_list, user_info_data]
def register (username, password ):
salt_code = get_verify_code(6 )
password_str = password + salt_code
password_encrypted = encrypt_decrypt(password_str)
user_pwd_data = f'{username} |{password_encrypted} |{salt_code} \n'
write_read_data(user_pwd_data, cmd=0 )
print (f'{username} 注册成功,注册结束!' )
def login ():
user_list, user_data = write_read_data(data=None , cmd=1 )
username_input = input ('Username:>>>' )
password_input = input ('Password:>>>' )
if username_input in user_list:
for info in user_data:
username = info['username' ]
password = info['password' ]
salt_code = info['salt_code' ]
password_str = password_input + salt_code
password_encrypted = encrypt_decrypt(password_str)
if username == username_input and password == password_encrypted:
print ('登陆成功!' )
return True
else :
print ('用户名或密码错误,登陆失败!' )
main()
else :
print ('用户名不存在,请注册' )
main()
def main ():
username = input ('Username:>>>' )
user_list = write_read_data(cmd=1 )[0 ]
if username not in user_list:
print ('当前用户未注册注册,注册操作开始!' )
password = input ('Password:>>>' )
register(username, password)
main()
else :
password = input ('Password:>>>' )
print ('进行登陆操作' )
res = login()
if res:
print ('欢迎使用' )
pass
else :
login()
if __name__ == '__main__' :
main()
import random
'''生成六位随机 (数字 + 大小写) 验证码'''
def get_verify_code (n ):
code = ''
for i in range (n):
random_int = str (random.randint(0 , 9 ))
random_upper = chr (random.randint(65 , 90 ))
random_lower = chr (random.randint(97 , 122 ))
temp = random.choice([random_int, random_upper, random_lower])
code += temp
return code
if __name__ == "__main__" :
res = get_verify_code(6 )
print (res)