浅析md5加密、加盐、碰撞等知识

写在文章之前

1.源码路径:https://github.com/liangminghui/MavenDemo.git 如果没有git环境,可以用zip包下载
2.本文章演示案例均为maven案例,需要引入下边这个包

		<dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.10</version>
        </dependency>

加密相关

最简单的MD5加密

 	@Test
    public void test1() {
        String test_str_first = 11316 + "";
        System.out.println(getMD5(test_str_first));
    }
    /**
     * 对字符串md5加密(小写+字母)
     *
     * @param str 传入要加密的字符串
     * @return MD5加密后的字符串
     */
    private String getMD5(String str) {
        return DigestUtils.md5Hex(str);
    }

最简单的揭秘方法就是访问这个网站 https://www.cmd5.com/ 把加密出来的数据解密,如下所示在这里插入图片描述

常用复杂加密MD5方法

多次加密

    @Test
    public void test2() {
        String test_str_first = 11316 + "";
        String salt = "666";
        // 1 :多次加密
        System.out.println(getMD5(test_str_first, 2));
        //2 : 加盐
        //2.1 密码加盐
        // System.out.println(getMD5(test_str_first+salt));
        //2.2 加密之后加盐
        // System.out.println(getMD5(test_str_first,salt));
    }
     private String getMD5(String str, int count) {
      if (count == 0) {
          return str;
      } else {
          str = getMD5(str);
          return getMD5(str, count - 1);
      }
  }

虽然这个方式看起来很可靠,但是很不幸,上边所用的网站也可以破解这个密码,如图在这里插入图片描述
不仅能解密,还能显示加密多少次。。。所以现在很多程序都在使用加盐的方式

加盐

首先解释一下什么叫做加盐,类似于做菜一样,是在原加密的基础上,加上一段“标记”,混淆密码,代码如下所示
1.先加盐再加密

 @Test
    public void test2() {
        String test_str_first = 11316 + "";
        String salt = "666";
        // 1 :多次加密
        //System.out.println(getMD5(test_str_first, 2));
        //2 : 加盐
        //2.1 密码加盐
         System.out.println(getMD5(test_str_first+salt));
        //2.2 加密之后加盐
        // System.out.println(getMD5(test_str_first,salt));
    }

这种加密虽然不失为一个解决方法,但是解密出来之后即使加盐,原密码也是有暴漏的风险
2.先加密在加盐

	@Test
    public void test2() {
        String test_str_first = 11316 + "";
        String salt = "666";
        // 1 :多次加密
        //System.out.println(getMD5(test_str_first, 2));
        //2 : 加盐
        //2.1 密码加盐
        //System.out.println(getMD5(test_str_first+salt));
        //2.2 加密之后加盐
        System.out.println(getMD5(test_str_first,salt));
    }
     private String getMD5(String str,String salt) {
        try {
            // 生成一个MD5加密计算摘要
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 计算md5函数
            md.update(str.getBytes());
            // digest()最后确定返回md5 hash值,返回值为8为字符串。因为md5 hash值是16位的hex值,实际上就是8位的字符
            // BigInteger函数则将8位的字符串转换成16位hex值,用字符串来表示;得到字符串形式的hash值
            return new BigInteger(1, md.digest()).toString(16)+salt;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

众所周知,MD5加密出来的数据是有固定长度的。现在就算获取到了“3798003c3d078a7b4fd1f33843a2e5c0666”这个值,除非知道加密方式以及盐值,否则很难解密出原文,所以这种方式应用广泛。

碰撞

什么叫碰撞?简单的来说就是加密出来的值相同,现在简单写个案例,重现一下碰撞,代码如下,在运行代码之前,你需要下载如下两个EXE文件(这两个文件不可安装,只是两个在文件加密之后值相同,下载之后给个star吧)在这里插入图片描述

	@Test
	public void test3(){
        String path = "F:\\project\\MavenDemo\\src\\test\\java\\demo\\";
        try {
            String str1 = DigestUtils.md5Hex(new FileInputStream(path+"GoodbyeWorld-colliding.exe"));
            String str2 = DigestUtils.md5Hex(new FileInputStream(path+"HelloWorld-colliding.exe"));
            String str1_sha = DigestUtils.sha1Hex(path+"GoodbyeWorld-colliding.exe");
            String str2_sha = DigestUtils.sha1Hex(path+"HelloWorld-colliding.exe");
            System.out.println("str1 md5>>>>>"+str1);
            System.out.println("str2 md5>>>>>"+str2);
//            System.out.println("str1_sha>>>>>"+str1_sha);
//            System.out.println("str1_sha>>>>>"+str2_sha);
//            System.out.println(DigestUtils.md5Hex(str1+str1_sha));
//            System.out.println(DigestUtils.md5Hex(str2+str2_sha));
        }catch (Exception e){
            System.out.println(e);
        }

    }

关于碰撞有以下几点
1.怎样解决碰撞
解决碰撞其实可以通过 MD5 和 SHA-1 结合使用来实现。首先将文件 A 的 MD5 值记为 B 再把 A 的 SHA-1 记为 C,之后用将 B 和 C 相加之后再次运算 MD5 值

	@Test
    public void test3(){
        String path = "D:\\project\\MavenDemo\\src\\test\\java\\demo\\";
        try {
            String str1 = DigestUtils.md5Hex(new FileInputStream(path+"GoodbyeWorld-colliding.exe"));
            String str2 = DigestUtils.md5Hex(new FileInputStream(path+"HelloWorld-colliding.exe"));
            String str1_sha = DigestUtils.sha1Hex(path+"GoodbyeWorld-colliding.exe");
            String str2_sha = DigestUtils.sha1Hex(path+"HelloWorld-colliding.exe");
            System.out.println(DigestUtils.md5Hex(str1+str1_sha));
            System.out.println(DigestUtils.md5Hex(str2+str2_sha));
        }catch (Exception e){
            System.out.println(e);
        }

    }

2.MD5还安全么?
我个人认为是安全的。主要是有一下原因
i.加密信息的不确定性,比如,当你要加密1+99时,MD5也只会加密100(1+99)的值,你可以通过解密推出原文是100,但100却很难推测出是通过1+99得来的。
ii.找到了碰撞也没用,你只是发现两个文件可以有相同的MD5,但你无法反推原文是什么,且商业应用中密码都是层层加密,破解不了的。
iii.可以使用最后解决MD5碰撞的方法,MD5 值碰撞的几率已经很小,再结合 SHA-1 的话,基本上就不会发生碰撞的问题出现了

结语

1.参考链接 https://blog.csdn.net/qq_40006446/article/details/80930113
2.各位给个star吧,就当下载那两个文件的csdn积分了
3.欢迎关注,欢迎留言

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值