计算密码的熵(最小字长...)

信息安全 密码
2021-09-08 16:34:07

编辑:2013-05-17。2013-05-27

在阅读了 Tom Leek 的第一个答案和网络上的一些文档之后,我开始为我的工具genpassphrase.pl编写一些选项

$ ./genpassphrase.pl -h
Usage: genpassphrase.pl [-h] [-d dict file] [-i mIn length] [-a mAx length]
   [-e entropy bits] [-r random file] [-w words] [-l lines] [lines]
Version: passphrase.pl v1.3 - (2013-05-12 10:43:14).
    -h           This help.
    -l num       number of phrases to generate  (default: 1)
    -w num       number of words by phrase  (default: 5)
    -e bits      Entropy bits for each words (default: 15)
    -d filename  Dictionary file (default: /usr/share/dict/american-english)
    -i length    Minimal word length (default: 4)
    -a length    Maximal word length (default: 11)
    -r device    Random file or generator (default: /dev/urandom)

默认输出如下所示:

With 5 words over 32768 (     15 entropy bits ) = 1/3.777893e+22 -> 75 bits.
With 5 words from 56947 ( 15.797 entropy bits ) = 1/5.988999e+23 -> 78.987 bits.
  3.736 206.819 foggier     enforced    albatrosses loftiest    foursquare  

第一行显示在字典中找到的 uniq 单词的计数,下降到2^Entropy. 第二行显示 uniq 单词的初始计数,并据此计算理论熵。

每个输出行以两个值开头,第一个是Shanon's entropy,我不清楚它的含义和用法。第二个是基于整行中的字符数,每个字符为 1/26。

计算熵减少

David Cary 的回答证实了这个计算非常近似且难以表示,但给出了一些很好的评价和一种思维方式:

我认为降低所有价值可能会对我的问题有所了解:

$ ./genpassphrase.pl -i 1 -a 1 -l 4
Warning: Bunch of 26 words too small! Entropy bits dropped down to 4 bits index.
With 5 words over 16 (      4 entropy bits ) = 1/1.048576e+06 -> 20 bits.
With 5 words from 26 (  4.700 entropy bits ) = 1/1.188138e+07 -> 23.502 bits.
  2.322  23.502     f           r           h           j           u           
  1.922  23.502     t           f           g           e           f           
  1.922  23.502     r           k           i           y           r           
  2.322  23.502     y           u           x           f           i           

这使得更容易表示人类对此的选择将如何减少熵:对于样本,如果我不喜欢一个、两个或最多 10 个字母,则基于 26 个字母的 4 位最终熵仍然保持不变......

所以通过扩展,如果超过一堆 56947 个词,我不会排除超过 24179 个词,15bit/word 的最终熵仍然保持不变,但是:

$ ./genpassphrase.pl -a 8
With 5 words over 32768 (     15 entropy bits ) = 1/3.777893e+22 -> 75 bits.
With 5 words from 34954 ( 15.093 entropy bits ) = 1/5.217764e+22 -> 75.466 bits.
  3.397 159.815 corded      boosts      hatters     overhear    rabbles     

如果人类不选择,对于比字符长的示例单词,要排除的单词数将下降到 2186。最差:如果人类拒绝使用超过 7 个字符的单词(使用我的个人 dict 文件),这将下降总熵:

$ ./genpassphrase.pl -a 7
Warning: Bunch of 24366 words too small! Entropy bits dropped down to 14 bits index.
With 5 words over 16384 (     14 entropy bits ) = 1/1.180592e+21 -> 70 bits.
With 5 words from 24366 ( 14.573 entropy bits ) = 1/8.588577e+21 -> 72.863 bits.
  3.923 141.013 nitpick     buglers     loaders     arms        promo       

到 70 位(可能是 72.8 位??),而不是 75。

从那里...

我想用一些简单的文档和建议来完成这个工具。

原帖

在搜索了生成随机密码短语的工具后,我开始了自己的...

拿我桌子上已经存在的字典:/usr/share/dict/american-english 看看:

wc -l /usr/share/dict/american-english
98569

快速浏览后,我看到许多's以大写字母开头的终止符和名称。

sed -ne '/^[a-z]\{4,99\}$/p' /usr/share/dict/american-english | wc -l
63469

哦,少于 65536,因为我不能只读取 15.953 位,所以我将把它降低到 15 位索引(使用伪随机,因为现在这可能就足够了。)。

与 5 个单词相比,我可以计算出 75 位密码:

#!/usr/bin/perl -w
use strict;

open my $fh, "</usr/share/dict/american-english" or die;
my @words = map { chomp $_; $_ } grep { /^[a-z]{4,11}$/ } <$fh>;
close $fh;

while (scalar @words > 32768 ) {
    my $rndIdx=int( rand(1) * scalar @words );
    splice @words, $rndIdx, 1 if $words[$rndIdx]=~/s$/ || int(rand()*3)==2;
}

open $fh, "</dev/random" or die;
$_='';
do { sysread $fh, my $buff, 10; $_.=$buff; } while 10 > length;
$_ = unpack "B80", $_;

s/([01]{15})/print "  ".$words[unpack("s",pack("b15",$1))]/eg;
print "\n";

这可能会产生如下输出:

  value  nationally  blacktopped  prettify  celebration

从那里,我有3个问题:

.1 一个词的最小长度是多少?4个字符就够了吗?如何计算 4 个字母单词的熵?

在普通字母表中,一个字母是 1/26 -> 4.7 位,但后面的字母通常是元音,所以 1/6 -> 2.5 位!?

如果我是对的,一个 4 个字母的单词不能代表超过 14.57 位??

.2有些人可能会尝试运行几次以获得一些选择:

for i in {1..6};do ./gen_pass_phrase.pl ; done
  commons  tweaking  inhered  driveways  sedately
  pantheon  appeaser  inmate  quantifiers  pyrite
  loopier  cloistering  asceticism  auctions  table
  value  nationally  blacktopped  prettify  celebration
  fainer  arthritis  deplete  vestry  fostering
  deuterium  junipers  luckless  burro  harmonic

并在这堆中选择 5 个单词是人类可感知的:

commons  value  fainer  quantifiers  celebration

这将减少

性感的词更有机会被选中。

但我不能用数字论证来表示这一点。

.3从我玩的时候开始,我意识到 1/3 的单词是复数:

sed -ne '/^[a-z]\{4,9\}$/p' /usr/share/dict/american-english | wc -l
 44476
sed -ne '/^[a-z]\{3,8\}s$/p' /usr/share/dict/american-english | wc -l
 13408

我试图在删除多余的单词时对其进行补偿,因为我认为删除每个s终止的单词也不是一个好主意,所以我在s终止或 rand 1/3 时删除了 exedent。

没问题。

最大75 位的熵,似乎用这种方法下降了,但我不代表如何演示它们,也不代表如何计算它们。

2个回答

熵是密码生成过程的度量。假设您有一个包含 32768 个单词的列表可供选择。您从该列表中随机且均匀地选择 5 个单词(这些单词是彼此独立选择的,因此您可能会得到相同的两倍)。那么你正好有 75 位熵您的密码生成过程可以精确地产生 2 75个不同的密码短语,它们都具有完全相同的被选中概率。那是 75 位熵,没有任何歧义。

有些词很短,有些词很长,或者有些词是复数形式,或者有些词比其他词更性感,对你的熵没有任何影响。熵是生成过程的一个属性,你的生成过程不关心单词的长度或性感。普通人类用户,当留给他们自己的基于肉类的设备(他们的大脑)时,往往会比其他人更频繁地选择某些单词;他们不擅长统一随机性。他们来说,计算实际的“熵”很困难,因为我们真的不知道他们有多大的偏见。但这与您的发电机无关,它不使用大脑,但是/dev/random. /dev/random没有发现某些词比其他词更有吸引力;它的口味更简单。

(说到这,你应该使用/dev/urandom,而不是/dev/random。见这个。)

正如 Tom Leek 正确指出的那样,熵是生成过程的属性。它不是该过程生成的任何特定密码短语的属性。

一个单词的最小长度是多少?4个字符就够了吗?如何计算 4 个字母单词的熵?

当您从随机数生成器中提取 15 位,并使用这些位从字典中统一选择 2^15 个唯一单词中的一个时,每个单词都恰好有 15 位熵——不管它有多长.

是的,使用只有4 个字母的英语单词的字典会导致密码短语的每个 4 个字母的单词的熵少于 15 位 - 这是另一种说法,即少于 2^15 个单词的长度为 4 个字母一本英语词典。但这在这种情况下无关紧要——没有理由从你的字典中任意排除短词。

同样,在英语词典中以“be”开头的单词少于 2^15 个——因此以“be”开头的单词每个单词的熵少于 15 位。同样,这个事实是无关紧要的——没有理由从你的字典中任意排除以“be”开头的单词。

...运行几次以获得一些选择:...并在这堆中选择 5 个单词为 is human ...这将减少熵 ...

是的,如果你让一个人拒绝一些词,那么它会减少熵。

估计这一点的一种方法是假设人类会接受一些“真实”的单词列表,而他会拒绝所有其他单词。如果该列表只有 2^N 位,那么实际人工选择的密码中的每个单词(最多)每个单词只有 N 位熵。唉,很难找出“N”到底是什么。

有时人类拒绝某些单词的原因是因为他们不知道如何拼写它们。避免这种情况的一种方法是使用更短的字典,只包含常见的、易于拼写的单词。例如,与 15 位/字 * 5 字 = 75 位的最佳情况相比,通过从 2^11 个常用词的短得多的字典中统一挑选 7 个词,您可以获得稍多的熵(77 位),例如S/Key 2048 字词典。

也许更好的选择是让计算机选择 5 个单词的密码短语作为全有或全无的列表。如果您向用户展示 8 个这样的密码短语,并强制用户从这 8 个密码短语中选择一个(而不是从 30 个单词的列表中混合和匹配任何 5 个单词),则可以证明:在最坏的情况下将所选密码的强度降低 3 位(至 72 位)。在最好的情况下(用户总是选择第一个,或者用户使用 3 次公平的硬币翻转来选择 8 个中的一个),所选密码的强度是 15 位 * 5 个字 = 75 位的全熵。

1/3 单词是复数

只要你的 2^15 个单词的字典中的每个单词都是唯一的并且是统一选择的,它是否是复数无关紧要。与上面的“be”案例一样,没有理由从字典中任意排除以“s”结尾的单词。

(而且我怀疑 1/3 的单词是真正的复数形式——您的快速测试会捕捉到不是真正的复数形式的单词,例如“abacus”、“bus”和“boss”)。