使用按位异或进行Java字符串比较
我在一个产品的代码中遇到了下面的代码片段。它使用按位异或进行字符串比较。这比使用按位异或进行Java字符串比较,java,bitwise-operators,bitwise-xor,Java,Bitwise Operators,Bitwise Xor,我在一个产品的代码中遇到了下面的代码片段。它使用按位异或进行字符串比较。这比String.equals(objecto)方法好吗?作者试图在这里实现什么 private static boolean compareSecure(String a, String b) { if ((a == null) || (b == null)) { return (a == null) && (b == null); } int len = a.len
String.equals(objecto)
方法好吗?作者试图在这里实现什么
private static boolean compareSecure(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;
}
private静态布尔比较安全(字符串a、字符串b)
{
如果((a==null)| |(b==null)){
返回(a==null)和&(b==null);
}
int len=a.length();
如果(len!=b.length()){
返回false;
}
如果(len==0){
返回true;
}
整数位=0;
对于(int i=0;i
对于上下文,被等同的字符串是身份验证令牌。这是字符串比较函数的常见实现,不受定时攻击的影响 简而言之,每次比较字符串时都要比较所有字符,即使您发现其中任何一个字符都不相等。在“标准”实现中,您只需中断第一个差异并返回false 这是不安全的,因为它会泄露有关比较字符串的信息。特别是,如果左侧字符串是您想要保留的秘密(例如密码),而右侧字符串是用户提供的,则不安全的方法允许黑客通过反复尝试不同的字符串并测量响应时间,相对轻松地发现您的密码。 两个字符串中相同的字符越多,“不安全”函数比较它们所需的时间就越多 例如,使用标准方法比较“1234567890”和“0987654321”将导致仅对第一个字符进行一次比较,并返回false,因为1=0另一方面,将“1234567890”与“1098765432”进行比较会导致执行两个比较操作,因为第一个操作相等,所以必须比较第二个操作以发现它们不同。这将花费更多的时间,而且是可以测量的,即使在我们谈论远程通话时也是如此 如果您使用N个不同的字符串进行N次攻击,每个字符串以不同的字符开头,您应该会看到其中一次攻击的结果比其他攻击的结果多了几分之一毫秒。这意味着第一个字符是相同的,因此函数需要花费更多的时间来比较第二个字符。冲洗并重复字符串中的每个位置,你可以比暴力更快地破解秘密数量级 防止此类攻击是此类实施的重点
编辑:正如MarkRotterveel在中认真指出的,此实现仍然容易受到旨在显示字符串长度的计时攻击。尽管如此,在许多情况下这并不是一个问题(要么你不在乎攻击者知道长度,要么你处理的数据是标准的,任何人都可以知道长度,例如某种已知长度的散列)这是比较字符串的一种较慢的方法,因为它必须始终比较所有字符。它不比
String.equals()更安全。
@FredK Not true。重新阅读第一条if
语句。这实际上可能是对String.equals()
的唯一改进:它是空安全的,可能这就是“安全”部分。在Java 7+中,您可以使用相同的空安全行为,这比标准的equals
@Zong不存在冲突问题更不安全。它使用的是位|=
,而不是位^=
。如果任意两个字符不相等,将设置一个或多个位,并将一直保持设置直到结束。此比较旨在不受字符串内容的太多影响,以防止定时攻击(正常字符串比较泄漏有关相等前缀的长度的信息)。但问题中的代码仍然容易受到计时攻击,从而无法确定字符串的长度。