为什么 Google 会削弱 2FA Google Authenticator PAM 模块?

信息安全 密码 验证 遵守 多因素 谷歌
2021-08-24 18:51:40

如果您为 Google Apps 启用 2FA,则共享密钥为 160 位。google_authenticator另一方面,PAM 模块似乎使用 80 位作为共享密钥

根据RFC 4226

R6 - 算法必须使用强共享密钥。共享密钥的长度
必须至少为 128 位。本文档
推荐 160 位的共享密钥长度。

注意“必须”而不是“应该”。这使得 Google Authenticator 不合规。

这样做的理由是什么?

2个回答

此代码的初始提交已包含“80 位”密钥长度。后来没有改过。

现在让我们更批判地分析事情。HOTP 在RFC 4226中指定。身份验证使用“共享密钥”,这就是我们所说的值。RFC 4226 对此有何评论?本质上,第 4 节有一个要求

R6 - The algorithm MUST use a strong shared secret.  The length of
the shared secret MUST be at least 128 bits.  This document
RECOMMENDs a shared secret length of 160 bits.

然后第 7.5 节详细解释了生成共享密钥的各种方法。

现在google_authenticator代码生成一个 80 位共享密钥,/dev/urandom然后继续使用Base32对该密钥进行编码:这种编码将每组 5 位映射到一个可打印字符。因此,生成的字符串由 16 个字符组成,这些字符“按原样”写入文件中,使用 ASCII 编码,这意味着在文件中共享密钥的长度为... 16个字节,即 128 位。因此,最初的混淆可能来自于:存储的内容具有可以看出的长度,在某种程度上符合 RFC 4226 的要求 R6。

当然,RFC第 5.1 节中通过将其称为“ K ”来讨论“共享密钥” ,然后继续将其用作 HMAC 的密钥(第 5.3 节,步骤 1)。使用命令行工具生成的共享密钥,进入 HMAC 的实际上是一个 80 位序列,而不是 128 位,即使这 80 位在存储时恰好被编码为 128 位(但它们被解码回 80位使用)。因此,这个 80 位机密不能以合法的方式真正符合 RFC 4226 的要求 R6。但是,“长度”(编码之后或之前)的混淆可以解释.google_authenticatorgoogle_authenticator

但请注意,这仅适用于命令行工具,可用于生成密钥作为初始步骤。其余代码支持更长的秘密值。

(另一种说法是作者想测试他的代码,特别是测试没有二维码的情况,这种情况下,用户必须码,80位的密码更容易打而不是 128 位或 160 位密钥。可能是作者首先使用了一个短密钥来简化开发,后来忘记将其设置回其标称长度。这种事故经常发生。)


很关键吗?带着我的密码学家的帽子,我必须回答:不。一个 80 位的密钥对暴力破解还是相当强的,因为即使有很多 GPU,对 HMAC/SHA-1 的2 79次评估仍然需要相当长的时间(使用 80 位密钥,暴力破解的平均成本)是尝试一半可能的键,即2 79次评估)。事实上,HMAC/SHA-1 被认为是“密码学强”,这意味着最著名的攻击是对密钥的暴力破解。让我们把数字放在上面:

HMAC/SHA-1 使用两个 SHA-1 调用。因此,平均而言,攻击成本是调用 SHA-1 2 80次所涉及的成本。这个页面显示了一个好的 GPU 每秒 25 亿次 SHA-1 调用的基准。如果您正在安装一个破解农场,您通常会使用“中档”GPU,而不是一流的型号,因为这样您将获得更多的每美元功率。假设您使用 100 美元的 GPU,每秒可以执行2 31 SHA-1(这比 20 亿多一点)。以10 亿美元的预算,你可以拥有一千万个这样的 GPU,他们将在平均... 652 天内运行攻击。

当然,1000 万个 GPU 占用了相当多的空间,更重要的是,使用了大量的电力。如果我们假设每个 GPU 可以以 50W 的功率运行(一个相当乐观的数字),那么每次攻击运行所需的功率将略低于 8 TW.h(太瓦时)。我住在加拿大魁北克省,由于巨大的水坝和大量的政府补贴,众所周知,那里的电力非常便宜,导致价格约为每千瓦时 0.05 美元(见价格)。以这个价格,每次攻击将花费大约4 亿美元仅靠电。这不包括制冷价格,因为所有这些能量都将变成热量并且必须消散(在某种程度上,加拿大的冬天会有所帮助)。另外,请注意,所有 GPU 将共同消耗 500 MW,这是一个不谨慎的数量(大约是核电站的一半......)。

这相当于以下内容:在实践中,一个 80 位的密钥就足够强大了如果一个 80 位的密钥保护核导弹的发射代码,我会很紧张;但是,如果战略劝阻受到 Google 的 2FA 的保护,我也会因为……其他原因而感到非常紧张。

所以我们可以说,虽然这个 80 位的秘密是不合规的并且在学术上“有点短”,但它仍然非常强大,并且不要求立即采取激烈的行动。如果代码是固定的,那就太酷了;如果不是这样,世界就不会停止旋转。

就像我在评论中提到的那样,我已经在 Google Authenticator 存储库上打开了一个问题。但是,开发人员尚未对此进行正式回复。看来存储库上的活动相当停滞。

虽然对于为什么 Google 选择 80 位而不是 RFC 推荐的 160 位可能没有很好的解释,但如果这是一个重要问题,有一个非常简单的解决方法。

据我所知,秘密的大小仅在libpam/google-authenticator.c第 39 行定义。

#define SECRET_BITS               80          // Must be divisible by eight

据我所知,将值从 80 更改为 160 有效并且没有任何破坏。如果您真的希望 PAM 模块符合 RFC,这可能是可行的。