MD5加密算法与实现

MD5加密算法与实现

MD5算法简介

MD5的全称是Message-Digest Algorithm,是Hash算法中的一种重要算法,具有单项加密、加密结果唯一、安全性能好等特点。MD5以512位分组来处理输入的信息,且每一分组又被划分为16个 32位子分组,经过了一系列的处理后 ,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。

MD5算法的优势

(1)容易计算及不可逆性:

  • 现在主流的编程语言基本都支持MD5算法的实现,所以非常容易计算出一个数据的MD5值。
  • 而且MD5算法是不可逆的,也就是说我们无法通过常规的方式从MD5值倒推出它的原文。

(2)压缩性:

  • 任意长度的数据,其MD5值都是一个32位长度的十六进制字符串区分大小写(所以要和安卓、服务端商量好是用大写还是小写)。

(3)抗修改性:

  • 对原数据做一丁点的改动,MD5值就会有巨大的变动。逆反过来理解一下这个特性,比如说两个原数据的MD5值非常相似,但是你不能想当然的认为它们俩对应的原数据也相似。这个特性表明的是,如果你想要很轻易的由MD5倒猜出原文数据是不可能的,因此这个特性在某种程度上表明了MD5算法是安全的。

(4)抗碰撞性:

​ 抗碰撞性分为两种:

  • 第一种,**知道了原数据及其MD5值,想要碰撞出这个MD5值,从而猜测出原数据,是非常困难的。**这种碰撞的难度表明的是,强制破解MD5算法是非常困难的,更别说上面的轻易倒推了。
  • 第二种,我们知道MD5值总是一个32位的十六进制字符串,换算成二进制就是一个128位的字符串,因此所有的MD5值一共有2的128次方种可能性,**那么用自然界无穷的数据去对应这个有限的MD5值集合,会不会出现不同的数据有相同的MD5值呢?这样看来,理论上是会的,但是实际中想要找到两个不同的数据有着相同的MD5值是非常困难的。**这种碰撞的难度表明的是,我们可以放心的去使用MD5算法,不必担心不同的数据拥有相同的MD5值。

为什么说以上两种碰撞是困难的呢?因为要寻找这样一对碰撞是需要耗费非常非常长的时间的,依照现在计算机的计算能力,碰撞被认为在实际中是不可能发生的。因此,这个特性也在某种程度上表明了MD5算法的安全性。

MD5算法流程

在这里插入图片描述

  • 信息填充首先需要对明文信息进行填充,使其位长度对512求余的结果等于448。因此,信息的位长度(Bits Length)将被扩展至 N512 + 448。然后,再在这个结果后面附加一个以64位二进制表示的填充前信息长度。经过这两步的处理 ,现在的信息字节长度为 N512 + 448 + 64 = (N + 1) *512,即长度恰好是 512的整数倍。

  • 结构初始化在处理过程中需要定义一个结构。该结构包含了每一次需要处理的一个明文块 (512bit)和计算出来的散列值 (128bit)。在散列的整个过程中,它的作用非常重要 ,各个明文块计算出来的散列值都是通过它来传递的。

  • 分组文件将填充好的文件进行分组 ,每组 512位 ,共有N组。

  • 处理分组使用算法处理每组数据。MD5算法在计算时会用到四个32位被称作链接变量 (Chaining Variable)的整数参数 ,在使用之前要对它们赋初值 ,分别就为 :A = 0x01234567,B = 0x89abcdef, C = 0xfedcba98,D =0x76543210。当设置好这四个链接变量后,就开始进入算法的四轮循环运算。循环的次数是信息中512位信息分组的数目。将上面四个链接变量复制到另外四个变量中 :A到 a,B到 b, C到 c,D到 d。主循环有四轮,每轮循环都很相似。第一轮进行16次操作。每次操作对 a、b、c和 d中的其中三个作一次非线性函数运算 ,然后将所得结果加上第四个变量,一个子分组和一个常数。再将所得结果向右环移一个不定的数,并加上 a、b、c或 d中之一,最后用该结果取代 a、b、c或 d中之一。

  • 输出结果当全部信息处理完成后 ,将分组处理的结果进行处理,输出计算结果。所有这些完成之后 ,将 A、B、C、D分别加上 a、b、c、d。然后用下一分组数据继续运行算法 ,最后的输出是 A、B、C和 D的级联。当全部分组处理完成后,将结果级联 ,即得到了 MD5处理的结果。

代码实现

import java.math.BigInteger;
import java.security.MessageDigest;

/**
 * 加密工具MD5类
 */
public class EncryptUtil {
    public static String md5(String plainText){
        String encryStr = null;
        if (plainText != null && !"".equals(plainText)) {
            try {
                //md5实现类实例化
                byte[] ret = MessageDigest.getInstance("md5").digest(plainText.getBytes());
                //将获取的byte数组值转为16进制的字符串
                String md5Code = new BigInteger(1, ret).toString(16);
                //获取的字符串不足32位的用“0”补齐
                for (int i = 0; i < 32 - md5Code.length(); i++) {
                    md5Code = "0" + md5Code;
                }
                encryStr = md5Code;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return encryStr;
    }
}

/*测试类*/
import org.junit.Test;

/**
 * 测试输出:81dc9bd52d04dc20036dbd8313ed055
 */
public class TestEncrypt {
    @Test
    public void testMd5(){
        System.out.println(EncryptUtil.md5("1234"));
    }
}

参考:https://blog.csdn.net/qq_37141773/article/details/97103457和https://blog.csdn.net/kkkjy/article/details/106404812

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值