对(密码)熵感到困惑

信息安全 密码
2021-08-19 17:04:53

似乎有许多不同的“种类”熵。我遇到了两个不同的概念:

A) 的 XKCD 示例correcthorsebatterystaple它有 44 位熵,因为从 2048 个单词列表中随机选择的四个单词是 4 * log2(2048) = 44 位熵。这个我明白。

B) 实际字符串的香农熵,即熵是根据字母/符号的频率计算的。对结果应用香农公式correcthorsebatterystaple是每个字符 3.36 位熵。

# from http://stackoverflow.com/a/2979208
import math
def entropy(string):
        "Calculates the Shannon entropy of a string"

        # get probability of chars in string
        prob = [ float(string.count(c)) / len(string) for c in dict.fromkeys(list(string)) ]

        # calculate the entropy
        entropy = - sum([ p * math.log(p) / math.log(2.0) for p in prob ])

        return entropy

print entropy('correcthorsebatterystaple')
# => 3.36385618977

维基百科只会增加我的困惑:

重要的是要认识到一组可能结果的熵与特定结果的熵之间的差异。一次抛硬币的熵只有一位,但特定结果(例如“正面”)的熵为零,因为它是完全“可预测的”。
--维基百科:熵(信息论)

我不太明白折腾的熵(生成)和结果的熵(字符串)之间的区别。

  1. 什么时候使用 B 以及用于什么目的?
  2. 哪个概念准确地反映了密码的熵?
  3. 是否有术语可以区分两者?
  4. 真正的随机性可以给我们correctcorrectcorrectcorrect使用 A 我们仍然有 44 位。使用 B 的熵将与 的熵相同correct两者之间的区别何时重要?
  5. 如果一个要求指定一个字符串需要有 20 位的熵——我是使用 A 还是 B 来确定熵?
4个回答

维基百科文章解释了数学熵,这与人们谈论密码熵时的意思不同。密码熵更多的是关于在某些假设下猜测密码的难度,这与熵的数学概念不同。

A 和 B 不是密码熵的不同概念,它们只是使用不同的假设来构建密码。

A 将其correcthorsebatterystaple视为一串英语单词,并假设单词是从 2048 个单词的集合中随机选择的。基于这些假设,每个单词恰好给出 11 位的熵和 44 位的熵correcthorsebatterystaple

B 将其correcthorsebatterystaple视为一串字符,并假设任何字符出现的概率与在英语中出现的概率相同。基于这些假设correcthorsebatterystaple有 84 位熵。

因此,您使用哪种定义实际上取决于您对密码所做的假设。如果您假设密码是 XKCD 风格的密码(并且每个单词确实有机会出现在 2048 年的密码中),那么 A 是计算熵的正确方法。如果您不假设密码是作为单词集合构建的,但假设任何字符出现的概率等于它在英语中出现的概率,那么 B 是计算熵的正确方法。

在现实世界中,这些假设都不是正确的。因此,如果您有一个“要求指定字符串需要有 20 位熵”,并且这是针对用户生成的密码,那么很难给出熵的精确定义。有关这方面的更多信息,请参阅计算密码熵?.

另一方面,如果您可以使用计算机生成的字符串(并且正在使用良好的 PRNG),那么每个字母数字字符(az、AZ、0-9)将给出几乎 6 位的熵。

这是什么意思

抛硬币熵假设从一次抛到下一次,上一次抛的结果不会影响下一次抛的结果。因此,每次折腾都会增加一点熵。

香农熵假设下一个字母的值实际上部分地由前一个字母(可能还有其他字母)的值决定。考虑到诸如“h”通常跟随“t”和“e”通常跟随“h”之类的事实,因此为常见模式分配了较低的熵值。因此,对于英语词典,字符串the的香农熵值会比字符串低得多exu

这对你意味着什么

这对密码的直接影响是微不足道的。关于密码的真正(也是唯一)重要的问题是:

你的密码在哪个字典里?

也就是说,如果您要构建一个潜在密码列表来进行暴力攻击,那么字典必须有多大才能包含您的密码?

例如:

  • 您的密码在最常用的 500 个密码中
  • 您的密码在小写英文单词字典中
  • 您的密码位于带有一位或两位后缀的小写或大写英文单词列表中
  • 您的密码在带有haxor数字替换的随机大小写英文单词列表中(即 A=>4、L=>1、S=>5)
  • 您的密码在使用数字和大小写字母的所有 8 个字符或更少字符的列表中。

以上都是常用的现实世界密码破解字典的例子。

换句话说

密码复杂性的目的是抵御暴力攻击。包含密码的最小可用字典的大小决定了破解密码所需的时间。我们可以猜测攻击者可以使用哪些字典,但我们无法确定。因此,作为字典大小的代理,我们改为使用这是一个糟糕的替代品,因为它不能反映实际的攻击机制,但它可能总比没有好。

基于熵计算的密码比较可能是富有成效的,但你应该小心避免将太多的价值归于一个数字,这最终只是间接地与密码的承受能力有关。

我想最简单的说明方法是举个例子。

假设我们有一个随机数生成器,其可证明的输出熵为每位输出 3 位。该生成器的“折腾”熵是 3 位。现在,假设您运行 20 位,尽管概率非常小,但流中的每个数字都是 6。“折腾”熵仍然是每个数字 3 位,所以是 60 位。密码的实际“结果”熵很小——有人可能会说它低至 3 或 4 位。

不同之处在于,“折腾”熵表示基于生成器的概率建模的输出的预期熵,而“结果”熵表示它在真实案例中产生的数据的实际信息熵。

一个字节最多可以包含 8 位熵。这是上限。随着您对数据的了解更多,这些 8 字节块中的熵量会下降。哦,你所有的字节都是ASCII字符?这意味着最高位必须为 0;你的熵只有 7 位。没有控制字符?在 ASCII 集中,0-31 是控制字符 - 制表符、回车、响铃、文件结尾。这进一步减少了性格。字母,仅小写?现在,您正在极大地减少可用选项。英文单词?其中并不多——一个完整的英文单词,随机选择,可能只有大约 12 位,即使这些单词可能有 5 个字符。

人类选择的密码更糟糕;不是因为可能性较小,而是因为某些可能性比其他可能性更频繁。如果某些密码很常见,则更容易猜到;这会影响熵。如果 10% 的用户有“密码”,那将减少密码列表中的熵 - 即更容易猜到。

因此,您对密码的了解越多,您计算的熵就越低。在香农公式的情况下,它假设自然语言中的偏差,并计算 3.6 位 * 25 个字符 = 约 90 位的熵。当您获得附加信息(4 个字,每个字来自 2048 个列表)时,它会下降到 44 位。

这样看——如果有人破解了这个密码,只知道它是某种自然语言,然后突然发现它是 2048 列表中的 4 个单词(并且知道列表),他们会突然发现他们的工作是容易多了。