发短信的 2FA 安全码是故意容易记住的吗?

信息安全 多因素
2021-09-07 05:06:59

我的银行账户上有 2FA 设置。当我登录时,我会在手机上收到一个六位数的代码作为我输入网站的 IM。这些代码似乎总是有一种模式。像 111xxx、123321、xx1212 等。

我认为这些代码一目了然很容易记住。是否有一个共同的商业实践/最佳实践要求这些代码有一个模式,使它们更容易记住?

4个回答

我也注意到了这一点,我认为这是人类大脑倾向于将模式应用于随机噪声的结果。当专门尝试记住一串数字时,这似乎更常见。

大约 85% 的六位随机数将至少有一个重复数字,40% 将有一个相邻的重复连续数字。(我很高兴在数学上得到纠正。)

这些密钥是使用标准 TOTP 算法生成的这篇文章总结了这个实现,表明没有任何努力来生成一个令人难忘的数字:

根据 RFC 6238,参考实现如下:

  • 生成一个密钥 K,它是一个任意字节字符串,并与客户端安全地共享它。
  • 同意一个 T0,即开始计算时间步长的 Unix 时间,以及一个间隔 TI,它将用于计算计数器 C 的值(默认为 Unix 纪元为 T0,30 秒为 TI)
  • 同意加密哈希方法(默认为 SHA-1)
  • 同意令牌长度,N(默认为 6)

尽管 RFC 6238 允许使用不同的参数,但验证器应用程序的 Google 实现不支持与默认值不同的 T0、TI 值、哈希方法和令牌长度。它还期望根据 RFC 3548 以 base-32 编码输入(或以 QR 码提供)K 密钥。

一旦参数达成一致,令牌生成如下:

  1. 将 C 计算为在 T0 之后经过 TI 的次数。
  2. 以 C 作为消息,K 作为密钥计算 HMAC 哈希 H(HMAC 算法在上一节中定义,但大多数密码库也支持它)。K 应该按原样传递,C 应该作为原始 64 位无符号整数传递。
  3. 取 H 的最低 4 个有效位并将其用作偏移量 O。
  4. 从 H 中取出 4 个字节,从 O 字节 MSB 开始,丢弃最高有效位并将其余位存储为(无符号)32 位整数 I。
  5. 记号是以 10 为基数的 I 的最低 N 位。如果结果的位数少于 N,则从左侧用零填充。

服务器和客户端都计算令牌,然后服务器检查客户端提供的令牌是否与本地生成的令牌匹配。一些服务器允许在当前时间之前或之后生成的代码,以解决轻微的时钟偏差、网络延迟和用户延迟。

在我的手机上,我收到了来自不同公司的大约 90 个验证码。其中 62 个是 6 位数长。这是每个数字的计数:

可能略微偏向 1,8 和 9?几乎可以肯定只是数据中的噪声(62 是一个小样本)。

两位数呢?

在此处输入图像描述 第一张图只是两位数边界上的两位数(即 AABBCC)——所以我们预计每对在 186 个可能的数字位置中出现大约 1.86 次。第二个是任何位置(即 XXX99X 计为两位数)。我们预计在 310 个展示位置中,每对大约是 3.1 倍。

似乎没有任何明显的偏差,两位数比非两位数多得多 - 两位数以橙色显示。在后一个数据中,我们预计大约有 31 个两位数,我们得到 27 个。这似乎是合理的。

当然,这并不排除其他“非随机”模式——但老实说,人类可能正在寻找模式——看看这些数字,全部来自我的 2FA 应用程序:365 595、111 216、566 272, 468 694、191 574、833 043。

我希望这只是你的随机机会。如果有一个模式,它会削弱拥有第二个代码的全部意义。

不,它们不应该是故意容易记住的,并且没有通用的商业案例,除非他们有反馈说他们的用户在输入 6 个数字时遇到了困难。那么有人可能做了一些愚蠢的事情,但我真的希望不会。