如果我接受完整的Unicode密码,我应该如何在将字符串传递给哈希函数之前对其进行规范化?
如果没有规范化,如果有人在一台计算机上将密码设置为“mañana”(ma\u00F1ana
)并尝试使用另一台计算机上的“mañana”(ma\u006E\u0303ana
)登录,则哈希值会有所不同并且登录将失败。这受用户代理或其操作系统的控制。
Unicode规范化形式:http://unicode.org/reports/tr15/#Norm_Forms
"office" == "office"
。答案 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。