The project supports encrypting a text message or an image file. The cipher used differs between them, but the key derivation works similarly. The key is generated by finding the SHA-256 hash of the sensor reading range (ex: 200-300) or GPS coordinates (ex: 40.656,-74.007).
Text Secrets
Text messages use the Vigenère cipher modified to support the full range of printable ASCII characters instead of just letters A-Z. This cipher outputs scrambled, but printable, text when an attempt to decrypt with the incorrect key is made. It's perfect for this project because it shows mysterious text as a clue that a secret message is hidden within. Vigenère cipher can use a key of any length. The key must use the same alphabet of characters that the encrypted message does. In this case, the ASCII printable characters in the ID range 32-126 from space to tilde in the ASCII chart. SHA-256 produces a 256-bit (32 byte) hash containing raw byte values which aren't restricted to printable ASCII. To work around this, the base64 representation of the hash is used as the Vigenère key. For example, a generated key looks something like this:
PdToaSE3R9V9ClRENwNMhYV+ihPv5NXt05kQo8VrbH8=
Once you have the key, encrypting a message with the Vigenère cipher is done by looking up each clear text characters cipher text counterpart in the Vigenère table or tabula recta. Each successive character that is encoded uses a row from the table matching the next character from the key, which gives the cipher its polyalphabetic property. That increases its resilience against basic frequency analysis, and makes repeated clear text characters come out looking scrambled and non-repetitive in the cipher text.
Image File Secrets
Image files contain raw binary data instead of only printable text characters. Modern cryptography ciphers were made for the computer age and support encrypting raw data. AES is one such modern cipher. It's used by this project for encrypting images. Under normal circumstances, an entire file would be encrypted with AES, making it completely unreadable and unable to be successfully rendered as an image in common applications.
The image file contains metadata like encoding type, size, and color palette which are necessary for rendering it. To avoid completely non-functional image files, only the pixel data is encrypted. The rest of the metadata remains intact. As a result, the display will show a scrambled image that resembles TV static whenever the key is wrong, instead of being entirely broken with only an error message about a corrupt file.
One of the variations of AES accepts a 256-bit (32 byte) key, which is conveniently exactly what is output by the SHA-256 hashing algorithm. That means the raw bytes of the hash can be used as the key directly instead of having to convert them to base64 or any other representation. Here is an example of what the AES key could look like:
b'9\x0b6|\xf2\xc3Cg\xca\xb5}I3,m\xcb\x0f\x8e\xb7\xb1\x08J`\xcb\x84\xd1]E\xeb\xe4\xe4\x8a'
The code attempts to decrypt the pixel data using a key derived from the current sensor reading, then uses bitmaptools.arrayblit() to copy the resulting pixels into a displayio.Bitmap so that it can be shown on the display. If the key was incorrect, the Bitmap will look like random pixel noise. If the key was correct, the original image will be revealed.
Page last edited May 06, 2026
Text editor powered by tinymce.