公众号后台回复“面试”,获取精品学习资料

扫描下方海报了解专栏详情

本文来源投稿:程序员石头
《Java工程师面试突击(第3季)》重磅升级,由原来的70讲增至160讲,内容扩充一倍多,升级部分内容请参见文末
先直接上代码:
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;
}
Scala)翻译成
Java的,
Scala版本(最开始吸引程序猿石头注意力的代码)如下:
def safeEqual(a: String, b: String) = {
if (a.length != b.length) {
false
} else {
var equal = 0
for (i <- Array.range(0, a.length)) {
equal |= a(i) ^ b(i)
}
equal == 0
}
}
1^1=0, 1^0=1, 0^0=0,来比较每一位,如果每一位都相等的话,两个字符串肯定相等,最后存储累计异或值的变量
equal必定为 0,否则为 1。
再细想一下呢?
for (i <- Array.range(0, a.length)) {
if (a(i) ^ b(i) != 0) // or a(i) != b[i]
return false
}

再再细想一下呢?
safeEquals可能知道些眉目,与安全有关。
本文开篇的代码来自playframewok 里用来验证cookie(session)中的数据是否合法(包含签名的验证),也是石头写这篇文章的由来。
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;
}

真相大白

计时攻击(Timing Attack)
safeEquals("abcdefghijklmn", "xbcdefghijklmn")(只有首位不相同)和调用
safeEquals("abcdefghijklmn", "abcdefghijklmn")(两个完全相同的字符串)的所耗费的时间一样。防止通过大量的改变输入并通过统计运行时间来暴力破解出要比较的字符串。
password,通过从a到z(实际范围可能更广)不断枚举第一位,最终统计发现
p0000000的运行时间比其他从任意
a~z的都长(因为要到第二位才能发现不同,其他非
p开头的字符串第一位不同就直接返回了),这样就能猜测出用户密码的第一位很可能是
p了,然后再不断一位一位迭代下去最终破解出用户的密码。
// Compares two strings using the same time whether they're equal or not.
// This function should be used to mitigate timing attacks;
// for instance, when testing crypt() password hashes.
bool hash_equals ( string $known_string , string $user_string )
//This function is safe against timing attacks.
boolean password_verify ( string $password , string $hash )
^)并用或(
|)保存,最后通过判断结果是否为 0 来确定两个字符串是否相等。
safeEquals去实现,后续的版本还会通过打补丁的方式去修复这样的安全隐患。
MessageDigest.isEqual中的bug的修复,如下图所示:


Timing Attack 真的可行吗?
OpenSSL 0.9.7的RSA加密算法了。关于 RSA 算法的介绍可以看看之前本人写的这篇文章。
补充说明2:感谢正在阅读文章的你,让我还有动力继续坚持原创。 本人发文不多,但希望写的文章能达到的目的是:占用你的阅读时间,就尽量能够让你有所收获。 如果你觉得我的文章有所帮助,还请你帮忙转发分享,另外请别忘了点击公众号右上角加个星标,好让你别错过后续的精彩文章(微信现在改版了,或许我发的文章都不能推送到你那了)。
END
《Java工程师面试突击第三季》加餐部分大纲:(注:1-66讲的大纲请扫描文末二维码,在课程详情页获取)



详细的课程内容,大家可以扫描下方二维码了解:

文章转载自石杉的架构笔记,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




