Python中摘要算法在存储用户口令中的应用(以MD5为例)

Python3中的hashlib提供了常见的摘要算法,如MD5、SHA1等等。
【概述】:什么是摘要算法呢?摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。
【实质】:摘要算法就是通过摘要函数f(x)对任意长度的数据data计算出固定长度的摘要digest,目的是为了发现原始数据是否被人篡改过。

一、计算一段字符串的MD5码

import hashlib
md5 = hashlib.md5()
md5.update('I Love You'.encode('utf-8'))
md5_str = md5.hexdigest()  # 生成16进制摘要
print(md5_str)

执行结果:

cd2824bba5d2803793c0553c8f7c0bd1

如果输入的字符串过长,也可以这样,但结果和上面一样:

md5.update('I Love'.encode('utf-8'))
md5.update(' You'.encode('utf-8'))

【简洁版本】:

import hashlib
md5_str = hashlib.md5('I Love You'.encode('utf-8')).hexdigest()
print(md5_str)

二、摘要算法的应用

在数据库中我们经常会遇到要存储用户的用户名(username)和密码(password)的时候,如果我们直接将用户的口令密码的明文直接存储在数据库中,如下图:

IDUsernamePassword
1sparks_flyspark123456
2Maryqq6411589

则网站的管理人员或数据库运维人员会轻而易举的获取每个用户的用户名和密码,这样用户的密码无疑被暴露出来。
如何解决的这样的问题呢?
此时可以用到刚才提到的MD5码,如下图:

IDUsernamePassword
1sparks_fly78ffdf361a2e7746c848d5f2beed8e3f
2Marya63b50c14bca6c461dac676f1e88d7cd

如果变成这样的存储方式,即使是管理员看到每个用户的数据库表也无法轻易知道用户的明文密码。这样,提高了用户口令存储的安全性

①使用hashlib

以下我们可以先从编写一个简单的注册用户信息的代码开始:

import hashlib
db = {}
def register(username,password):
    md5 = hashlib.md5()
    md5.update(password.encode('utf-8'))
    db[username] = md5.hexdigest()
    
register('sparks_fly','spark123456') 
register('Mary','qq6411589')
print('注册后数据库中写入的数据应该如下:')
for key in db:
    print('用户名:%-15s 密码:%s' % (key,db[key]))

执行结果:

注册后数据库中写入的数据应该如下:
用户名:sparks_fly      密码:78ffdf361a2e7746c848d5f2beed8e3f
用户名:Mary            密码:a63b50c14bca6c461dac676f1e88d7cd

然后我们在扩展到简单的登录功能:

import hashlib
db = {}
# 注册功能
def register(username,password):
    md5 = hashlib.md5()
    md5.update(password.encode('utf-8'))
    db[username] = md5.hexdigest()
# 登录功能
def login(username,password):
    md5 = hashlib.md5()
    md5.update(password.encode('utf-8'))
    if md5.hexdigest() == db[username]:
        print('%s登录成功' % username)
        return
    print('登录失败')
    
register('sparks_fly','spark123456') 
register('Mary','qq6411589')
login('Mary','qq6411589')

执行结果:

Mary登录成功

但是MD5码不是绝对安全的,比如有两个用户的密码是一样的,那么这两个密码生成的MD5码也一定是一样的。还有一种情况就是对于简单的密码,不怀好意的人可以先自己生成一个简单常用的密码生成的MD5库,然后对用户数据库中的MD5码进行match。因此可以想到在原有用户密码的基础上增加一些"东西"来增强安全性(这种方式被称为"加盐"),比如可以把用户的注册密码和用户名拼接成一个字符串再生成MD5码存储在数据库中。
代码如下:

import hashlib
db = {}
# 注册功能
def register(username,password):
    md5 = hashlib.md5()
    md5.update((password+username).encode('utf-8')) #拼接密码和用户名
    db[username] = md5.hexdigest()
# 登录功能
def login(username, password):
    md5 = hashlib.md5()
    md5.update((password+username).encode('utf-8'))
    if md5.hexdigest() == db[username]:
        print('%s登录成功' % username)
        return
    print('%s登录失败' % username)
    
register('sparks_fly','spark123456')  
register('Mary','qq6411589') 
print('注册后数据库中写入的数据应该如下:')
for key in db:
    print('用户名:%-15s 密码:%s' % (key,db[key]))
login('Mary','qq6411589')

执行结果:

注册后数据库中写入的数据应该如下:
用户名:sparks_fly      密码:5edc0043dfe3b0e8322e4b75e1e72130
用户名:Mary            密码:3c00f67fd930d2e04ddd600680662c19
Mary登录成功
②使用hmac

在上面的案例中,我们手动把用户名和密码进行拼凑,然后再生成MD5码,但是在python中提供了一种内建模块hmac可以帮我们做这件事,用此模块也会更标准。
代码如下:

import hmac
h = hmac.new(b'Mary', b'qq6411589', digestmod='MD5')
h.hexdigest()

# 执行结果:
'0c09ebc704b5887e51b1063e6aeca451'

语法:

hmac.new(key, message, digestmod='MD5')

这实际上就是Hmac算法:Keyed-Hashing for Message Authentication。它通过一个标准算法,在计算哈希的过程中,把key混入计算过程中。
此处传入的两个参数keymessage均是byte类型,所以除了可以在字符串前加b以外还可以对于字符串进行如下转换。

import hmac
user_b = bytes('Mary',encoding='utf-8')
password_b = bytes('qq6411589',encoding='utf-8')
h = hmac.new(user_b, password_b, digestmod='MD5')
h.hexdigest()

参考文献:
[1]廖雪峰-摘要算法简介.
[2]Hmac算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SL_World

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值