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

一口Linux 2021-08-23 11:50


点击上方蓝色字体,关注我 ——

一个在阿里云打工的清华学渣!


抱歉用这种标题吸引你点进来了,不过你不妨看完,看看能否让你有所收获。(有收获,请评论区留个言,没收获,下周末我直播吃**,哈哈,这你也信

补充说明:微信公众号改版,对各个号主影响还挺大的。目前从后台数据来看,对我影响不大,因为我这反正都是小号阅读量本身就少的可怜,真相了,(刚从交流群学会的表情)。

先直接上代码:

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
}

我们常常讲性能优化,从效率角度上讲,难道不是应该只要中途发现某一位的结果不同了(即为1)就可以立即返回两个字符串不相等了吗?(如上所示)。

这其中肯定有……

再再细想一下呢?

结合方法名称 safeEquals 可能知道些眉目,与安全有关。

本文开篇的代码来自playframewok 里用来验证cookie(session)中的数据是否合法(包含签名的验证),也是石头写这篇文章的由来。

以前知道通过延迟计算等手段来提高效率的手段,但这种已经算出结果却延迟返回的,还是头一回!

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

看注释知道了,目的是为了用常量时间复杂度进行比较。

但这个计算过程耗费的时间不是常量有啥风险?(脑海里响起了背景音乐:“小朋友,你是否有很多问号?”)

真相大白

再深入探索和了解了一下,原来这么做是为了防止计时攻击(Timing Attack)。(也有人翻译成时序攻击

计时攻击(Timing Attack)

计时攻击是边信道攻击(或称"侧信道攻击", Side Channel Attack, 简称SCA) 的一种,边信道攻击是一种针对软件或硬件设计缺陷,走“歪门邪道”的一种攻击方式。

这种攻击方式是通过功耗、时序、电磁泄漏等方式达到破解目的。在很多物理隔绝的环境中,往往也能出奇制胜,这类新型攻击的有效性远高于传统的密码分析的数学方法(某百科上说的)。

这种手段可以让调用 safeEquals("abcdefghijklmn", "xbcdefghijklmn") (只有首位不相同)和调用 safeEquals("abcdefghijklmn", "abcdefghijklmn") (两个完全相同的字符串)的所耗费的时间一样。防止通过大量的改变输入并通过统计运行时间来暴力破解出要比较的字符串。

举个🌰,如果用之前说的“高效”的方式来实现的话。假设某个用户设置了密码为 password,通过从a到z(实际范围可能更广)不断枚举第一位,最终统计发现 p0000000 的运行时间比其他从任意a~z的都长(因为要到第二位才能发现不同,其他非 p 开头的字符串第一位不同就直接返回了),这样就能猜测出用户密码的第一位很可能是p了,然后再不断一位一位迭代下去最终破解出用户的密码。

当然,以上是从理论角度分析,确实容易理解。但实际上好像通过统计运行时间总感觉不太靠谱,这个运行时间对环境太敏感了,比如网络,内存,CPU负载等等都会影响。

但安全问题感觉更像是 “宁可信其有,不可信其无”。为了防止(特别是与签名/密码验证等相关的操作)被 timing attack,目前各大语言都提供了相应的安全比较函数。各种软件系统(例如 OpenSSL)、框架(例如 Play)的实现也都采用了这种方式。

例如 “世界上最好的编程语言”(粉丝较少,评论区应该打不起架来)—— php中的:

// 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 去实现,后续的版本还会通过打补丁的方式去修复这样的安全隐患。

例如 JDK 1.6.0_17 中的Release Notes[1]中就提到了MessageDigest.isEqual 中的bug的修复,如下图所示:

MessageDigest timing attack vulnerabilities

大家可以看看这次变更的的详细信息openjdk中的 bug fix diff[2]为:

MessageDigest.isEqual计时攻击

Timing Attack 真的可行吗?

我觉得各大语言的 API 都用这种实现,肯定还是有道理的,理论上应该可以被利用的。这不,学术界的这篇论文就宣称用这种计时攻击的方法破解了 OpenSSL 0.9.7 的RSA加密算法了。关于 RSA 算法的介绍可以看看之前本人写的这篇文章。

这篇Remote Timing Attacks are Practical[3] 论文中指出(我大致翻译下摘要,感兴趣的同学可以通过文末链接去看原文):

计时攻击往往用于攻击一些性能较弱的计算设备,例如一些智能卡。我们通过实验发现,也能用于攻击普通的软件系统。本文通过实验证明,通过这种计时攻击方式能够攻破一个基于 OpenSSL 的 web 服务器的私钥。结果证明计时攻击用于进行网络攻击在实践中可行的,因此各大安全系统需要抵御这种风险。

最后,本人毕竟不是专研安全方向,以上描述是基于本人的理解,如果有不对的地方,还请大家留言指出来,感谢。

补充说明2:感谢正在阅读文章的你,让我还有动力继续坚持原创。

本人发文不多,但希望写的文章能达到的目的是:占用你的阅读时间,就尽量能够让你有所收获。

如果你觉得我的文章有所帮助,还请你帮忙转发分享,另外请别忘了点击公众号右上角加个星标,好让你别错过后续的精彩文章(微信现在改版了,或许我发的文章都不能推送到你那了)。

原创真心不易,希望你能帮我个小忙呗,如果本文内容你觉得有所启发,有所收获,请帮忙点个“在看”呗,或者转发分享让更多的小伙伴看到。 


一个由跨平台产生的浮点数bug | 有你意想不到的结果


实战!我用“Wireshark”让你看见 TCP


震惊! 阿里的程序员也不过如此,竟被一个简单的 SQL 查询难住


面了 7轮Google,最终还是逃不脱被挂的命运


欢迎关注,共同成长,共同进步!

参考资料

[1] Release Notes: http://www.oracle.com/technetwork/java/javase/6u17-141447.html
[2] openjdk中的 bug fix diff: http://hg.openjdk.java.net/jdk6/jdk6/jdk/rev/562da0baf70b
[3] Remote Timing Attacks are Practical: http://crypto.stanford.edu/~dabo/papers/ssl-timing.pdf
一口Linux 写点代码,写点人生!
评论
  • 在物联网领域中,无线射频技术作为设备间通信的核心手段,已深度渗透工业自动化、智慧城市及智能家居等多元场景。然而,随着物联网设备接入规模的不断扩大,如何降低运维成本,提升通信数据的传输速度和响应时间,实现更广泛、更稳定的覆盖已成为当前亟待解决的系统性难题。SoC无线收发模块-RFM25A12在此背景下,华普微创新推出了一款高性能、远距离与高性价比的Sub-GHz无线SoC收发模块RFM25A12,旨在提升射频性能以满足行业中日益增长与复杂的设备互联需求。值得一提的是,RFM25A12还支持Wi-S
    华普微HOPERF 2025-02-28 09:06 101浏览
  • 应用趋势与客户需求,AI PC的未来展望随着人工智能(AI)技术的日益成熟,AI PC(人工智能个人电脑)逐渐成为消费者和企业工作中的重要工具。这类产品集成了最新的AI处理器,如NPU、CPU和GPU,并具备许多智能化功能,为用户带来更高效且直观的操作体验。AI PC的目标是提升工作和日常生活的效率,通过深度学习与自然语言处理等技术,实现更流畅的多任务处理、实时翻译、语音助手、图像生成等功能,满足现代用户对生产力和娱乐的双重需求。随着各行各业对数字转型需求的增长,AI PC也开始在各个领域中显示
    百佳泰测试实验室 2025-02-27 14:08 238浏览
  • 1,微软下载免费Visual Studio Code2,安装C/C++插件,如果无法直接点击下载, 可以选择手动install from VSIX:ms-vscode.cpptools-1.23.6@win32-x64.vsix3,安装C/C++编译器MniGW (MinGW在 Windows 环境下提供类似于 Unix/Linux 环境下的开发工具,使开发者能够轻松地在 Windows 上编写和编译 C、C++ 等程序.)4,C/C++插件扩展设置中添加Include Path 5,
    黎查 2025-02-28 14:39 100浏览
  • 更多生命体征指标风靡的背后都只有一个原因:更多人将健康排在人生第一顺位!“AGEs,也就是晚期糖基化终末产物,英文名Advanced Glycation End-products,是存在于我们体内的一种代谢产物” 艾迈斯欧司朗亚太区健康监测高级市场经理王亚琴说道,“相信业内的朋友都会有关注,最近该指标的热度很高,它可以用来评估人的生活方式是否健康。”据悉,AGEs是可穿戴健康监测领域的一个“萌新”指标,近来备受关注。如果站在学术角度来理解它,那么AGEs是在非酶促条件下,蛋白质、氨基酸
    艾迈斯欧司朗 2025-02-27 14:50 363浏览
  • 美国加州CEC能效跟DOE能效有什么区别?CEC/DOE是什么关系?美国加州CEC能效跟DOE能效有什么区别?CEC/DOE是什么关系?‌美国加州CEC能效认证与美国DOE能效认证在多个方面存在显著差异‌。认证范围和适用地区‌CEC能效认证‌:仅适用于在加利福尼亚州销售的电器产品。CEC认证的范围包括制冷设备、房间空调、中央空调、便携式空调、加热器、热水器、游泳池加热器、卫浴配件、光源、应急灯具、交通信号模块、灯具、洗碗机、洗衣机、干衣机、烹饪器具、电机和压缩机、变压器、外置电源、消费类电子设备
    张工nx808593 2025-02-27 18:04 92浏览
  •           近日受某专业机构邀请,参加了官方举办的《广东省科技创新条例》宣讲会。在与会之前,作为一名技术工作者一直认为技术的法例都是保密和侵权方面的,而潜意识中感觉法律有束缚创新工作的进行可能。通过一个上午学习新法,对广东省的科技创新有了新的认识。广东是改革的前沿阵地,是科技创新的沃土,企业是创新的主要个体。《广东省科技创新条例》是广东省为促进科技创新、推动高质量发展而制定的地方性法规,主要内容包括: 总则:明确立法目
    广州铁金刚 2025-02-28 10:14 90浏览
  • 一、VSM的基本原理震动样品磁强计(Vibrating Sample Magnetometer,简称VSM)是一种灵敏且高效的磁性测量仪器。其基本工作原理是利用震动样品在探测线圈中引起的变化磁场来产生感应电压,这个感应电压与样品的磁矩成正比。因此,通过测量这个感应电压,我们就能够精确地确定样品的磁矩。在VSM中,被测量的样品通常被固定在一个震动头上,并以一定的频率和振幅震动。这种震动在探测线圈中引起了变化的磁通量,从而产生了一个交流电信号。这个信号的幅度和样品的磁矩有着直接的关系。因此,通过仔细
    锦正茂科技 2025-02-28 13:30 78浏览
  • RGB灯光无法同步?细致的动态光效设定反而成为产品客诉来源!随着科技的进步和消费者需求变化,电脑接口设备单一功能性已无法满足市场需求,因此在产品上增加「动态光效」的形式便应运而生,藉此吸引消费者目光。这种RGB灯光效果,不仅能增强电脑周边产品的视觉吸引力,还能为用户提供个性化的体验,展现独特自我风格。如今,笔记本电脑、键盘、鼠标、鼠标垫、耳机、显示器等多种电脑接口设备多数已配备动态光效。这些设备的灯光效果会随着音乐节奏、游戏情节或使用者的设置而变化。想象一个画面,当一名游戏玩家,按下电源开关,整
    百佳泰测试实验室 2025-02-27 14:15 132浏览
  • 在2024年的科技征程中,具身智能的发展已成为全球关注的焦点。从实验室到现实应用,这一领域正以前所未有的速度推进,改写着人类与机器的互动边界。这一年,我们见证了具身智能技术的突破与变革,它不仅落地各行各业,带来新的机遇,更在深刻影响着我们的生活方式和思维方式。随着相关技术的飞速发展,具身智能不再仅仅是一个技术概念,更像是一把神奇的钥匙。身后的众多行业,无论愿意与否,都像是被卷入一场伟大变革浪潮中的船只,注定要被这股汹涌的力量重塑航向。01为什么是具身智能?为什么在中国?最近,中国具身智能行业的进
    艾迈斯欧司朗 2025-02-28 15:45 160浏览
  •         近日,广电计量在聚焦离子束(FIB)领域编写的专业著作《聚焦离子束:失效分析》正式出版,填补了国内聚焦离子束领域实践性专业书籍的空白,为该领域的技术发展与知识传播提供了重要助力。         随着芯片技术不断发展,芯片的集成度越来越高,结构也日益复杂。这使得传统的失效分析方法面临巨大挑战。FIB技术的出现,为芯片失效分析带来了新的解决方案。它能够在纳米尺度上对芯片进行精确加工和分析。当芯
    广电计量 2025-02-28 09:15 89浏览
  • 振动样品磁强计是一种用于测量材料磁性的精密仪器,广泛应用于科研、工业检测等领域。然而,其测量准确度会受到多种因素的影响,下面我们将逐一分析这些因素。一、温度因素温度是影响振动样品磁强计测量准确度的重要因素之一。随着温度的变化,材料的磁性也会发生变化,从而影响测量结果的准确性。因此,在进行磁性测量时,应确保恒温环境,以减少温度波动对测量结果的影响。二、样品制备样品的制备过程同样会影响振动样品磁强计的测量准确度。样品的形状、尺寸和表面处理等因素都会对测量结果产生影响。为了确保测量准确度,应严格按照规
    锦正茂科技 2025-02-28 14:05 117浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦