At the end of the Cybersecurity: Encryption Intro [1] tutorial, there’s a Your Turn in the Substitution Ciphers [2] page where you created a scrambled_alphabet_cipher script. This kind of function is a much better defense against brute force attacks. Instead of testing 93 possible shifts, a brute force attack would have to try decrypting with 26! permutations of the alphabet. The term 26! is pronounced 26 factorial.
3! = 3 * 2 * 1 = 6
4! = 4 * 3 * 2 * 1 = 24
5! = 5 * 4 * 3 * 2 * 1 = 120
…
26! = 403,291,461,126,605,635,584,000,000
Wow! That would be a lot of rearrangements of the alphabet for a brute force algorithm to crack. Also, who would try to look at all those combinations to find the intelligible text?
# scrambled_alphabet_cipher from microbit import * # Scrambled alphabet cipher. def scramble(text, encrypt): alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" crypta = "PTQGMKCRSVEXADZBJFOWYNIHLU" result = "" if encrypt is False: temp = alpha alpha = crypta crypta = temp for letter in text: letter = letter.upper() index = alpha.find(letter) result = result + crypta[index] return result # The script starts executing statements from here. sleep(1000) print("Set your keyboard to CAPS LOCK.") print() while True: text = input("Enter a CAPS LOCK string: ") result = scramble(text, True) print("scrambled result =", result) result = scramble(result, False) print("unscrambled result =", result)
The scrambled alphabet cipher has two arguments, text and encrypt. In this case, the cipher accepts upper-case characters or words. The encrypt argument accepts True or False. True encrypts, and False decrypts. Inside the function, there is an alphabet, and a cryptabet. The cryptabet is a scrambled version of the alphabet. It also has an empty result string that will be used to build the encryption result.
# Scrambled alphabet cipher. def scramble(text, encrypt): alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" crypta = "PTQGMKCRSVEXADZBJFOWYNIHLU" result = ""
This step is only performed if the function is called with the encrypt argument set to False. When the function encrypts, it uses alpha and crypta as declared above. When it decrypts, alpha has to store "PTQGMKCRSVEXADZBJFOWYNIHLU" and crypta has to store "ABCDEFGHIJKLMNOPQRSTUVWXYZ". So if encrypt is False, the statements below and indented shuffle the two strings. It does so by copying the alpha string into temp, then copying the crypta into alpha. Lastly, temp — which contains the original alpha — gets copied to crypta.
if encrypt is False: temp = alpha alpha = crypta crypta = temp
The encryption loop starts by making sure the letter is upper case with letter = letter.upper(). Then, it finds the index of the letter in alpha with index = alpha.find(letter). Finally, it looks up the letter with that index in the cryptabet and appends the string result with result = result + crypta[index].
for letter in text: letter = letter.upper() index = alpha.find(letter) result = result + crypta[index] return result # The script starts executing statements from here.
The script starts executing statements here, with the usual sleep(1000) and a message to set your keyboard to CAPS LOCK.
sleep(1000) print("Set your keyboard to CAPS LOCK.") print()
Inside the main loop, an input statement prompts you to type a CAPS LOCK word and stores the result in a variable named text. Then, result = scramble(text, True) encrypts the text you typed and stores it in a variable named result, which gets printed.
while True: text = input("Enter a CAPS LOCK string: ") result = scramble(text, True) print("scrambled result =", result)
Next, result = scramble(result, False) decrypts the string, and the last print statement displays the original text you entered.
result = scramble(result, False) print("unscrambled result =", result)
It takes a while to well and truly shuffle the characters in an alphabet by hand, so why not use a script?
If you want the scramble to be repeatable, you can add a statement like random.seed(10) anywhere above while n < size: For each different seed, you will get a different, but repeatable, result. Without a manually entered seed value, the micro:bit uses the system timer to get a more random seed to determine the sequence.
# cryptabet_autogenerate from microbit import * import random sleep(1000) alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" size = len(alpha) print("size: ", size) print("alpha:", alpha) sleep(1500) crypta = "" n = 0 while n < size: sleep(50) r = random.randint(0, size-1) c = alpha[r] print("r:", r, ", c:", c) if crypta.find(c) == -1: crypta = crypta + c n = n + 1 print("n:", n, ", crypta:", crypta) sleep(1000) print("crypta:", crypta) sleep(100) print()
The cryptabet_auto_generator script starts with alpha, which is set to the upper-case alphabet for the sake of example. It repeatedly generates random numbers in the 0…25 range, and then grabs the character at that index from alpha. Then, it checks if that character is already in crypta. If yes, then it discards the character and tries again. If no, then it appends the character to crypta and starts adding the next character.
Sleep statements were added at various points to give the online editor’s terminal enough time to keep up with the stream of text data.
The script uses the length of the alpha string to build the crypta string. So there would be no problem using a custom alphabet, like alpha = "vLR{}:,’01234 56789", for example. That particular alphabet would support dictionaries from the Terminal Control - Go Wireless [3] activity.
Now that you know how to better encrypt communications, you can strengthen apps from previous activities against brute force attacks.
A scrambled alphabet substitution cipher can make the app from Share Something Personal - Encrypted [4] activity much more difficult to crack with a brute force attack.
You can even use cryptabet_autogenerate to generate a custom cryptabet. If you just use the one that’s in the scrambled_alphabet_cipher script, your fellow students might have a very easy time cracking your cipher with a simple guess and test!
This cipher does not need to just have upper-case alphabet letters. You could, for example, make alpha and crypta strings that contain the characters for the keyboard-controlled cyber:bot’s dictionary. The alpha and crypta strings might look might look like this:
alpha = "vLR{}:,’01234 56789" crypta = "v9L:3405’R286, 7{}1"
With nineteen characters, there are 19! = 121,645,100,408,832,000 different ways to arrange the characters in this string.
For an example of the steps to follow to add encryption to your data applications, try the Encrypt Your App Data [6] activity in the Cybersecurity: Sniffing Attacks and Defenses [7] tutorial.
Links
[1] https://learn.parallax.com/tutorials/robot/cyberbot/cybersecurity-encryption-intro
[2] https://learn.parallax.com/tutorials/robot/cyberbot/cybersecurity-encryption-intro/ascii-and-other-simple-ciphers
[3] http://learn.parallax.com/tutorials/robot/cyberbot/cybersecurity-navigation-control-keyboard/terminal-control-%E2%80%94-go-wireless
[4] https://learn.parallax.com/node/2282
[5] https://learn.parallax.com/tutorials/robot/cyberbot/cybersecurity-navigation-control-keyboard/terminal-control-%E2%80%94-go-wireless
[6] https://learn.parallax.com/tutorials/robot/cyberbot/cybersecurity-sniffing-attacks-and-defenses/encrypt-your-app-data
[7] https://learn.parallax.com/tutorials/robot/cyberbot/cybersecurity-sniffing-attacks-and-defenses