MD5加密算法的原理

目录

 

1.MD5简介;

2.MD5用途;

3.MD5工具类的实现;

4.MD5加密过程;

5. MD5特征分析;


​​​​​​​

1.MD5简介;

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

密码散列函数(Cryptographic hash function),又译为加密散列函数,是散列函数的一种。它被认为是一种单向函数,也就是说极其难以由散列函数输出的结果,回推输入的数据是什么。这样的单向函数被称为“现代密码学的驮马”。这种散列函数的输入数据,通常被称为消息(message),而它的输出结果,经常被称为消息摘要(message digest)或摘要(digest)。在信息安全中,有许多重要的应用,都使用了密码散列函数来实现,例如数字签名,消息认证码。 

2.MD5用途;

 MD5特点:用户传入一个明文的字符串,加密后得到一个密文!

3.MD5工具类的实现;

加盐方式:

//加盐方式
    public static String EncoderPwdByMd5(String pwd) throws NoSuchAlgorithmException {

        // 1,获取信息摘要对象md5,利用其单例函数来获取
        MessageDigest md5=MessageDigest.getInstance("MD5");

        // 2,信息摘要对象md5是对字节数组进行摘要的,所以先获取字符串的字节数组
        byte[] str_bytes=pwd.getBytes();

        // 3,信息摘要对象对得到的字节数组进行摘要,得到摘要字节数组,返回的是byte[] - 字节数组,长度是16个字节
        byte[] result = md5.digest(str_bytes);

        // 4,把摘要数组中的每一个字节转换成16进制,并拼在一起就得到了MD5值.
        StringBuffer sb = new StringBuffer();
        // 把每一个byte 做一个与运算 0xff;
        for (byte b : result) {
            // 与运算,获取字节的低8位有效值
            int number = b & 0xff;// 加盐
            // 将整数转换成16进制
            String str = Integer.toHexString(number);
            // 如果是1位的话,补0
            if (str.length() == 1) {
                sb.append("0");
            }
            // 把密文添加到缓存中
            sb.append(str);
        }
        // 标准的md5加密后的结果
        return sb.toString();
    }

主函数测试:

public static void main(String[] args) throws NoSuchAlgorithmException {
        System.out.println("加密后的密码为:\n"+EncoderPwdByMd5("123fbuinnviuiwj265"));
        System.out.println("md5密文的位数:\n"+EncoderPwdByMd5("123").length());
    }

运行结果:

普通方式:

//普通方式
    public static String EncoderPwdByMd5_2(String pwd) throws NoSuchAlgorithmException {

        char hexDigits[] = {
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
        };

        // 1,获取MD5摘要算法的MessageDigest对象md5,利用其单例函数来获取MD5的对象
        MessageDigest md5=MessageDigest.getInstance("MD5");

        // 2,将密码先转换成字节数,使用指定的字节更新摘要
        md5.update(pwd.getBytes());

        // 3,获得密文
        byte[] result = md5.digest();

        // 4,把密文(字节数组)转换成十六进制的字符串形式,拼在一起就得到了MD5值
        int j = result.length;
        char str[] = new char[j * 2];
        int k = 0;
        for (int i = 0; i < j; i++) {
            byte byte0 = result[i];
            str[k++] = hexDigits[byte0 >>> 4 & 0xf];
            str[k++] = hexDigits[byte0 & 0xf];
        }
        return new String(str);
    }

主函数测试:

public static void main(String[] args) throws NoSuchAlgorithmException {
        //System.out.println("加密后的密码为:\n"+EncoderPwdByMd5("123fbuinnviuiwj265"));
        //System.out.println("md5密文的位数:\n"+EncoderPwdByMd5("123").length());
        System.out.println("加密后的密码为:\n"+EncoderPwdByMd5_2("123"));
        System.out.println("md5密文的位数:\n"+EncoderPwdByMd5("123").length());
    }

运行结果:

4.MD5加密过程;

加密过程分为4步:

第1步:

//1,获取MD5摘要算法的MessageDigest类,利用其单例函数来获取对象md5
MessageDigest md5=MessageDigest.getInstance("MD5");

第2步:

/*2,信息摘要的方法md5.digest(),其中的参数和返回值都是byte[](字节数组)类型;

所以先要获取字符串的字节数组;*/

 byte[] str_bytes=pwd.getBytes();

第3步:

/*3,信息摘要对象对得到的字节数组进行摘要,得到摘要字节数组,返回的是byte[] - 字节数组,长度是16个字节*/
byte[] result = md5.digest(str_bytes);

第4步:

// 4,把摘要数组中的每一个字节转换成16进制,并拼在一起就得到了MD5值
StringBuffer sb = new StringBuffer();
        // 把每一个byte 做一个与运算 0xff;
        for (byte b : result) {
            // 与运算,获取字节的低8位有效值
            int number = b & 0xff;
            // 将整数转换成16进制
            String str = Integer.toHexString(number);
            // 如果是1位的话,补0
            if (str.length() == 1) {
                sb.append("0");
            }
            // 把密文添加到缓存中
            sb.append(str);
        }
        // 标准的md5加密后的结果
        return sb.toString();

5. MD5特征分析;

总体概括:

用户传入一个明文的字符串(可见),加密后得到一个密文(不可见)!

得到的散列值特点: 

1,密文为128bit(16字节)的散列值,用于确保信息传输完整一致

2,长度固定,不管多长的字符串,加密后长度都是一样长;

3,不可逆,你明明知道密文和加密方式,你却无法反向计算出原密码,一般解密不了;

长度问题:

1,md5的长度,默认为128bit,也就是128个0和1的二进制串;

2,格式不太好,所以将二进制转成了16进制,每4个bit表示一个16进制,

3,所以128/4 = 32 换成16进制表示后,为32位了;

byte类型转换成int类型:

首先byte是1个字节,8bit;

int是4个字节,32bit;

当把一个低精度的数据类型转成一个高精度的数据类型时,必然会涉及到如何扩展位数的问题;

补符号位扩展,若为负数,高24位全部补1,转换成十进制则会出问题。

目的就是为了保证二进制数据的一致性。

 第一,oxff默认为整形,二进制位最低8位是1111  1111,前面24位都是0;

第二,&运算: 如果2个bit都是1,则得1,否则得0;

第三,byte的8位和0xff进行&运算后,最低8位中,原来为1的还是1,原来为0的还是0,而0xff其他位都是0,所以&后仍然得0,

发布了295 篇原创文章 · 获赞 100 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/qq_37084904/article/details/102753515