Secret Agent Chat - Raspberry PI

von Satoshi Nakamoto



What you will make
In this resource you will learn how to create and use an encryption technique known as the one-time pad. This method of encryption will allow you to send secret messages to your friends and, as long as you’re careful, the messages will be unbreakable.
What you will learn
By writing the secret agent chat program, you will learn:

How random numbers can be used to encrypt messages
How iteration can be used to encrypt individual characters
Why techniques such as the Caesar cipher are insecure
Why it’s important to keep your keys a secret

This resource covers elements from the following strands of the Raspberry Pi Digital Making Curriculum:

Combine programming constructs to solve a problem

 
What you will need

A computer with Python 3 installed

 
Secret agent chat
In this resource you will learn how to send secret messages using a technique called the one-time pad.

One-time pad

When you’re a secret agent, sending messages to your friends can be a tricky business. If the message is seen by your enemies they’ll know what you’re up to, and you could be in trouble.

Cryptography is a way of disguising the contents of your message, to make it harder for your enemies to read. One of the first forms of cryptography was used by the Roman emperor Julius Caesar, and is now called the Caesar Cipher.

Imagine Alice wants to send a secret message to Bob, without Eve knowing what the message says. Alice first picks a key, which will be a number such as 3. Alice then tells Bob the key.

Whenever Alice wants to write a message, all she needs to do is shift each of the letters in her message forward in the alphabet by 3 places:

So the plaintext…

becomes the ciphertext…

The problem with this is that Eve can easily decrypt the message. She just needs to try using every number between 1 and 26 as the key, and see which one makes sense. She could also look for words with 2 or 3 letters in them that occur a lot, like ‘to’, ‘at’, ‘the’ or ‘and’, then use these to find out what the key is.

During World War II the German military thought they had developed a perfect method of encrypting messages, using something called an Enigma machine.

Engima

They were wrong, though, as there’s no such thing as perfect cryptography. Thanks to some clever Polish mathematicians and a British mathematician called Alan Turing, the Enigma messages were decrypted, and this helped the Allies win the war.

A one-time pad (OTP) is a different method of encryption. When using an OTP, a string of random numbers are generated and shared between Alice and Bob. Each letter of the message is then shifted by the corresponding number in the OTP, so each letter has its own individual key! As long as Eve doesn’t have the OTP, the message is impossible to decrypt.

 
Generating a one-time pad
Open a new Python file in your preferred editor.

The first thing you need is some random numbers, so import the randint method from the random module:


It is worth noting, that if we were real secret agents, then using random might be a little insecure. os.urandom is a much more secure way of generating random numbers.
Later on you’re going to need the alphabet as well, so it’s best to declare this constant now:


Next, you can create a function to generate an OTP. It will need to have parameters for the number of sheets in the pad and the number of characters that each sheet can encrypt:


Now a new file needs to be created for every sheet. Each file will be saved as .txt with the following naming convention: otp0.txt, otp1.txt, otp2.txt. You can use a for loop for this:


Finally for this function, you can add in two lines of code that will write out the random numbers to the file. Here, you’re adding a n character to the end of each number, so it’s written to a new line.


Test your code by saving (ctrl+s) and running (F5). Then type generate_otp(5, 100)into the shell
If you open your file browser, you should see 5 new files have been created. Open one of them and you’ll see a column of random numbers. These files are collectively called your one-time pad.

files

 
Loading a sheet from the OTP
Now that the OTP has been generated, you need a way to load a sheet and store all its numbers in a list.

First, you can create a function to open a file:


Then you can load the contents of the file into a list. The splitlines() part breaks each line up into a single item in the list and also removes the n character (newline):


Test this function by saving and running your code again. Now in the shell you can type the following:


output of load_sheet

 


Writing a secret message
The next function is a really simple one: it asks the user to type in the message that will be encrypted. The only small addition is to convert all the letters to lowercase, as this will make it easier to encrypt without losing any meaning:



Loading and saving the messages
Next, you’re going to need a method of opening messages written to you, and saving the messages that have been encrypted. Again, you’re going to need a couple of fairly basic functions - one to open and read a file, the other to open and write a file:





Encrypting a message
Now comes the fun part: you’re going to encrypt a message using a sheet from the one-time pad. This function will have two parameters. The first will be for a string that contains the plaintext message; the second will be for the one-time pad sheet that will be used.

To start with, you can define the function:
Once you start encrypting the plaintext, you’ll need to store the ciphertext. You can use an empty string to do this:
Now comes the clever part. This function is going to act on every character in the plaintext, a process called ‘iteration’. While it’s doing this, it needs to keep track of which character it’s working on and what position that character has in the plaintext. To do this, you can use the built-in function enumerate():
The next thing to do is check if the character from the plaintext is in the alphabet or not. In this program you’re not going to bother encrypting spaces or punctuation, so if the character is not a letter, it can just be added to the ciphertext string. This is where we use that ALPHABETconstant you wrote earlier:
The next part is quite tricky to understand.

Firstly, you need to find the position of the plaintext character in the alphabet - ALPHABET.index(character).
Then you need to add this number to the value from the equivalent position on the sheet from the OTP - int(sheet).
This new number needs converted back into a letter. If the new number was 0 it would become a, if it was 5 it would become f and so on. What if the number is greater than 25, though? If the number is 26 it needs to be changed to 0, and if it’s 30 it should be changed to 4. To do this we can use the modulo operator (%), which finds the remainder after a division.
Lastly, the number is converted to a letter.


Putting that all together into your function, it would look like this:
You can finish off by returning the ciphertext:
To test your function you can save and run your code and then type the following into the shell.

encrypt output



Decrypting messages


Decrypting messages
When communicating with your friends, you’ll need a way to decrypt the message as well. The next function is very similar to the previous one, but instead of adding the value from the one-time pad’s sheet, you just need to subtract the value:

Let’s test the decryption. Save and run your code, then type the following into the shell
You should see the encrypted text. To decrypt, just type the following line:

decrypt output




Adding a menu
Although you now have working OTP generation, encryption and decryption, you should make the program a little easier for the user. This should include saving the encrypted text, so that it can be emailed to your friend.

You can begin by defining a new function for the menu:


You’re going to give the user 4 choices in the menu. It should just loop if their choice isn’t 1, 2, 3 or 4:


Next, you can add in the options for the menu, and save their choice as a variable:


If option 1 is chosen, then the user needs to be asked how many sheets they want to generate and how long the sheets should be. These values can then be fed into the generate_otpfunction:


If they choose option 2, then you need to get the name of the sheet they wish to use and the message they want to write. Then the message can be encrypted and saved with a name of their choosing:


If they choose option 3, then you need to get the name of the sheet used to encrypt the file and the name for the file to be decrypted. The file can then be opened, decrypted, and the contents printed out:


If they choose 4 then the program should exit:


You need to reset the choice variable at the end of the function, so that the loop will continue around. Your entire function should now look like this:


To finish off the code, you just need to add a call to the menu() function:





Full code listing
Your full code should look like this:

Use the script to generate an OTP, encrypt a message and then decrypt the same message, to ensure that it’s working correctly. Here’s an example:

script output

 


Using the program
While a one-time pad offers perfect secrecy, you still have to be careful if you want to remain really secure, and there are some issues with this program.

To send encrypted messages to each other, you can use email, SMS or even social media such as Facebook or Twitter. It won’t even matter if your posts are public, as the only person who could decrypt the message is your friend.
Once you’ve generated your OTP, such as by generating 100 sheets, you need to transfer them to the person you want to communicate with. You can’t send them electronically, such as by email, as this is insecure. Probably the most secure method is giving them to your friend on a storage device, such as an SD card or USB flash memory.
The OTP method is only secure if you and your friend keep the OTP secure.
You and your friend need to be sure which OTP you’re using. The best way of doing this is by starting with otp0.txt and then deleting it when you’ve encrypted or decrypted a message. You can then progress to using otp1.txt.
The OTP relies on the randomness of the random number generator. If the generator isn’t truly random, then the OTP could be cracked. Python’s random module is probably not the best way of generating random numbers.
Your message can’t be longer than the length of the sheet from the OTP. If you’re not sure how long your messages will be, it’s better to generate large sheets just in case.

What next?

Can you alter the program so that capital letters are preserved?
Can you alter the program so that punctuation is also encrypted?
Can you make your program delete the sheet from the OTP, once it’s been used to encrypt or decrypt some text?

Read the full article
Porträt von Satoshi Nakamoto

Satoshi Nakamoto

Zur Person

Satoshi Nakamoto