Python学习之路——MD5加密

一、MD5简介

MD5(MD5 Message-Digest Algorithm),中文名称第五代信息摘要算法,它是一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。
MD5的特性:

  • 压缩性: 任意长度的数据,算出的MD5值长度都是固定的。
  • 容易计算: 从原数据计算出MD5值很容易。
  • 抗修改性: 对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。
  • 弱抗碰撞: 已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。
  • 强抗碰撞: 想找到两个不同的数据,使它们具有相同的MD5值,是非常困难的。

MD5的应用:

  • 用户密码
  • 请求参数校验
  • 文件校验

二、实现

MD5 算法的过程分为四步:处理原文,设置初始值,循环加工,拼接结果。
第一步:
首先计算出原文长度(bit)对 512 求余的结果,如果不等于 448,就需要填充原文使得原文对 512 求余的结果等于 448。填充的方法是第一位填充 1,其余位填充 0。填充完后,信息的长度就是 512*N+448
之后,用剩余的位置(512-448=64 位)记录原文的真正长度,把长度的二进制值补在最后。这样处理后的信息长度就是 512*(N+1)。
第二步:
MD5 的哈希结果长度为 128 位,按每 32 位分成一组共 4 组。这 4 组结果是由 4 个初始值 A、B、C、D 经过不断演变得到。MD5 的官方实现中,A、B、C、D 的初始值如下(16 进制):

  • A=0x01234567
  • B=0x89ABCDEF
  • C=0xFEDCBA98
  • D=0x76543210

第三步:
这一步是最复杂的一步,大概流程就是将ABCD进行循环,每一次循环都会让旧的 ABCD 产生新的 ABCD,然后再用新的 ABCD再去循环(具体细节不展开)。
循环的次数是由处理后的原文长度决定的:
假设处理后的原文长度是 M

主循环次数 = M / 512
每个主循环中包含 512 / 32 * 4 = 64 次 子循环

第四步:
这一步就很简单了,把循环加工最终产生的 A,B,C,D 四个值拼接在一起转换成字符串。

更详细的过程请参考:链接

三、破解MD5

首先要明白,所谓的“破解”并不是使用密文推算出明文,这在理论上是不可能的

山东大学王小云院士在2004成功破解 MD5,她的成果也不是通过 MD5 的散列值逆向推算出明文。实际上,王小云的研究成果为,给定消息 M1,能够计算获取 M2,使得 M2 产生的散列值与 M1 产生的散列值相同,即MD5(M1)=MD5(M2)。

可参看王小云院士提交的报告: 《Collisions for Hash Functions
MD4, MD5, HAVAL-128 and RIPEMD 》

在网络上使用的破解都是使用 碰撞 的方法实现由密文得到原文。
举例来说,假设我们得到一个 md5 的密文,我们可以先将一些常用密码使用 md5 加密,然后与我们之前得到的 md5 密文进行比较,如果两个密文相同,我们就可以知道密码了。理论上只要你的密码库足够大,你破解密码的成功率就足够高。
作为用户来说,在设置密码时,尽量不使用常用密码,作为开发者来说,我们可以对用户密码进行 加盐操作,我们将用户密码与一个我们要加的 ‘盐’ 拼接在一起,只要’盐‘不被知道,我们的密码就很难被 撞库破解

四、代码实现

在Python中内置模块 hashlib 中可以实现 md5 加密,在该模块中还可以实现 sha1 的加密:

from hashlib import md5

s = md5()
s.update('我爱 Python'.encode())
s.update('Salt'.encode()) # 加盐操作
print(s.hexdigest())  # aeeb02d8a54ade8469e419c8a8f9d8b8

md5类 的 update() 方法是添加字符串而不是覆盖字符串,因此对于数据量较大时的加密我们可以使用多次 update 计算的方法。

猜你喜欢

转载自blog.csdn.net/qq_43580193/article/details/105048270
今日推荐