散列时哪些Unicode规范化(和其他处理)适用于密码?

tre*_*ell 16 passwords unicode password-storage unicode-normalization homoglyph

如果我接受完整的Unicode密码,我应该如何在将字符串传递给哈希函数之前对其进行规范化?

目标

如果没有规范化,如果有人ma\u00F1ana在一台计算机上将其密码设置为"mañana"()并尝试使用ma\u006E\u0303ana另一台计算机上的"mañana"()登录,则哈希将不同,登录将失败.这受用户代理或其操作系统的控制.

  • 我想确保那些哈希到同一个东西.
  • 我并不关心Α,А和A(希腊语,西里尔语,拉丁语)等同性字.

参考

Unicode规范化形式:http://unicode.org/reports/tr15/#Norm_Forms

注意事项

  • 任何标准化过程都可能导致冲突,例如"o?ce" == "office".
  • 规范化可以改变字符串中的字节数.

进一步的问题

  • 如果服务器收到的字节序列不是UTF-8(或其他格式),会发生什么?拒绝,因为它不能正常化?
  • 如果服务器收到其Unicode版本中未分配的字符会发生什么?

tre*_*ell 12

如果输入格式错误,例如涉嫌包含非法字节序列的UTF-8文本,则规范化是不确定的.在不同的环境中,非法字节可能会有不同的解释:拒绝,替换或遗漏.

建议#1:如果可能,拒绝不符合预期编码的输入.(但这可能超出了应用程序的控制范围.)

当输入仅包含指定的字符时,Unicode附件15可确保标准化稳定性:

11.1规范化形式的稳定性

对于所有版本,甚至在Unicode 4.1之前,遵循以下策略:

规范化的字符串保证稳定; 也就是说,一旦规范化,就会根据Unicode的所有未来版本对字符串进行规范化.

更准确地说,如果字符串已根据特定版本的Unicode进行规范化并且仅包含在该版本中分配的字符,则它将符合根据Unicode的任何未来版本进行规范化.

建议#2:无论使用哪种规范化形式,都必须使用稳定字符串规范化过程,即拒绝任何包含未分配字符的密码输入,因为在服务器升级时,它们的规范化不能保证稳定.

兼容性规范化形式似乎更好地处理日语,将几个分解折叠到规范形式不相同的输出中.

规范警告:

规范化表格KC和KD不得盲目地应用于任意文本.因为它们会消除许多格式区别,所以它们会阻止往返许多遗留字符集的往返转换,除非通过格式化标记取代,否则它们可能会删除对文本语义重要的区别.

但是,这里不关心语义和往返.

建议#3:在散列之前应用NFKC或NFKD.

  • 这些参考文献已被取代.RFC 7613(https://tools.ietf.org/html/rfc7613)废弃了RFC 4013,PRECIS框架(https://tools.ietf.org/html/rfc7564)是saslprepbis进程的最终结果. (2认同)