Day 29 29.2 MD5摘要算法
哈希算法 - - MD5摘要算法
【一】Hash算法
-
哈希算法也称摘要算法、散列算法
- 哈希函数的输入为一段可变长度x,输出一固定长度串,该串被称为x的哈希值。
-
Hash函数满足以下几个基本需求:
- (1)输入值x为任意长度
- (2)输出值长度固定
- (3)单向函数,算法不可逆
- (4)唯一性,很难找到两个不同的输入会得到相同的Hash输出值
-
MD5是一个非常常见的摘要(hash)逻辑.
- 其特点就是小巧. 速度快. 极难被破解.
- 所以, md5依然是国内非常多的互联网公司选择的密码摘要算法.
【二】概要
- MD5信息摘要算法,一种被广泛使用的密码散列函数
- 可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。
- MD5由美国密码学家罗纳德·李维斯特(Ronald Linn Rivest)设计,于1992年公开,用以取代MD4算法。
- 这套算法的程序在 RFC 1321 标准中被加以规范。
- 1996年后该算法被证实存在弱点,可以被加以破解,对于需要高度安全性的数据,专家一般建议改用其他算法,如SHA-2。
- 2004年,证实MD5算法无法防止碰撞(collision),因此不适用于安全性认证,如SSL公开密钥认证或是数字签名等用途。
【三】算法原理
a. 填充
-
消息长度应为一个比512bit的倍数少64bit的数,即:
- 512*n+448
- 512*n-64
-
填充方法:在消息后添加一个1,再后接多个0
-
后64bit为填充前消息长度
- 如下图所示:
- 这样可以对明文分组,每组长度为512bit,即16个长度为32bit的字。
b. 迭代
-
标准幻数
- MD5输出为128bit,即4个32bit的字,可用A、B、C、D表示。
- A、B、C、D为标准幻数,其初始值分别为:
- A=01234567
- B=89ABCDEF
- C=FEDCBA98
- D=76543210
-
对于每512bit输入
-
MD5运算64步
-
得到128bit输出
-
该输出参与下一轮输入
-
如图所示:
-
-
每轮中512bit分为16份,
-
每份32bit,即4B
-
分别参与4轮运算中16步迭代运算
-
因此4轮共64步。
-
-
逻辑函数F、G、H、I分别如下:
- F( X ,Y ,Z ) = ( X & Y ) | ( (~X) & Z )
- G( X ,Y ,Z ) = ( X & Z ) | ( Y & (~Z) )
- H( X ,Y ,Z ) =X ^ Y ^ Z
- I( X ,Y ,Z ) =Y ^ ( X | (~Z) )
【四】应用场景
(1)数据完整性校验
- 常用Web服务器本身缺乏页面完整性验证机制,无法防止站点文件被篡改。
- 为确保文件的完整性,防止用户访问页面被篡改,可采用MD5算法校验文件完整性的Web防篡改机制,计算目标文件的数字指纹,运用快照技术恢复被篡改文件,以解决多数防篡改系统对动态站点保护失效及小文件恢复难的问题 。
(2)密码加密
- 我们知道MD5加密是不可逆的,用MD5算法加密后的字符串,是无法反向推算出原始密码的,可以有效防止密码被盗,但是固定长度的纯文本加密容易被撞库
- 既然如此,那么我们就要对密码加盐。服务器在保存密码时,会生成一段随机字符串并添加到密码后再做MD5散列,确保密码的安全性。
(4)数字签名
- MD5 算法还可以作为一种电子签名的方法来使用,使用 MD5算法就可以为任何文件(不管其大小、格式、数量)产生一个独一无二的“数字指纹”,借助这个“数字指纹”,通过检查文件前后 MD5 值是否发生了改变,就可以知道源文件是否被改动。
- 我们在下载软件的时候经常会发现,软件的下载页面上除了会提供软件的下载地址以外,还会给出一串长长的字符串。
- 这串字符串其实就是该软件的MD5 值,它的作用就在于下载该软件后,对下载得到的文件用专门的软件(如 Windows MD5 check 等)做一次 MD5 校验,以确保我们获得的文件与该站点提供的文件为同一文件。
- 利用 MD5 算法来进行文件校验的方案被大量应用到软件下载站、论坛数据库、系统文件安全等方面。
【五】注意
- Hash算法不是加密算法。
- hash算法也被称为摘要算法、散列算法,其过程不可逆,目的主要是确保数据的完整性。
- 加密算法的目的主要是确保数据的保密性。
【六】总结
(1)特点
这玩意不可逆. 所以. 摘要算法就不是一个加密逻辑.
相同的内容计算出来的摘要应该是一样的
不同的内容(哪怕是一丢丢丢丢丢不一样) 计算出来的结果差别非常大
(2)用途
-
在数学上.
- 摘要其实计算逻辑就是hash.
-
hash(数据) => 数字
- 密码
- 一致性检测
-
md5的python实现:
# md5加密模块
from hashlib import md5
# 如果需要十六进制的结果与二进制的结果之间的转换,需要的模块
import binascii
# 【1】准备数据
data = '你好' #这里是字符串类型
# 字符串转二进制数据方式一
encode_data = s.encode()
# 字符串转二进制数据方式二
encode_data = b'你好'
# 【2】数据加密
# 构建md5对象
md5_obj = md5()
# 将数据更新到md5算法中进行数据加密 (参数为二进制数据的明文数据)
#(方法一):直接在加密算法中进行转码
md5_obj.update("你好".encode("utf-8"))
md5_obj.update(data.encode("utf-8"))
#(方法二):先将明文数据进行转码,再传入到加密算法中
md5_obj.update(encode_data)
# 【3】数据提取
# 拿到加密字符串 # 十六进制的结果
result_16 = obj.hexdigest()
# 拿到加密字符串 # 二进制的结果
result_2 = obj.digest()
# 拿到加密字符串 # 十六进制的结果与二进制的结果之间的转换 (参数为result_16 或 result_2)
result_change = binascii.unhexlify(result_16)
- 我们把密文丢到网页里. 发现有些网站可以直接解密.
- 但其实不然. 这里并不是直接解密MD5.
- 而是"撞库".
- 就是它网站里存储了大量的MD5的值.
- 就像这样:
- 而需要进行查询的时候. 只需要一条select语句就可以查询到了.
- 这就是传说中的撞库.
(3)如何避免撞库:
- md5在进行计算的时候可以加盐.
- 加盐之后. 就很难撞库了.
from hashlib import md5
salt = "我是盐.把我加进去就没人能破解了"
obj = md5(salt.encode("utf-8")) # 加盐
obj.update("alex".encode("utf-8"))
bs = obj.hexdigest()
print(bs)
(4)扩展: sha256/sha512
from hashlib import sha1, sha256
sha = sha256(b'salt')
sha.update(b'alex')
print(sha.hexdigest())
- 不论是sha1, sha256, md5都属于摘要算法.
- 都是在计算hash值.
- 只是散列的程度不同而已. 这种算法有一个特性.
- 他们是散列. 不是加密.
- 而且, 由于hash算法是不可逆的, 所以不存在解密的逻辑.
本文来自博客园,作者:Chimengmeng,转载请注明原文链接:https://www.cnblogs.com/dream-ze/p/17362507.html