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是相对安全的,目前使用也比较广泛
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
