equals方法居然也有不一样的?

        今天在翻阅jdk源码中加密相关代码时,翻着翻着好像混进来一个奇怪的东西。

        正当我以为是普通的equals方法准备划过去时,突然瞥见了一行代码。

result |= digesta[i] ^ digestb[i];

         我靠,这是啥东西,这好像和我之前用的equals方法不一样哇,我怀疑我的记忆出现了问题,赶快去看了一下equals的代码。

         这肯定不一样好吧,仔细看上面单独拿出来的一行代码,发现MessageDigest类下的isEqual方法是按位比较,直至字符串结束;String类下的Equals类是比较到不相同的字符直接退出。这两段代码一看就知道第一种很费时,既然是比较字符串是否相等,为什么还要第一种呢?

        查了一些资料发现,这种可以防止【计时攻击】,计时攻击说白了就是他遍历所有的字符来试你的密码,根据你的响应时间判断前面的几位字符是否相同。比如你的密码是password,你调用euqals遍历一次是1ms,他输入pa666,当你使用第一种isEqual时就是5ms,调用第二种时就是2ms,很容易就能判断出来前两位密码。

        写到这里我突然想起来MD5算法,和这个的作用岂不是很像,只不过可能MD5慢了一点。我瞅瞅他能慢到哪去?

        String password = "testPassword123456";


        long startTime=System.nanoTime();
        System.out.println("spring-DigestUtils中md5开始:" + startTime);
        String result = DigestUtils.md5DigestAsHex((password).getBytes());
        System.out.println(result);
        long endTime=System.nanoTime();
        System.out.println("spring-DigestUtils中md5结束:" + endTime);
        System.out.println("spring-DigestUtils中md5用时:" + (endTime - startTime));


        System.out.println("------------------------------------------------------");
        long oldStartTime = 0L;
        long oldEndTime = 0L;
        String oldResult = null;
        try {
            oldStartTime=System.nanoTime();
            System.out.println("jdk-MessageDigest中md5开始:" + oldStartTime);
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            byte[] byteInput = password.getBytes();
            md5.update(byteInput);
            byte[] btResult = md5.digest();
            StringBuffer stringBuffer = new StringBuffer();
            for (byte b : btResult) {
                int bt = b&0xff;
                if (bt < 16) {
                    stringBuffer.append(0);
                }
                stringBuffer.append(Integer.toHexString(bt));
            }
            oldResult = stringBuffer.toString();
            System.out.println(oldResult);
            oldEndTime=System.nanoTime();
            System.out.println("jdk-MessageDigestmd5结束:" + oldEndTime);
            System.out.println("jdk-MessageDigestmd5用时:" + (oldEndTime - oldStartTime));
        } catch (Exception e) {
            e.printStackTrace();
        }

        long startMD5Time=System.nanoTime();
        System.out.println("md5比较开始:" +startMD5Time);
        boolean equals = result.equals(oldResult);
        long endMD5Time=System.nanoTime();
        System.out.println("md5比较结束:" +endMD5Time);
        System.out.println("md5比较用时:" + (endMD5Time - startMD5Time));
        System.out.println("spring-DigestUtils中md5总用时:" + (endMD5Time - startMD5Time + (endTime - startTime)));
        System.out.println("jdk-MessageDigest中md5总用时:" + (endMD5Time - startMD5Time + (oldEndTime - oldStartTime)));


        System.out.println("------------------------------------------------------");
        long isEqualStartTime=System.nanoTime();
        System.out.println("isEqual开始:" + isEqualStartTime);
        boolean equal = MessageDigest.isEqual(password.getBytes(StandardCharsets.UTF_8), password.getBytes(StandardCharsets.UTF_8));
        System.out.println("是否相等:" + equal);
        long isEqualEndTime=System.nanoTime();
        System.out.println("isEqual开始:" + isEqualEndTime);
        System.out.println("isEqual用时:" + (isEqualEndTime - isEqualStartTime));

 运行结果如下

         好吧,jdk中的MD5比isEqual慢了一倍,但是意外的是spring中DigestUtils下的MD5算法竟然慢了这么多,下一期我们解析一下spring中DigestUtils下的MD5算法做了什么,为什么这么慢。

        写到这里了笔者还是不理解为啥会有isEqual方法的存在,储存密码的话为什么不直接使用MD5呢?什么情况下会调用这个方法?求指教

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

差点资深程序员

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

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

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

打赏作者

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

抵扣说明:

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

余额充值