boolean safeEqual(String a, String b) { if (a.length() != b.length()) { return false; } int equal = 0; for (int i = 0; i < a.length(); i++) { equal |= a.charAt(i) ^ b.charAt(i); } return equal == 0; }
从效率角度上讲,难道不是应该只要中途发现某一位的结果不同了就可以立即返回两个字符串不相等了吗?
这里有解密,欢迎关注讨论。
看来 V 站的都是大神~ NPE 被省去了哈。JDK 中的 java.security.MessageDigest
是有的:
public static boolean isEqual(byte[] digesta, byte[] digestb) { if (digesta == digestb) return true; if (digesta == null || digestb == null) { return false; } if (digesta.length != digestb.length) { return false; } int result = 0; // time-constant comparison for (int i = 0; i < digesta.length; i++) { result |= digesta[i] ^ digestb[i]; } return result == 0; }
欢迎大佬关注公众号,给予指导。
![]() | 1 xiangyuecn 2020-06-07 20:00:45 +08:00 如果真需要保护不被时序攻击,理论上这坨代码第一行就会泄露被保密的字符串长度。另外欢迎体验 NullPointerException |
![]() | 2 jmc891205 2020-06-07 20:00:55 +08:00 via iPhone ![]() 学习了 差点因为烂标题错过一篇好文章 |
3 sarvatathagata 2020-06-07 20:00:55 +08:00 这东西编译器稍微优化优化不就完全不管用了吗 |
![]() | 4 msg7086 2020-06-07 20:01:01 +08:00 都写了 safe 了,防止侧信道攻击当然要完整对比完了。 |
![]() | 5 msg7086 2020-06-07 20:03:51 +08:00 ![]() @sarvatathagata 按位或还是挺难优化的,要消除运算量必然要加入分支,而现代处理器上跑分支并不见得更快,所以很大可能编译器不会去尝试这些不会提速的优化。 |
![]() | 6 murmur 2020-06-07 20:07:07 +08:00 大概原理我都懂,不过现在一般都是 hash 存数据库,不代表说改一位时间长就代表那一位是对的 而且都侦测电磁信号了,拿着刀夹脖子逼你说出密码不是更好么 |
7 lpts007 2020-06-07 20:13:11 +08:00 via Android 第一次接触,是通过返回时间判断吗,这也太理论了吧? 1 毫秒的区别也不会有吧,干扰因素那么多,整个返回时间根本不是正相关吧 |
![]() | 8 Ultraman 2020-06-07 20:14:39 +08:00 via Android 同问 1L 的问题,或者说长度不重要吗? |
![]() | 9 jiejiss 2020-06-07 20:38:31 +08:00 @xiangyuecn #1 是因为语言不同吧,原文写的是 Scala 语言的,字符串的 length 是属性不是方法,不用在调用时计算 我不太懂 Scala,如果 Scala 是把 length 给搞成 getter 了那还是不行 |
11 tl3shi OP 看来 V 站的都是大神~ NPE 被省去了哈。JDK 中是有的。 ```java public static boolean isEqual(byte[] digesta, byte[] digestb) { if (digesta == digestb) return true; if (digesta == null || digestb == null) { return false; } if (digesta.length != digestb.length) { return false; } int result = 0; for (int i = 0; i < digesta.length; i++) { result |= digesta[i] ^ digestb[i]; } return result == 0; } ``` |