a paper calendar, 31 days are on it

My 31 Days Passcode Based System for My Sunrise Alarm

Published on:

If I want to stop my Sunrise Pialarm, I have to enter that day’s passcode. I will show you how I generate them.

The individual source code of the script can be found at GitHub Gist: generate_passcodes.py. This is part of a bigger project, which is fully open source. Check out GitHub - 11Firefox11/sunrise-pialarm.

The Goal

I have to generate 31 unique random, hard to remember passcodes. What are the goals?

Implementation

Write Into JSON

Writing into a file is easy, no need to overthink it. The format I want to achieve is: ["code1", "code2" ...]. The script opens a file, puts in the starting bracket, writes in the passcodes one by one and closes the bracket. This can be achieved with a for loop.

PASSCODES_JSON_PATH = "passcodes.json"
passcodes_file = open(PASSCODES_JSON_PATH, "w")  # open the file in write mode
passcodes_file.write("[")
for day_num in range(31):
    passcodes_file.write(f"\"code{day_num}\"{',' if day_num != 30 else ''}") # write in "codeX" plus a comma if it isn't the last day_num 
passcodes_file.write("]")

Generate Passcodes

To create random passcodes use token_urlsafe, which creates a random text string based on inputted nbytes.

from secrets import token_urlsafe as secrets_token_urlsafe
# ...
for day_num in range(31):
    passcode_raw = secrets_token_urlsafe(4)
    # ...

Hash and Make Them Unique

Hashing is a process of converting input data of any size into a fixed-size output value. This makes a one way tunnel, it can be checked if a hash is the inputted passcode (if we know the hash algorithm), but we can’t get from the hash what is the passcode. In this script the sha1 algorithm is used. To make them unique store all passcodes in a list. If a passcode is already in the list a new one is generated.

from hashlib import sha1
# ...
hashes_generated = []
for day_num in range(31):
    passcode_raw = secrets_token_urlsafe(4)
    passcode_hashed = sha1(passcode_raw.encode()).hexdigest()
    while passcode_hashed in hashes_generated: # if exists, generate new one
        passcode_raw = secrets_token_urlsafe(4)
        passcode_hashed = sha1(passcode_raw.encode()).hexdigest()
    hashes_generated.append(passcode_hashed)
    # ...

Save Into File and Print

Just simply change the text inside write to save the hashes instead of "codeX". The script prints out each passcode one by one, waits for an input just so it is more visible which passcode is coming now.

# ...
for day_num in range(31):
    # ...
    passcodes_file.write(f"\"{passcode_hashed}\"{',' if day_num != 30 else ''}")
    print(f"{str(day_num+1).zfill(2)} | {passcode_raw}", end="") # zfill the number so each will be same width
    input()

Read more

a hand holding a remote control with a led strip in the background

Python Class to Control an RGB LED Strip on a Raspberry Pi

a raspberry pi with a LED strip connected to it

How to Connect a LED Strip to a Raspberry Pi