MD5加密算法

目录

一、MD5 概述

二、MD5 算法原理

三、使用 Java 实现 MD5 加密

四、使用 Python 实现 MD5 加密

最后

一、MD5 概述

MD5,即 Message Digest Algorithm 5 缩写,中文含义为信息摘要算法第5版,是一种被广泛使用的密码散列函数,可产生一个16字节的散列值,用来提供信息的完整性保护。对于软件开发者来说,经常使用 MD5 校验信息的完整性(比如,防止文件篡改或损坏),甚至将它当作加密算法使用。

MD5 作为一种摘要算法,具有以下特征:

1、产生固定长度的散列值。无论输入了多长的信息,经过 MD5 处理后都只会产生一个16字节的散列值。

2、不可逆。经过 MD5 处理后得到的散列结果,无法计算出原始数据,正是因为 MD5 无法从密文还原成明文,它不能用于解密了。

3、运算快。MD5 采用的是位运算,速度很快,几乎不占用 CPU 资源。

4、不安全。1996年后该算法被证实存在弱点,可以被加以破解。2004年,证实 MD5 算法无法防止碰撞,因此不适用于安全性认证,比如 SSL 公开密钥认证、数字签名等用途。2011年,RFC 6151 禁止 MD5 用作密钥散列消息认证码。

所谓特性决定用途。由于 MD5 存在不安全的问题,注定不能用于加解密算法。比如,攻击者通过某些方式(查字典)获取了 MD5 的原文信息,那 MD5 加密就没什么用了。举个容易懂的例子,我需要在用户信息表中存放用户密码 10086,通过 MD5 加密后存放的是一串字符串 6412121cbb2dc2cb9e460cfee7046be2,如果攻击者的字典手册里也有这串字符串,那攻击者很轻易知道你的密码就是 10086 了,是不是很危险!

尽管如此,MD5 在校验文件的完整性是大有作为的。比如,文件上传和下载。通常情况下,发送方会将原始数据文件和 MD5 摘要信息同时发送给接收方,当接收方拿到数据文件后,会将数据文件做 MD5 处理得到一个摘要信息,然后只要比对这两个摘要信息是否一致就能判定文件是否被篡改,或者损坏了。

二、MD5 算法原理

MD5 本质上也是一种哈希算法,会输出一个16字节(128位)固定长度的散列值,该算法的大致流程如下:

MD5 算法原理,可简单的描述为:MD5 码以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。

在 MD5 算法中,首先需要对信息进行填充,这个数据按位补充,要求最终的位数对512求模的结果为448。也就是说数据补位后,其位数长度只差64位就是512的整数倍。即便是这个数据的位数对512求模的结果正好是448也必须进行补位。补位的实现过程:首先在数据后补一个1 bit; 接着在后面补上一堆0 bit, 直到整个数据的位数对512求模的结果正好为448。总之,至少补1位,而最多可能补512位。

在完成补位工作后,又将一个表示数据原始长度的 64 bit数补在最后。当完成补位及补充数据的描述后,得到的结果数据长度正好是512的整数倍。也就是说,长度正好是16个(32bit) 字的整数倍。

需要注意,MD5 运算要用到一个128位的 MD5 缓存器,用来保存中间变量和最终结果。该缓存器又可看成是4个32位的寄存器A、B、C、D,初始化如下:

  • A : 01 23 45 67
  • B: 89 ab cd ef
  • C: fe dc ba 98
  • D: 76 54 32 10

MD5 处理数据段时,首先定义4个非线性函数 F、G、H、I,对输入的报文运算以512位数据段为单位进行处理。对每个数据段都要进行4轮的逻辑处理,在4轮中分别使用4个不同的函数 F、G、H、I。每一轮以 ABCD 和当前的512位的块为输入,处理后送入 ABCD (128位)。

信息摘要最终处理成以 A, B, C, D 的形式输出。也就是开始于 A 的低位在前的顺序字节,结束于 D 的高位在前的顺序字节。

目前有很多验证 MD5 的工具,比如:

这些可以直接拿来使用和验证。

三、使用 Java 实现 MD5 加密

实际项目中,我使用 MD5 是简化参数连接的。有一个使用场景是,要将十多个参数值拼接在一起组成 ES 文档的 pkey,这样的 pkey 看上去特别长,最多时有200多个字符吧!

此时,使用 MD5 算法就可以有效解决这个问题,因为无论输入端有多长,MD5 处理后只会得到一个固定长度的字符串。

Java 实现 MD5 算法,代码如下:

import java.security.MessageDigest;
import java.util.Objects;

public class MD5Util {
    private static final char[] HEX_DIGITS
            = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    private static String characterEncoding;

    public static String encode(String str) {
        if (Objects.isNull(str)) {
            return null;
        }
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(Objects.nonNull(characterEncoding) 
                    ? str.getBytes(characterEncoding) : str.getBytes());
            byte[] bytes = md.digest();
            StringBuilder builder = new StringBuilder(bytes.length * 2);
            for (byte b : bytes) {
                builder.append(HEX_DIGITS[b >> 4 & 15]);
                builder.append(HEX_DIGITS[b & 15]);
            }
            return builder.toString();
        } catch (Exception e) {
            throw new RuntimeException("process failed ", e);
        }
    }
}

测试结果:

@SpringBootTest
@Slf4j
class SpringbootApplicationTests {

    @Test
    void test20230330() {
        //6412121cbb2dc2cb9e460cfee7046be2
        log.info("10086 md5 is {}", MD5Util.encode("10086"));
        //c807aa66939df40294ccaf65b8c009c5
        log.info("我是一句话 md5 is {}", MD5Util.encode("我是一句话"));
    }

}

当然,也可以借助其他工具,验证该算法的正确性。这里,我是用的是 Notepad++ 编辑器里的”工具-md5“验证,如下:

四、使用 Python 实现 MD5 加密

Python 的 hashlib 包支持 md5 加密,使用演示如下:

import hashlib

# 要先创建md5对象
md1 = hashlib.md5()
md1.update("10086".encode())
print(md1.hexdigest())  # 预期值:6412121cbb2dc2cb9e460cfee7046be2

md2 = hashlib.md5()
md2.update("我是一句话".encode())
print(md2.hexdigest())  # 预期值:c807aa66939df40294ccaf65b8c009c5

测试结果:

最后 

不同的编程语言,都有着各自的 MD5 加密实现方式。不过,大多数都是高度封装后提供包来给开发者直接使用了,无论何种方式,理解 MD5 的特性及实现原理才是最重要的。

参考资料:百度百科。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值