Processing math: 100%
0%

利用 Diceware 生成好记的密码

XKCD comic about password strength
Diceware是一种生成便于记忆并难以通过暴力穷举密码的方式。很长时间以来,网站都在建议人们使用更加复杂的密码,如:

  • 混合使用大小写字母和数字
  • 使用标点符号
  • 避免出现常见单词的拼写组合
  • 在不同的网站使用不同的密码以避免被撞库

几种常见的密码组合方式的组合数分别为:

密码成分 8位组合数 12位组合数 16位组合数
a-z 1011.3 1017.0 1022.6
a-z0-9 1012.5 1018.7 1024.9
a-zA-Z 1013.7 1020.6 1027.5
a-zA-Z0-9 1014.7 1022.0 1029.3
a-zA-Z0-9& 1015.8 1023.7 1031.6

这样的确可以生成复杂度极高的密码,但是这样的密码对用户非常不友好,难以记忆,所以事实上真正这样做的人并不多。毕竟,没有多少人真得能牢记形如 z28>+J]pFF22c+tj?WtdCW(a9j9u2+jw@^xtE9am#(eFC9H8T3sY]7]tnRc28U>}i949re{NCjje%/*9 的密码,并且能分清分别对应哪个网站、哪个账户。

用 Diceware 生成密码可以在一定程度上解决这个问题。 Diceware 的原理是:对字典中的每一个单词用长度一定(如5位)的6进制数字编号,生成密码时,掷一枚均匀的六面骰子5次,得到一个5位的6进制数字,根据编号找到并记录这个单词。重复这样的操作3到5次,即可得到长度为3至5个单词的diceware密码。可以针对这几个单词编一个故事便于记忆。

电子前线基金会(EFF)在网站上给出了一个已经完成编号的单词列表,其中包含了 65=7776 个单词,另外,在 github 上还可以找到包含近50万单词的词汇列表。根据 EFF 的词典生成的随机密码可以具有相当高的复杂度:

  • 随机选取3个单词一共有 (65)3=1011.7 种不同的组合
  • 随机选取4个单词一共有 (65)4=1015.6 种不同的组合
  • 随机选取5个单词一共有 (65)5=1019.5 种不同的组合

相对于记住十几位毫无规律的随机字符串,通过编故事记住几个形如 aloft-applied-embodymug-gown-getawayidiom-eggnog-sadden 的单词组合应该会容易的多。

利用 Python ,写一个生成 Diceware 密码的程序非常简单:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import collections
import random

diceware = collections.defaultdict()

with open('eff_large_wordlist.txt') as fp:
for line in fp:
words = line.split()
diceware[words[0]] = words[1]

length = 3
sep = '-'

words = []
for j in range(length):
index = "".join([str(random.randint(1,6)) for i in range(5)])
words.append(diceware[index])
print(sep.join(words))

生成密码的部分还可以分别一行写完

1
print(sep.join([diceware["".join([str(random.randint(1,6)) for i in range(5)])] for j in range(length)]))

另外在实际应用中,要使用密码学安全伪随机数生成器(CSPRNG)