I love puzzles – in particular, I love puzzles that involve cryptography.
I'm always looking for a way to teach difficult concepts in classroom settings, especially if I can lean on the confluence of my love of tinkering and my love of puzzles.
I bought a new house several months ago and it has a garage. I don't want to buy new garage remotes (that would be much too easy) when I can build them out of parts that SparkFun sells everyday. The thought occurred to me that it would be fun to do in encrypted wireless using an XBee module; that way I could program not only commands for the garage door, but for lights and the front door and anything else that I can put on electronic control.
At the heart of the way we do business on the web is RSA encryption. RSA is a brilliant and complicated way to encrypt information using large prime numbers. As many of us can remember from algebra, the prime factorization of large numbers can be very difficult. RSA relies on using this within a framework of modular exponentiation and totient equations to pass information safely.
All of this is very effective for secure banking transactions, but probably not necessary for turning on lights at my house.
When I started thinking about this problem I did, however, take some of the way we think about RSA encryption and applied it to a simple Arduino program. Here is how I thought about my problem:
Using an Arduino base station to store an array of three-digit numbers.
Use the random function in Arduino to generate a random number, store it in a variable and subtract it from a random place in the array.
Pass the place in the array and difference generated to a client device as values separated by commas.
If the client device has the matching array as the base station, it will subtract the number it received from the specific place in the array, and pass the difference back to the base station.
The base station will add the answer it receives from the requesting device to the number stored in the variable. If the sum of these two things is equivalent to the place in the array that the base station has been working with, it will grant access to the client device.
Let's look at this in action!
My array = {103,147,171,199}
My random number generated = 59
My random pace in the array = 2
So: 171-59 = 112
I pass to a device requesting access (2,112).
If that device has the same array stored on it as my key array on the base station, it will subtract what it received from the specified place in the array.
171-112 = 59
I send back to the base station a request (like the character “r”) and 59, so the transmission would be (r,59).
The base station then adds the number it receives - if that number and the number it sent are equivalent to the value in that place in the array, it grants the request. In my Arduino code I have set it up so that our lights are red LEDs.
Here’s some Arduino code; test it with the serial terminal.
///////////////////////
int keys[]=
{117,161,173,187,199};
int arryPos=0;
char request;
int arrayPos;
int subtractNum;
int returnVal;
int red=0;
int blue=0;
int green=0;
void setup()
{
Serial.begin(9600);
pinMode(13,OUTPUT);
pinMode(12,OUTPUT);
pinMode(11,OUTPUT);
pinMode(10,OUTPUT);
pinMode(9,OUTPUT);
}
void loop()
{
//subtractNum=10;
if(Serial.available()!=0)
{
request= Serial.read();
digitalWrite(13, HIGH);
if(request=='a')
{
arrayPos=(random(0,4));
subtractNum=(random(1,100));
delay(10);
Serial.print(arrayPos);
Serial.print(",");
Serial.println(keys[arrayPos]-subtractNum);
}
if(request=='r')
{
returnVal=Serial.parseInt();
Serial.print("array val =");
Serial.println(keys[arrayPos]);
Serial.print(returnVal + keys[arrayPos]-subtractNum);//subtractNum=10+ x = 117
delay(50);
if(returnVal + keys[arrayPos]-subtractNum==keys[arrayPos])
{
digitalWrite(9,HIGH);
delay(350);
digitalWrite(9,LOW);
delay(350);
digitalWrite(9,HIGH);
delay(350);
digitalWrite(9,LOW);
delay(350);
digitalWrite(9,HIGH);
delay(350);
digitalWrite(9,LOW);
delay(350);
}
}
}
digitalWrite(13,LOW);
}
//////////////////////
When you get this code loaded to the Arduino, you can then follow these steps:
The next step is creating a device to send the serial commands. This could be another Arduino, and this is where it really opens up. The client could be a traditional remote with push-button function, or a keypad, or even a fingerprint reader.
I think the classroom applications of this project are particularly interesting. The idea I had was to let students “tune into” the traffic being passed back and forth, and try to figure out the key array based on the behavior of the packets – seems like a great hacking/cryptography prompt.
I am adding code to my GitHub page, so you are welcome to dig around there and take this further. Happy hacking!