Home Diceware
Post
Cancel

Diceware

What is Diceware?

Diceware™ is a method for picking passphrases that uses ordinary dice to select words at random from a special list called the Diceware Word List. Each word in the list is preceded by a five digit number. All the digits are between one and six, allowing you to use the outcomes of five dice rolls to select a word from the list.1

Here’s what a Diceware word list looks like:

1
2
3
4
5
6
7
8
9
10
11
12
...
16655 clause
16656 claw
16661 clay
16662 clean
16663 clear
16664 cleat
16665 cleft
16666 clerk
21111 cliche
21112 click
...

The complete list contains 7776 unique words. I’ve posted the one I use on my GitHub. You can download it here.

Breaking it down

Objective: Create a secure password

  1. Roll a die five times to create a five digit number (eg. 52334)
  2. Get a special char and a number
  3. Correlate roll to a word in the word list
  4. Profit

Code

1
import random, string

As you can see, the only libraries you’ll need to import are random and string. Random for the simulated die rolls and string so we don’t have to type out all the special characters.

Main function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def generate_password():
    passwd = []
    num = 3

    # Generate a random number between 1 and 999
    rand_num = str(random.randint(1, 999))

    for w in range(num):
        # Generate 5 random numbers between 1 and 6
        roll = ''.join([str(random.randint(1, 6)) for _ in range(5)])
        word = wl_dict[roll]

        # Randomly capitalizes the current word
        if random.randrange(2) == 1:
            word = word.capitalize()

        # Appends word to array
        passwd.append(word)

        # Generate a random special character
        passwd.append(random.choice(string.punctuation))

    # Concatenate the words, number, and special character to form the password
    final_pw = ''.join(passwd) + rand_num

    return final_pw

The num variable allows us to specify how many words we want in our password. For me, three is the sweet spot. Next we generate a random number between 1-999. Finally, we get to our beefy for loop.

  • roll: simulates our die roll resulting in a five digit number
  • word: searches our dictionary and stores the word in our variable

The if statement basically does a coin flip and will capitalize the word if it rolls a one. The two lines below the if statement append the selected word and a random special character to our empty passwd array. At the end our passwd variable will look like [‘Junkie’, ‘~’, ‘undivided’, ‘%’, ‘Disorder’, ‘#’]

  • final_pw: joins all of the elements in the passwd array into one string and adds our random number (ie. “Junkie~undivided%Disorder#943”)

Creating our word list dictionary

1
2
3
4
5
6
7
8
# Load the diceware word list
with open("diceware.txt", "r") as f:
    wl = [line.strip() for line in f]

wl_dict = {}
for line in range(len(wl)):
    l = wl[line].split("\t")
    wl_dict[l[0]] = l[1]

This part used to be way longer and over complicated for no reason. But, I fixed it. While our file is open we create the array wl which contains every line. However, our file has tabs in it for some reason so we can’t just split it normally. Instead we’ll create an empty dictionary and a for loop. In our for loop we can iterate line by line and split by that tab with \t. Then we just append to our dictionary wl_dict with the key being the number l[0] and value being the word l[1].

Calling our function

1
print("Password = " + generate_password())

Finally, we call our function which returns our finished password and print.

Conclusion

If you made it this far, you now have to go and change all your passwords. I hope you’re not reusing the same password for everything. Tisk Tisk Tisk. If you want a video tutorial, the YouTube channel Computerphile2 has a great video going over this topic. If you just want to run the script and not have to worry about all the coding, download it from my GitHub3 or run the web app I spent way too long on above.

This post is licensed under CC BY 4.0 by the author.

-

FileCloud - MongoDB connection failed