V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
tl3shi
V2EX  ›  程序员

这 10 行比较字符串相等的代码给我整懵了,不信你也来看看

  •  
  •   tl3shi · 2020-06-07 19:43:26 +08:00 · 3778 次点击
    这是一个创建于 1637 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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;
    }
    

    从效率角度上讲,难道不是应该只要中途发现某一位的结果不同了就可以立即返回两个字符串不相等了吗?

    这里有解密,欢迎关注讨论。

    第 1 条附言  ·  2020-06-07 21:03:27 +08:00

    看来 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;
    }
    

    欢迎大佬关注公众号,给予指导。

    18 条回复    2020-06-08 10:28:02 +08:00
    xiangyuecn
        1
    xiangyuecn  
       2020-06-07 20:00:45 +08:00
    如果真需要保护不被时序攻击,理论上这坨代码第一行就会泄露被保密的字符串长度。另外欢迎体验 NullPointerException
    jmc891205
        2
    jmc891205  
       2020-06-07 20:00:55 +08:00 via iPhone   ❤️ 1
    学习了
    差点因为烂标题错过一篇好文章
    sarvatathagata
        3
    sarvatathagata  
       2020-06-07 20:00:55 +08:00
    这东西编译器稍微优化优化不就完全不管用了吗
    msg7086
        4
    msg7086  
       2020-06-07 20:01:01 +08:00
    都写了 safe 了,防止侧信道攻击当然要完整对比完了。
    msg7086
        5
    msg7086  
       2020-06-07 20:03:51 +08:00   ❤️ 2
    @sarvatathagata 按位或还是挺难优化的,要消除运算量必然要加入分支,而现代处理器上跑分支并不见得更快,所以很大可能编译器不会去尝试这些不会提速的优化。
    murmur
        6
    murmur  
       2020-06-07 20:07:07 +08:00
    大概原理我都懂,不过现在一般都是 hash 存数据库,不代表说改一位时间长就代表那一位是对的
    而且都侦测电磁信号了,拿着刀夹脖子逼你说出密码不是更好么
    lpts007
        7
    lpts007  
       2020-06-07 20:13:11 +08:00 via Android
    第一次接触,是通过返回时间判断吗,这也太理论了吧? 1 毫秒的区别也不会有吧,干扰因素那么多,整个返回时间根本不是正相关吧
    Ultraman
        8
    Ultraman  
       2020-06-07 20:14:39 +08:00 via Android
    同问 1L 的问题,或者说长度不重要吗?
    jiejiss
        9
    jiejiss  
       2020-06-07 20:38:31 +08:00
    @xiangyuecn #1 是因为语言不同吧,原文写的是 Scala 语言的,字符串的 length 是属性不是方法,不用在调用时计算

    我不太懂 Scala,如果 Scala 是把 length 给搞成 getter 了那还是不行
    wizardoz
        10
    wizardoz  
       2020-06-07 20:56:01 +08:00   ❤️ 1
    @Ultraman 长度真不重要,长度信息之于密码就像端口之于 ssh 。
    tl3shi
        11
    tl3shi  
    OP
       2020-06-07 21:01:39 +08:00
    看来 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;
    }
    ```
    yukiloh
        12
    yukiloh  
       2020-06-07 21:06:38 +08:00
    我抓包的时候发现,一些网站传到后台的密码 1 不是明文,2 会加满位数
    这个题目挺有趣的,但是我觉得不实用
    tl3shi
        13
    tl3shi  
    OP
       2020-06-07 21:40:10 +08:00
    @jmc891205 这年头难啊,不“标题党”都没人点进来。然后点进来吧,又被吐槽标题党了。
    zlfoxy
        15
    zlfoxy  
       2020-06-07 22:58:50 +08:00
    有点儿基于时间的 sql 盲注的意思。
    xuanbg
        16
    xuanbg  
       2020-06-08 02:42:43 +08:00
    比较个字符串怎么实现时序攻击?要攻击的话拦截入参就啥都知道了,还要时序攻击做咩?
    killergun
        17
    killergun  
       2020-06-08 10:05:33 +08:00
    占楼 学习
    KaynW
        18
    KaynW  
       2020-06-08 10:28:02 +08:00
    理解思想就好、实际应用这个还没用到过
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1012 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 23:09 · PVG 07:09 · LAX 15:09 · JFK 18:09
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.