一、hashlib模块

HASH

Hash,一般翻译做“散列”,也有直接音译为”哈希”的,就是把任意长度的输入(又叫做预映射,pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。

简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。

HASH主要用于信息安全领域中加密算法,他把一些不同长度的信息转化成杂乱的128位的编码里,叫做HASH值.

Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等。

什么是摘要算法呢?摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。

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

摘要算法之所以能指出数据是否被篡改过,就是因为摘要函数是一个单向函数,计算f(data)很容易,但通过digest反推data却非常困难。而且,对原始数据做一个bit的修改,都会导致计算出的摘要完全不同。

hash值的特点是:

  • 只要传入的内容一样,得到的hash值必然一样:要用明文传输密码文件完整性校验

  • 不能由hash值返解成内容:把密码做成hash值,不应该在网络传输明文密码

  • 只要使用的hash算法不变,无论校验的内容有多大,得到的hash值长度是固定的

MD5(消息摘要算法第五版)

什么是MD5算法

MD5讯息摘要演算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码杂凑函数,可以产生出一个128位的散列值(hash value),用于确保信息传输完整一致。MD5的前身有MD2、MD3和MD4。

MD5功能

输入任意长度的信息,经过处理,输出为128位的信息(数字指纹);不同的输入得到的不同的结果(唯一性);

MD5算法的特点

  1. 压缩性:任意长度的数据,算出的MD5值的长度都是固定的

  2. 容易计算:从原数据计算出MD5值很容易

  3. 抗修改性:对原数据进行任何改动,修改一个字节生成的MD5值区别也会很大

  4. 强抗碰撞:已知原数据和MD5,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。

MD5算法是否可逆?

MD5不可逆的原因是其是一种散列函数,使用的是hash算法,在计算过程中原文的部分信息是丢失了的。

MD5用途

  1. 防止被篡改:

  2. 防止直接看到明文:

  3. 防止抵赖(数字签名):

SHA-1(安全哈希算法)

安全哈希算法(Secure Hash Algorithm)主要适用于数字签名标准(Digital Signature Standard DSS)里面定义的数字签名算法(Digital Signature Algorithm DSA)。对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。当接收到消息的时候,这个消息摘要可以用来验证数据的完整性。

SHA是美国国家安全局设计的,由美国国家标准和技术研究院发布的一系列密码散列函数。

科学家们又推出了SHA224, SHA256, SHA384, SHA512,当然位数越长,破解难度越大,但同时生成加密的消息摘要所耗时间也更长。目前最流行的是加密算法是SHA-256 .

通常应用

  1. 密码加密(很常用的一种用法)

    将用户的密码或者账户名密码转为密文进行存储(密文是加了密的的文字,明文是加密之前的文字。),防止用户资料信息被泄露带来各种不安全的情况

  2. 文件校验

在网上下载大尺寸文件的时候常见到网站同时会提供这个文件的MD5的值,它的作用是用户下载后可以在下载文件基础上计算MD5的值,如果和网站提供的MD5是相同的说明文件在下载过程中没有损坏或者说文件没有被恶意网站修改。

3.工作量证明(Proof ofWork)

详见https://www.zhihu.com/question/22369364/answer/23600737

MD5算法例子

import hashlib

m = hashlib.md5() #实例化创建加密对象
m.update(b"nicholas") #传入待加密的字符串,注意要转换为bytes二进制形式,以下两种写法也是可以的
# m.update("nicholas".encode("utf-8"))
# m.update(bytes("nicholas",encoding="utf-8"))

v1 = m.hexdigest()
print(type(v1))
print(v1) #返回产生的十六进制的字符串类型数值
#输出结果532ab4d2bbcc461398d494905db10c95
"""注意这里是十六进制的数,共32个数,由于一位十六进制的数要用4位二进制的数来表示
这里是产生了32*4=128位二进制数,所以我们经常听到MD5是128位的校验,这里的128位是代表128位的二进制数
"""

v2 = m.digest()
print(v2) #返回二进制形式的数值,可以转换为十六进制形式,与hexdigest结果一致
print(type(v2))
import binascii #这里为了方便,直接在这里导入binascii ,将二进制转为十六进制
print(binascii.b2a_hex(v2)) #b'532ab4d2bbcc461398d494905db10c95'

  

输出结果

  <class 'str'>
532ab4d2bbcc461398d494905db10c95
b'S*\xb4\xd2\xbb\xccF\x13\x98\xd4\x94\x90]\xb1\x0c\x95'
<class 'bytes'>
b'532ab4d2bbcc461398d494905db10c95'

  

分析:可以看到digest()和hexdigest()产生的数值其实是一样的,只不过一个是作为二进制数据字符串值(bytes类型),一个是十六进制数据字符串值(字符串类型)。

注意:如果m.update(a)之后再次 m.update(b),那么就相当于m.update(a+b)

例子

  
  import hashlib

m1 = hashlib.md5() #实例化创建加密对象
m1.update(b"nicholas") #传入待加密的字符串
m1.update(b"123")
print(m1.hexdigest()) #12962a329e66f22a0dfbeec2f2498d87

m2 = hashlib.md5()
m2.update(b"nicholas123")
print(m2.hexdigest()) #12962a329e66f22a0dfbeec2f2498d87

  

输出结果

  12962a329e66f22a0dfbeec2f2498d87
12962a329e66f22a0dfbeec2f2498d87

  

分析:可以看到m1传入2次bytes之后产生的结果和m2结果一样的。这种特性表示如果处理同一个大量数据可以分块传入,与一次性传入处理结果是一样的。

SHA算法例子

例子

  
  import hashlib

m1 = hashlib.sha1() #实例化创建加密对象
m1.update(b"nicholas") #传入待加密的字符串
m1.update(b"123")
print(m1.hexdigest())

m2 = hashlib.sha1()
m2.update(b"nicholas123")
print(m2.hexdigest())

  

输出结果

  ef3f18a2b33e1f5366c25161a4869707503225f2
ef3f18a2b33e1f5366c25161a4869707503225f2

  

分析;可以看到,SHA算法的用法和MD5用法类似,也有分批次传入和一次性传入结果一致的特性。

加盐

上述各种算法比明文存储密码确实要安全不少。但在有些场景中,用户通常会将密码设置的尤为简单。这样如果数据库泄露,黑客可以通过简单的密码尝试来完成对加密字串的匹配。即:通过撞库可以反解。为了解决这种方法,我们通常需要对密码做“加盐”处理,即有必要对加密算法中添加自定义key再来做加密。

所谓加盐就是在m = hashlib.md5()这里设置参数,如果没有参数,所以md5遵守一个规则,生成同一个对应关系,如果加了参数,就是在原先加密的基础上再加密一层,这样的话参数只有自己知道,防止被撞库,因为别人永远拿不到这个参数。

例子


 import hashlib

m1 = hashlib.md5() #md5对象,md5不能反解,但是加密是固定的,就是关系是一一对应,所以有缺陷,可以被对撞出来
m1.update(b"nicholas") #传入待加密的字符串
print(m1.hexdigest())
# 输出结果 532ab4d2bbcc461398d494905db10c95
"""这个结果可以别人也可以直接对简单字符串的进行MD5取值生成一个数据库,拿数据库中的MD5值与这个MD5值进行比对,
一致则反向找到了原字符串,因此现在网站注册用户一般会提示密码加上字母、数字、特殊字符多种组合
"""

m2 = hashlib.md5(b"salt") #这里加盐设置的参数自己确定,如果没有参数,所以md5遵守一个规则,
# 生成同一个对应关系,如果加了参数, 就是在原先加密的基础上再加密一层,别人不知道这个对应关系,就加大了撞库破解的难度。
m2.update(b"nicholas")
print(m2.hexdigest())
# 输出结果317bf09f6da0f56f86b896fac6663443

  

tips:sha加盐用法与md5类似。

摘要算法应用场景

(1)大文件md5校验

  
  import hashlib
def file_md5(filename):
md5_value = hashlib.md5()
with open(filename, 'rb') as f:
while True:
data = f.read(2048) # 每次读取2048个字节数据
if not data:
break
md5_value.update(data)# 计算md5值
return md5_value.hexdigest()

file = input("请输入文件完整路径:")
v = file_md5(file)
print(v)

  

输出结果


 32a9d0ad680bcdcb712ec802be9971be

  

(2)网站用户注册登录

  
  import hashlib
import json
import os


def handle_md5(msg):
"对关键信息进行MD5处理"
m = hashlib.md5(bytes("salt",encoding="utf-8")) #加盐
m.update(bytes(msg,encoding="utf-8"))
res = m.hexdigest()
return res


def write_data(filename,data):
with open(filename,"a+",encoding="utf-8") as f:
json.dump(data,f)


def read_data(filename):
with open(filename,"r",encoding="utf-8") as f:
data = json.load(f)
return data

def login():
#用户登录模块
username = input("请输入账户名:").strip()
userpasswd = input("请输入密码:").strip()
username_file = "%s.json"%username
start_file_path = os.path.dirname(os.path.abspath(__file__))
username_file_path = os.path.join(start_file_path,username_file)
if os.path.exists(username_file_path): #判断用户信息文件是否存在
data = read_data(username_file_path)
account = data["name"]
passwd_md5 = data["passwd"]
userpasswd_md5 = handle_md5(userpasswd)
if username == account and userpasswd_md5 == passwd_md5:
print("恭喜%s,登录成功!"%username)
else:
print("账号或者密码错误,请重新登录。")
return "ok"
else:
print("账户不存在,请注册!")
return "no"


def register():
#用户注册模块
username = input("请输入要注册的用户名:").strip()
userpasswd = input("请输入要注册的密码:").strip()
user_filename = "%s.json"%username
user_passwd_md5 = handle_md5(userpasswd)
user_data ={"name":username,"passwd":user_passwd_md5}
write_data(user_filename,user_data)
print("注册成功")


def main():
print("欢迎登录XX")
while True:
res = login()
if res == "no":
register()
elif res == "ok":
print("进入了XX网站")
break


if __name__ == "__main__":
main()

  

Python之路(第十九篇)hashlib模块的更多相关文章

  1. Python之路(第二十九篇) 面向对象进阶:内置方法补充、异常处理

    一.__new__方法 __init__()是初始化方法,__new__()方法是构造方法,创建一个新的对象 实例化对象的时候,调用__init__()初始化之前,先调用了__new__()方法 __ ...

  2. Python之路(第十八篇)shutil 模块、zipfile模块、configparser模块

    一.shutil 模块 1.shutil.copyfileobj(fsrc, fdst[, length]) 将文件内容拷贝到另一个文件中,需要打开文件 import shutil shutil.co ...

  3. Python之路(第十六篇)xml模块、datetime模块

    一.xml模块 xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单, xml比较早,早期许多软件都是用xml,至今很多传统公司如金融行业的很多系统的接口还主要 ...

  4. Python之路(第十五篇)sys模块、json模块、pickle模块、shelve模块

    一.sys模块 1.sys.argv 命令行参数List,第一个元素是程序本身路径 2.sys.exit(n) 退出程序,正常退出时exit(0) 3.sys.version . sys.maxint ...

  5. Python之路(第十四篇)os模块

    一.os模块 1.os.getcwd() 获取当前工作目录(当前工作目录默认都是当前文件所在的文件夹) import os print(os.getcwd()) 2.os.chdir(path) 改变 ...

  6. Python学习【第十二篇】模块(2)

    序列化 1.什么是python序列化? 把变量从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling 序列化就是将python的数据类型转换成字符串 反序列化就是将字符串转换成 ...

  7. (十九)hashlib模块

    hashlib模块用于加密相关的操作,3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法 注意:md5和sha25 ...

  8. Python开发【第十九篇】:Python操作MySQL

    本篇对于Python操作MySQL主要使用两种方式: 原生模块 pymsql ORM框架 SQLAchemy pymsql pymsql是Python中操作MySQL的模块,其使用方法和MySQLdb ...

  9. Python之路(第二十八篇) 面向对象进阶:类的装饰器、元类

    一.类的装饰器 类作为一个对象,也可以被装饰. 例子 def wrap(obj): print("装饰器-----") obj.x = 1 obj.y = 3 obj.z = 5 ...

随机推荐

  1. mui-顶部选项卡-第一个选项卡内容不显示

    <div id="item1" class="mui-control-content mui-active"> <div id="s ...

  2. webstocket 聊天

    /** * 初始化socket **/ function initSocket(index_host){//端口号 if( !window.WebSocket ){ console.log(" ...

  3. 04_web基础(六)之请求转发与重定向

    1.交互方式 Web组件之间跳转: 从AServlet 跳转到 BServlet. 三种类型: 1:请求转发(forward) 2:URL重定向(redirect) 3:请求包含(include) 3 ...

  4. Real Time Rendering 1

    [Real Time Rendering 1] 1.RTR是一本导论.官网:http://www.realtimerendering.com. 2.At around 6 fps, a sense o ...

  5. Shader基础(固定管线着色器)

    在Shader的编码中,要养成不加空格的习惯,否则会有时候出现一些错误 固定管线着色器: 优点:实现简单 缺点:处理的效果比较差 //设置Shader的路径 Shader "MyFixedS ...

  6. centos7.4上安装python3环境的坑

    前言:为了将爬虫项目布置到服务器上,才有了今天这一下午的坑,必须记录 不要动现有的python2环境!不要动现有的python2环境!不要动现有的python2环境! 解压 tar -xvf Pyth ...

  7. 使用Fiddler查看APP的请求接口、接口参数和返回值的方法

    1.下载Fiddler,然后安装成功后. 2.开启代理的设置 3.查看电脑的ip, 4.建立一个wifi局域网,什么360wifi,猎豹wifi,腾讯wifi都可以,用安装手机接入到这个局域网的wif ...

  8. Centos 7 RabbitMQ + Haproxy 集群高可用部署

    一.   功能和原理介绍 RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端,如:Python.Ruby..NET.Java.JMS.C.PHP.ActionSc ...

  9. TOJ 5225: 玩转二叉树

    传送门:http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=5225 时间限制(普通/Java): ...

  10. HDU 4940 Destroy Transportation system(无源汇上下界网络流)

    Problem Description Tom is a commander, his task is destroying his enemy’s transportation system. Le ...