【问题标题】:Why is this hash, created from a constant list, "in different order" each time the program is run?为什么每次运行程序时,这个从常量列表创建的哈希“以不同的顺序”?
【发布时间】:2015-02-19 05:36:49
【问题描述】:

下面是 Perl 中的小脚本。每次我运行这段代码时,我都会得到不同的输出。

谁能帮我理解散列变量存储的基础知识,那就是如何为 Perl 的散列变量的键值对进行索引。

#!/usr/bin/perl

%data = ('John Paul' => 45, 'Lisa' => 30, 'Kumar' => 40);
@names = keys %data;
print "$names[0]\n";
print "$names[1]\n";
print "$names[2]\n";

【问题讨论】:

  • 我认为这是一个有趣的问题,因为 what 这意味着 Perl 正在做什么以及为什么这样做的微妙含义。然而,一般来说,哈希顺序是“不可靠的”,因此虽然它可能会暴露一个有趣的工件,但它是在一般的“不要那样做”类别下这样做的——这可能是导致投票失败的原因。跨度>
  • 可重复的ideone.com/IXwgWz(添加了更多名称,因此不同的顺序更频繁地可见)
  • 我不认为这是该问题的重复项(其中的答案确实涵盖了“不要那样做”类别),原因如前所述。这是关于为什么运行之间的顺序不同特定情况,并且与特定的实现细节相关联。这种行为是“相对较新的”。
  • @user2864740,它实际上已经很老了。自 5.8.1 中添加 env var PERL_HASH_SEED 以来,它至少已有 12 年的历史。唯一的区别是它现在发生得更频繁了。过去在哈希被加盐之前必须发生一些特定条件,但现在所有哈希从一开始就被加盐。

标签: perl hash


【解决方案1】:

该行为记录在perlsecAlgorithmic Complexity Attacks 中。


散列是一个链表数组。散列函数将键转换为一个数字,该数字用作存储值的数组元素(“桶”)的索引。多个键可以散列到同一个索引(“冲突”),这种情况由链表处理。

如果恶意用户知道散列算法,他可以设计散列到相同索引的值,导致散列退化为链表。这可能会导致某些应用程序的性能大幅下降,因此可用作拒绝服务 (DoS) 攻击的一部分。

采取了两种措施来避免这种情况。一种是对散列算法进行加盐以随机化元素存储的顺序,另一种是通过扰乱迭代器访问散列元素的顺序来使得更难检测到加盐。

$ perl -E'
   my @k = "a".."z";
   for (1..3) {
      my %h = map { $_ => 1 } @k;
      say keys %h;
   }
'
iocmbygdkranwxfejuqpzvltsh
bmcoigdywrankujfxezpqlvths
juexfwarnkgdybmcoihstlvzpq

【讨论】:

  • (缓解的漏洞称为“Hash [Flood] DoS”。)
  • 另外,如果你需要命令并且你需要一个“哈希”,那么有多种方法可以做到这一点,其中:Hash::Ordered.
  • @ikegami:你使用的是什么 perl 版本?在我的系统 perl v5.14.2 中,输出是一次 wraxdjyukhgftienvmslcpqbzowraxdjyukhgftienvmslpcqbzo 两次(如果我增加 for 循环范围,则输出更多)。为什么会这样?
  • @cuonglm,您可以在 5.14 中在运行之间获得不同的排序,但必须先发生一些特定条件。在 5.18 中,您获得不同订单的频率发生了变化。
  • @ikegami:你能澄清一下specific conditions是什么吗?
【解决方案2】:

perldoc -f keys 中描述了此行为

哈希条目以明显随机的顺序返回。实际的随机顺序特定于给定的哈希;对两个散列进行完全相同的一系列操作可能会导致每个散列的顺序不同。任何插入到散列中的操作都可能会更改顺序,任何删除操作也一样,但每个或多个键返回的最新键可能会在不更改顺序的情况下被删除。只要未修改给定的哈希值,您就可以依赖键、值和每一个重复返回彼此相同的顺序。

..为了防止Algorithmic Complexity Attacks

【讨论】:

  • 该行为暗示 Perl 使用的 (re)hash 函数本身在进程间是不确定的(这与引用不冲突,但未完全被引用)并且可能应该被覆盖更详细。
  • 那段话并没有解释为什么它在运行过程中会有所不同。
  • @Сухой27,我没有替换所有内容,而是发布了自己的答案。
  • 正确的文档链接:Algorithmic Complexity Attacks
  • 关于“为了”,即使没有采取措施防止“算法复杂性攻击”,引用的这段话也是正确的。
猜你喜欢
  • 2014-12-06
  • 2015-08-01
  • 2011-05-04
  • 2014-12-30
  • 2014-02-04
  • 2020-10-04
  • 1970-01-01
  • 2016-12-15
  • 2012-06-27
相关资源
最近更新 更多