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

时间:2013-04-23 15:26:33

标签: unicode passwords unicode-normalization password-storage homoglyph

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

目标

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

  • 我想确保那些哈希值相同。
  • 我并不关心Α, А, and A(希腊文,西里尔文,拉丁文)等同形文字。

参考

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

考虑

  • 任何标准化程序都可能导致碰撞,例如"office" == "office"
  • 规范化可以改变字符串中的字节数。

进一步的问题

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

1 个答案:

答案 0 :(得分:13)

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

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

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

  

11.1规范化形式的稳定性

     

对于所有版本,即使在Unicode 4.1之前,也遵循以下策略:

     

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

     

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

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

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

规范警告:

  

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

然而,这里不关心语义和往返。

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