Github的保护Webhook页面说:
不建议使用普通的
==
运算符。像secure_compare
这样的方法执行“常量时间”字符串比较,使其免受针对常规等号运算符的某些时序攻击。
比较密码时,我使用bcrypt.compare('string', 'computed hash')
。
什么是“安全比较”,我是否可以使用Node中的标准crypto
库执行此操作?
Github的保护Webhook页面说:
不建议使用普通的
==
运算符。像secure_compare
这样的方法执行“常量时间”字符串比较,使其免受针对常规等号运算符的某些时序攻击。
比较密码时,我使用bcrypt.compare('string', 'computed hash')
。
什么是“安全比较”,我是否可以使用Node中的标准crypto
库执行此操作?
crypto.timingSafeEqual(a, b)
。const isEqual = crypto.timingSafeEqual( Buffer.from(a), Buffer.from(b) );
- Freewalkera
和b
的字节长度不同,timingSafeEqual()
会抛出异常。 - mamacdontimingSafeEqual
方面真的搞砸了。我只想要一个时间安全的函数来比较两个字符串并返回true或false,但他们却给了我们这个东西,如果字符串不是最基本的相等,就会抛出异常,并需要“ArrayBufferViews”。我不喜欢自己编写加密函数,但我想我会为这个特殊情况做个例外。 - Kaiser Keister编辑:即使没有这样做也绝对没有安全风险,但 bcrypt.compare() 函数已经 被编程以抵御时间攻击。
aaaaaaaaab
,你将其与测试字符串b
、bbbbbbbbbb
和aaaaaaaaaa
进行比较。
经典比较对于b
会立即返回false,因为长度不匹配。
对于bbbbbbbbbb
,由于第一个字符不匹配,也会几乎立即返回false。
对于aaaaaaaaaa
,也是false,但不是那么立即(需要更多微秒或纳秒)。
因此,比较所需的时间越长,测试字符串与秘密越接近。
攻击者可以尝试通过发送许多不同长度的测试字符串并找到最小长度来猜测长度。
然后,他可以继续以类似的方式找到第一个字符,依此类推,直到找到秘密。// (Javascript)
function equals(test, secret) {
// String comparison that does not leak timing information
let diffs = test.length !== secret.length ? 1 : 0;
for (let i = 0; i < test.length; i++) if (test[i] !== secret[i]) diffs++;
return diffs == 0;
}
timingSafeEqual(a, b)
函数,该函数主要用于哈希输入,因为正如评论中所说,它期望输入具有相同的长度。
如果在没有哈希的情况下使用此函数,可能会导致问题,因为当输入长度不匹配时,您不能只返回false
,这样会泄露有关秘密长度的信息。