我发现每个TOTP实现(甚至是RedHat的FreeOTP)都使用Base32编码/解码来生成秘密。 为什么它不使用Base64,因为Base32使用大约20%的空间而且(主要)唯一的优点是,它更易于人类阅读?无论如何都没有向用户显示它。
虽然实现中的每条评论都说明其实现遵循Collectors.joining(CharSequence)
/ RFC6238,但我无法在RFC文档中找到关于base32的任何内容。
由于通过传输实现数据安全,将它转换为Base32或Base64显然是有意义的,但为什么不使用Base64呢?
答案 0 :(得分:1)
我认为这只是一个历史背景。 最初的某个人选择了Base32,一个工具变得流行,后代使用相同的编码来遵守。
我也看到了很多使用十六进制格式的实现,并且提供的RFC6238中的示例也使用了十六进制格式。
答案 1 :(得分:1)
使用base32的原因是为了避免人为错误。与空间无关。 RFC4226中未提及Base32的原因是,它与私钥,HMAC和令牌生成无关。 Base32仅用于以人类可读的形式将私钥传递给人类。
有兴趣的更多详细信息。
TOTP中的私钥应该是20字节(160位)的秘密。 私钥与HMAC-SHA1一起使用来编码时期计数器。 从生成的160位HMAC中提取令牌。
但是要将此秘密输入到Google身份验证器之类的工具中并不容易。 好的,可以选择QR码从网站收集此私钥。 但是此功能并不总是可用。
因此,当您必须输入此私钥时,是以base32格式与用户共享。 即密钥被编码为产生BASE32字符串。
所以在这种情况下,为什么BASE32比base64更好。
一个重要而简单的原因以及BASE32为何存在。 是仅使用A-Z大写字母(不使用小写字母)和数字2-7。 0189号 26 + 6个字符= 32。
没有小写字母,也没有0189,因此ilI1不会引起混淆。只有我 B和8 0以及O的混乱也被消除了。
要点是,如果输入0,则可以将其视为O。将1视为I等。
这些工具是尝试自动更正还是我的偏爱,只是告诉用户无效的输入是一个品味问题。但是很明显,人为错误对字符串的非唯一解释大大减少了。
base64并非如此。
以上所有带有大小写和数字混淆的问题都适用于base64。