【问题标题】:Picking a check digit algorithm选择校验位算法
【发布时间】:2021-07-30 14:27:42
【问题描述】:

我正在生成随机 OTP 样式的字符串,作为短期标识符来链接两个原本不相关的系统(它们在每一端都有身份验证)。这些需要用户读取并重新输入,因此为了降低错误率并减少伪造的机会,我想将其中一个数字作为校验位。目前我的随机字符串符合模式(删除IO以避免混淆):

^[ABCDEFGHJKLMNPQRSTUVWXYZ][0-9]{4}$

我想为支票附加一位额外的十进制数字。到目前为止,我已经将它实现为一个 BLAKE2 哈希(来自 libsodium),它被转换为十进制并截断为 1 个字符。这仅给出了校验位的 10 种可能性,这并不多。我的主要目标是检测输入中的单个字符错误。

这种方法是可行的,但似乎一个数字不足以检测单个字符错误,并且未检测到的错误很容易找到,例如K37705K36705 都被认为是有效的。

我没有在这个 OTP 中加入时间值;相反,它完全是随机的,我依靠记录最近为每个用户生成的 OTP,这些 OTP 会定期删除,并且我正在通过速率和尝试计数限制来减少暴力破解的机会。

我猜BLAKE2在这里不是一个好的选择,但鉴于结果只有10种可能性,我不知道其他人会更好。使用什么算法/方法更好?

【问题讨论】:

  • 我认为这不是算法问题。您根本不可能将检测任何这些字符的任意变化所需的信息量编码为单个数字。可能有一些数学可以证明这一点。如果它不是关于任意更改而是关于可能的更改(即 P 与 R、E 与 F 但不是 A 与 Z),它可能会有所不同。
  • 与其他校验位相同顺序的校验位可能会更好。一个建议是使用与符号顺序匹配的准群的 Damm 算法。它用于捕获在这种情况下常见的错误,例如两个相邻符号的换位或不正确的符号。
  • 虽然与您尝试做的不完全相同,但比特币使用称为 Base58Chcek 的东西来检测比特币地址中的拼写错误并避免出现类似字符。它的工作原理是基本上将有效负载的双 sha256 的最后 4 个字节附加到有效负载,然后对结果进行 base58 编码(以消除看起来相似的字符)。请参阅bitcoin.stackexchange.com/questions/32353/… 了解更多信息。
  • 我投票支持迁移到 StackOverflow,因为检测错别字不是安全问题。如果这是一种安全机制,那么您需要以某种方式添加攻击者不知道的密钥;比如校验和需要是(截断的)公钥签名或密钥 MAC。
  • Luhn code 是一种常见但不完善的检查人工转录错误的方法。在信息论意义上,还有其他更优化的方法,并且还有最佳纠错码。加密散列函数在这里不适合。但是,您的用例不会从错误检测中受益。 OTP 代码要么在数据库中,要么不在。您可以选择代码长度、有效期和尝试次数,以保持足够低的猜测概率。

标签: hash one-time-password checksum


【解决方案1】:

框架挑战

为什么需要校验位?

它不会提高安全性,而且对于大多数人来说,五位数字微不足道。检查是否是服务器端,如果错误则返回错误消息。

正常的 TOTP 令牌通常是 6 位数字,并且像谷歌这样的行为者已经确定人们通常能够正确地得到它们。

【讨论】:

  • 我不是在寻求更高的安全性,而是更高的可靠性。据用户所知,这只是另一个数字。我认为尽早发现转录问题会更有用,甚至可能在 API 查找之前“免费”
猜你喜欢
  • 1970-01-01
  • 2017-02-23
  • 2016-01-31
  • 2010-11-09
  • 1970-01-01
  • 1970-01-01
  • 2018-05-20
  • 1970-01-01
  • 2021-05-11
相关资源
最近更新 更多