MD5数据加密方法

什么场景需要使用数据加密呢?比如秘密数据传输、用户密码加密存储等等

数据传输可使用密钥对的方式进行加密解密,使用签名方式验证数据是否可靠,而密码加密存储可使用MD5等一些算法对数据进行单向加密

一、MD5单向加密

1、百度说法:

MD5信息摘要算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。MD5由美国密码学家罗纳德·李维斯特(Ronald Linn Rivest)设计,于1992年公开,用以取代MD4算法。这套算法的程序在 RFC 1321 标准中被加以规范。1996年后该算法被证实存在弱点,可以被加以破解,对于需要高度安全性的数据,专家一般建议改用其他算法,如SHA-2。2004年,证实MD5算法无法防止碰撞(collision),因此不适用于安全性认证,如SSL公开密钥认证或是数字签名等用途。

2、理解
md5可以把明文加密成密文,但是不可以把密文解密成原来的明文

在这里插入图片描述

那我们使用的逻辑是
密码加密后把密文存在数据库中,要判断输入的密码是否正确时,只需要对输入密码经过相同的md5加密,验证两次加密结果是否相同就可以了

在这里插入图片描述

md5能做到的就是,两个不同的明文加密得到相同的密文的几率是极低的,所以可以用以上逻辑判断

3、破解

md5不能解密,那么如何破解呢?其实md5的弊端非常明显,那就是同一个明文每次加密得到的密文都是一样的,例如对123456加密的到的结果是e10adc3949ba59abbe56e057f20f883e,那么我们只要跑一次加密就可以知道密文对应的原文是什么了

如果密码单纯是10位以内的数字,那么跑10的10次方次MD5,就可以破解所有密码

考虑到查询的性能问题,可以把结果进行排序,通过二分查找就可以log(n)的复杂度查出结果

我们可以看看目前对应的破解平台
在这里插入图片描述

e10adc3949ba59abbe56e057f20f883e是123456加密出来的结果

破解:
在这里插入图片描述

4、解决办法
(1)一次md5加密容易被破解,那么我们进行多次md5加密呢?这种办法也是不太可行的,如果加密次数也知道了,那么也是容易被破解的
(2)加盐,可看以下详细解释

二、MD5+固定盐值

1、原理
对原来的明文拼接一个字符串,再进行加密,如果这个字符串不泄露,那么就密文就是安全的,因为即使你通过暴力打表的手段得到了原来的明文1afvr2ara34avf56bsrcafavtrt,你也不能知道原来的密码是123,还是246
在这里插入图片描述

那么我们使用的方法就是,将用户输入的密码按相同的方法加盐值,加密,对比存储的密码是否相同即可

3、不足
md5加固定盐值是多次加密的原理是一样的,只要固定盐值也泄露了,那么也就意味着被破解了

三、MD5+随机盐值

1、原理
固定盐值加密泄露了盐值,就可以被暴力计算出来,而且可以很快就破解全部的密码

那么可以考虑,如果每个用户加密使用的盐值都是不一样的,那么黑客就无法一下子破解全部的密码,每破解一个用户的密码,都需要按盐值暴力跑加密,直到密码被找到,这大大提高的破解的时间

这样,某个用户的盐值泄露了,不会影响其它用户,即使所有用户的盐值都泄露了,黑客也需要非常长的时间才可以全部破解

在这里插入图片描述

四、BCrypt

1、原理
spring security 封装了BCryptPasswordEncoder

BCryptPasswordEncoder的实现思路和md5+随机盐值的思路差不多
也是使用随机盐值加密,使得同一个明文每次的加密的结果都不同,不一样的是,BCryptPasswordEncoder会对明文进行多次加密,多次转换操作,提高破解难度

值得一提的一个点是,适当地提高单次完整加密的时间也可以提高破解难度,提高系统安全性,如果一次单次完整加密需要从0.1秒提升到1秒,那么破解的时间会从1年提高到10年

五、加密体验

添加security依赖:

	<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>

使用MD5加密:

package com.wu.encryption.main;

import org.springframework.util.DigestUtils;

import java.util.UUID;

public class Md5 {
    public static void main(String[] args) {

        /**
         * MD5加密
         * 1、生成密文,存数据库
         * 2、判断的时候,对密码加密,取出数据库密文校验
         * 3、若一致则正确,否则不正确
         *
         */
        String password1 = "123456";
        String encode1 = DigestUtils.md5DigestAsHex(password1.getBytes());
        System.out.println("MD5加密:"+encode1);
        System.out.println("-----------------------");


        /**
         * MD5+固定盐
         * 1、密码拼接盐值
         * 2、生成密文,存数据库
         * 3、判断的时候,密码拼接盐值,生成密文,取出数据库密文校验
         * 4、若一致则正确,否则不正确
         */

        String salt2 = "hello";
        String password2 = "123456";
        String encode2 = DigestUtils.md5DigestAsHex((password2+salt2).getBytes());
        System.out.println("MD5固定盐加密:"+encode2);
        System.out.println("-----------------------");


        /**
         * MD5+随机盐
         * 1、生成随机盐,UUID可以保证全局唯一,即可实现每个用户的盐都不一样
         * 2、密码拼接盐值
         * 3、生成密文,把密文和盐都存数据库
         * 4、判断的时候,取出数据库盐值,密码拼接盐值,生成密文,取出数据库密文校验
         * 5、若一致则正确,否则不正确
         */

        String salt3 = UUID.randomUUID().toString();
        String password3 = "123456";
        String encode3 = DigestUtils.md5DigestAsHex((password3+salt3).getBytes());
        System.out.println("MD5随机盐加密:"+encode3);


    }


}

在这里插入图片描述

经过加盐处理后,就不能被简单解密了
在这里插入图片描述

使用spring security提供的BCryptPasswordEncoder:

package com.wu.encryption.main;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import java.util.*;

public class BCrypt {
    public static void main(String[] args) {
        /**
         * 1、BCryptPasswordEncoder机制和md5+随机盐类似,BCryptPasswordEncoder采用的是安全hash,SHA256
         * 2、BCryptPasswordEncoder同一个明文每次加密都会产生不同的结果
         * 3、BCryptPasswordEncoder只需要简单地使用encode加密和matches判断匹配就可以了,盐值就存在密文里,不需要程序员关心
         *
         */
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        int n=10;
        long time1 = new Date().getTime();
        for (int i = 0; i < n; i++) {
            String encode = encoder.encode("123456");
            System.out.println(encode);
            System.out.println(encoder.matches("123456",encode));

        }
        long time2 = new Date().getTime();
        System.out.println("加密"+n+"条数据,耗时"+(Double.valueOf(time2)-time1)/1000+"秒");

    }
}

在这里插入图片描述
可以看到,每次加密的结果都不一样,但是都可以匹配成功

BCrypt是相对安全的,目前使用也比较广泛

  • 22
    点赞
  • 91
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旧林墨烟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值