17

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

目标

如果没有规范化,如果有人ma\u00F1ana在一台计算机ma\u006E\u0303ana上将他们的密码设置为“mañana”(这是在用户代理或其操作系统的控制之下。

  • 我想确保这些哈希值相同。
  • 我不关心诸如Α、А 和 A(希腊语、西里尔语、拉丁语)之类的同形文字。

参考

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

注意事项

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

进一步的问题

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

1 回答 1

12

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

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

当输入仅包含分配的字符时,Unicode 附件 15 保证规范化稳定性:

11.1 规范化形式的稳定性

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

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

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

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

兼容性规范化形式似乎可以更好地处理日语,将几个分解分解为规范形式没有的相同输出。

规范警告:

规范化形式 KC 和 KD 不能盲目地应用于任意文本。因为它们消除了许多格式区别,它们将阻止往返于许多旧字符集的往返转换,除非被格式标记取代,否则它们可能会消除对文本语义很重要的区别。

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

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

于 2013-04-23T15:26:32.913 回答