什么是密码强度?
密码强度是指破解一个密码需要尝试的次数,其本质是密码所包含信息熵的大小。所以通常不是使用十进制数字来表示,而是用这个数字以 2 为底的对数来表示,也可以理解为把这个数字转换成二进制的位数。
例如使用 6 位数字作为密码,暴力破解最多需要尝试 10^6 次。他的密码强度就是 log2(10^6) = 23.25
。
AES-128/192/256 的密钥长度分别是 128/192/256 位,因为破解 AES 算法除了把每种可能都尝试一遍之外没有更好的办法了,需要尝试的次数分别是 2^128
/2^192
/2^256
次,所以他们的密码强度就是 128/192/256 位。
因为密码强度是使用二进制位数来表示的,所以密码强度每增加一位,意味着二进制数增加了一位,其破解的工作量就要翻倍了。
破解一个密码并不需要尝试到最后一种可能,平均来说,应该尝试一半的密码就可以了。所以实际破解密码所需的平均工作量,是比密码强度少一位的。
密码强度就是破解难度吗?
银行卡密码只有 6 位数字,而网站的密码通常至少要有 8 位的字母、数字和符号。不用计算都知道前者密码强度一定比后者低很多,但不会有人觉得银行卡密码不安全。
这是因为密码强度只表示了要破解一个密码需要尝试的次数,还有一个重要的因素是每次尝试所需的时间。两者相乘才是预计破解一个密码所需的时间。
银行卡密码虽然只有 6 位数字,但通常每天输错三次就锁定了。假设银行没有别的风控手段,每天都可以试三次,那么 6 位数字的密码平均需要 10^6 / 2 / 3 / 365 = 456
年才试出来。等到这时候不知道银行还在不在,反正我是不在了。
所以可以看出,像这种在线系统,更多是在尝试时间上做文章,也就是系统本身的安全策略比密码强度更重要。大多数网站也是这样,可以进行控制的手段有很多,例如输错多少次就要锁定一段时间,甚至每次锁定的时间成指数变长;通过图形验证码防止机器暴力破解,来降低尝试的速度;结合短信验证码等其他验证手段等。
除了在线系统外,还有一些离线的数据。例如一个加密的压缩文件,或者 OpenPGP、SSH 等各种密钥。这些数据可以被人截取之后离线攻击,攻击者可不会每天试三个密码就停下来了。这时就需要通过一些算法来延缓攻击者尝试密码的速度了,这就轮到我们的 KDF(密钥派生函数) 登场了。
理论上我们也可以开发出一个算法,你输入一个密码,他要计算 8 个小时才能给出结果,同样可以达到一天只能试三个密码的效果,这样按照上面的计算,同样使用 6 为数字的密码就可以保护四百多年了。但这里存在几个问题:
第一是算法可不分人,攻击者试一个密码要 8 小时,你也一样,你能忍受输入一个密码睡一觉起来才能看到结果吗?
第二个问题是芯片的性能是不断增长的。银行可以保证一百年后也一天只让你试三个密码(如果那时候还有密码的话)。但根据摩尔定律,今天需要计算 8 小时的算法可能 18 个月后就只需要 4 个小时了。
第三个问题是,KDF 是有上限的。KDF 是基于你输入的密码派生出那个真正用来加密的密钥。如果它真的慢到了一定程度,那攻击者不如直接去尝试派生出来的密钥算了。
所以 KDF 只能把每次尝试密码延缓到一个合理的范围,剩下的就要靠密码强度了。
我们需要多强的密码?
没有永远安全的密码,随着新技术的诞生、算力的提升,无论多强的密码都会被破解。所以要想知道需要多强的密码,首先需要想一下你希望密码在能在多长时间内不被人破解?假设这个值是 y
年。
刚才提到破解一个密码所需的时间还和尝试一个密码所需的时间相关,这通常可以估算或者实际测试出来。例如 KeePass 可以使用 Argon2d 算法,根据你的设备设置参数,使尝试一个密码所需的时间大概为你所设置的时间。假设这个值是 t
秒。
根据这些信息,我们能算出来在这些年内一共可以尝试 (365 * 24 * 60 * 60) / t * y
个密码。根据密码强度的定义,所需的密码强度为:
Math.log2((365 * 24 * 60 * 60) / t * y) + 1
在某些场景下,这个公式就够了。但很多时候并不是这样的,因为这个公式没有考虑:算力是不断提升的;攻击者可以离线破解。
随着算力的提升,每年能尝试的密码次数也将不断提升。假设算力每年提升 n
倍,那么每年能尝试的密码个数将是一个等比数列,在 y
年之内一共能尝试的密码次数就是一个等比数列求和问题了:(365 * 24 * 60 * 60) / t * (1 - n^y) / (1 - n)
。
算力通常都是用多少个月翻一番来表示,假设 m
个月翻一番,则 n^(m / 12) = 2
,所以 n = 2^(12 / m)
。
在你的设备上需要 1 秒钟做到的事情,在攻击者的设备上可不是。攻击者的设备通常性能会更好,甚至可能是专用的硬件。我们可以用一个倍数来表示,假设攻击者设备的性能是我们的 x
倍,那么这些年能尝试的个数也将是 x
倍:(365 * 24 * 60 * 60) / t * (1 - n^y) / (1 - n) * x
。
这个倍数更多是一个成本的问题,也就是你认为攻击者愿意花多大代价来破解你的密码。可以这样假设,你认为攻击者愿意每年花一百万来破解你的密码,而你当前的设备价值一万元,那么可以简单的认为攻击者的算力就是你的一百万倍。这样估算很粗暴,但对最终的结果不会产生太大的影响。我觉得攻击者有一百万,与其花在破解我的密码上,不如去挖矿更好一点。或者可以试一下每年花一百万来问我,我可能一秒就可以告诉他。
注意这个成本是每年,因为我们的公式还考虑到了算力是每年提升的,而攻击者如果想利用算力每年提升的成果,就需要每年更新设备才行。
如果攻击者不能离线攻击的话,只用第一个公式就够了。因为不能离线攻击,意味着每次密码的验证都要在你的设备上发生,那么无论攻击者的设备有多强都用不上了。而且不能离线攻击,只要你不换设备,摩尔定律对你就不生效。
最终的公式大概是这样:
const n = 2 ** (12 / m)
Math.log2((365 * 24 * 60 * 60) / t * (1 - n ** y) / (1 - n) * x) + 1
例如使用如下参数计算可以得到大概需要 66.61 位的密码强度。
t = 1, y = 30, m = 18, x = 1000000
如何生成一个这样的密码?
如果只使用 26 个字母作为密码,4 位的密码强度大概是 log2(26^4) = 18.80
位。那么如果我使用 mima
作为密码,他的强度是否有 18.80 位呢?
我们在最开始时就提到了,密码强度的本质是信息熵。4 位的密码之所以有 18.80
位的强度,是因为他有 26^4
种可能,攻击者平均需要做 26^4 / 2
次尝试。如果你使用的是汉字拼音作为密码,而攻击者也知道了这一点,他就只会使用汉字拼音来尝试,两个拼音总共有 413^2
种可能,所以这个密码的实际强度为 log2(412^2) = 17.38
。如果更进一步他知道你只使用了包含了两个字母的拼音,那么密码强度就只剩下 log2(79^2) = 12.61
了。
密码学有个原则叫柯克霍夫原则,是说你必须假设攻击者对你的系统完全了解,只是不知道你的密钥。所以你看我们常用的加解密算法全都是公开的、广为流传的、久经考验的,这根本就不是秘密,保密的只有密钥或者非对称加密的私钥。你不能说靠脑洞,攻击者肯定不知道我用的是拼音、双拼、五笔编码、古诗词、名字、生日、地名等等。攻击者可能就是会收集和你相关的信息,把它们做成字典来破解你的密码,这很容易做到。
所以计算一个密码的强度,不能单纯的看他所包含的字符数量。更合理的是应该看你用于组成密码的最小单元(我们把他叫做元素吧)的数量。
例如你使用 5 个汉字的拼音来组成密码,那么它的密码强度就是 log2(413^5) = 43.45
。无论这五个拼音包含的字符数是 10 个还是 30 个,它的强度都是 43.45 位。每个元素所能提供的密码强度为 log2(413) = 8.69
。
用于生成密码的元素越多,单个元素所能提供的熵就越高,生成同等安全强度的密码所需的元素数量就越少,也就越容易记忆。但元素多到一定程度,可能记住每个元素的编码就成问题了。
平均每个元素所包含的字符越少,单位字符的熵就越高,生成的密码就越短,越容易输入。但这是有极限的,例如元素都是用小写字母来编码的,那么单位字符所能提供的熵极限也就是 log2(26) = 4.70
了。这就意味着已经把键盘的所有排列组合都利用到了。
另外要保证这个密码的强度真的是 43.45,还有个因素很重要,就是你选取的元素必须是足够随机的。如果你不愿意记太长的密码,只选或者倾向于选两个字母的,那你的密码长度还是只有或略高于 log2(79^5) = 31.52
。
如果交给人主观去想,那么生成的密码肯定是不够随机的。所以有一种专门用于生成密码的方法叫 Diceware。大概步骤是提前准备好了一个包含了 6^5
个单词的列表,给每个单词编个号。然后扔五次骰子得到一个编号,去表里找到这个编号对应的单词。重复这个过程,找到多个单词组成一个密码。每个单词大概可以提供 log2(6^5) = 12.92
位的强度,六个单词大概是 77.52。
我们可以对比一下容易想到的各种元素集合:
元素集合 | 包含元素个数 | 每个元素能提供的熵 | 每个元素平均包含的字符数 | 平均每个字符提供的熵 |
---|---|---|---|---|
Diceware 单词列表 | 7776 | 12.92 | 4.24 | 3.04 |
拼音 | 413 | 8.69 | 2.4 | 3.62 |
双拼 | 同上 | 同上 | 2 | 4.35 |
五笔 | 6763 | 12.72 | 4 | 3.18 |
五笔二级简码 | 589 | 9.20 | 2 | 4.60 |
小写字母 | 26 | 4.70 | 1 | 4.70 |
ASCII 可打印字符 | 95 | 6.57 | 1 | 6.57 |
可以看到五笔二级简码的熵基本已经接近 4.70 了,说明二级简码基本已经把两个按键的组合覆盖完了。差不多是 Diceware 单词列表的 1.5 倍,也就是用 Diceware 生成的 30 个字符的密码和五笔二级简码生成的 20 个字符的密码强度是差不多的。ASCII 可打印字符的熵最高,但这个没有参考意义,因为很多符号需要配合 Shift 键使用,输入效率不一定更高。
结合这个表格,选一个适合自己的元素集合。然后根据前面计算出需要的密码强度,就可以知道需要多少个元素组成密码了,接下来就是扔骰子或者使用随机数等方式,选出这么多个元素就可以了。
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net
MEC208 Instrumentation and Control SystemS2, 2022-2023Computer Lab (Lab 2):Control System CAD and CAS using MATLABDr. Chee Shen LI…