Java字符串安全比较方法

先贴java String类源码:

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

这是字符串比较函数的常见实现,不受定时攻击的影响。

简而言之,这个想法是每次比较字符串时比较所有字符,即使您发现其中任何一个字符都不相等。在“标准”实现中,您只需中断第一个差异并返回false。

这是不安全的,因为它会泄露有关比较字符串的信息。具体来说,如果左边的字符串是你想保留的秘密(例如密码),而右边的字符串是用户提供的,那么不安全的方法可以让黑客通过反复尝试不同的字符串和测量响应时间,相对轻松地发现你的密码。两个字符串中相同的字符越多,“unsecure”函数就越需要比较它们。

例如,使用标准方法比较“1234567890”和“0987654321”将导致仅对第一个字符进行一次比较并返回false,因为1=0另一方面,比较“1234567890”和“1098765432”,将导致执行两个比较操作,因为第一个操作相等,所以必须比较第二个操作才能发现它们不同。这将需要更多的时间,而且是可以测量的,即使在我们谈论远程通话时也是如此。

如果您使用N个不同的字符串进行N次攻击,每个字符串都以不同的字符开头,您应该会看到其中一个结果比其他结果多花费了几分之一毫秒。这意味着第一个字符是相同的,因此函数需要花费更多的时间来比较第二个字符。冲洗和重复在字符串中的每个位置,你可以破解的秘密数量级快于暴力。

如何防止此类攻击呢?直接上代码

private static boolean SecureEquals(String a, String b)
{
    if ((a == null) || (b == null)) {
        return (a == null) && (b == null);
    }
    int len = a.length();
    if (len != b.length()) {
        return false;
    }
    if (len == 0) {
        return true;
    }
    int bits = 0;
    for (int i = 0; i < len; i++) {
        bits |= a.charAt(i) ^ b.charAt(i);
    }
    return bits == 0;
}

每个位置上做异或运算 再与上次结果做或运算。这样 每次返回时间都是一样的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值