Hi everyone, thanks for the interesting comments so far! personally, I really have no idea have people crack encrypted messages, so that's why I have no idea of knowing whether or not what we have come up with is a good idea. The original code is based on the enigma machine but, unlike the original machine, my code uses all the ASCII characters ranging from ASCII values 32 to 125.
Here is the code and the header file associated with the code:
#include "encryptor.h"
char message[] = "Hello arduino forum!!! this is my secret message";
void setup() {
Serial.begin(57600);
Serial.print(F("Original message: \""));
Serial.print(message);
Serial.println(F("\""));
encrypt(message);
Serial.print(F("Encrypted message: \""));
Serial.print(message);
Serial.println(F("\""));
rotate(rotor, ROTOR_SIZE, -1*(strlen(message)));
encrypt(message);
Serial.print(F("Decrypted message: \""));
Serial.print(message);
Serial.println(F("\""));
}
void loop() {}
and here is the encryptor.h
file:
#ifndef MY_ENC
#define MY_ENC
#define OFFSET 32 //Start of "printable" characters in ASCII table
#define NUM_OF_CHARS 94 //Total num of possible chars (only including printable ones)
#define ROTOR_SIZE (sizeof(rotor)/sizeof(rotor[0]))
byte rotor[NUM_OF_CHARS] = {93, 14, 17, 91, 48, 8, 11, 57, 15, 31, 3, 72, 69, 18, 22, 77, 20, 81, 34, 6, 4, 52, 23, 79, 19, 46, 86, 29, 61, 59, 13, 64, 24, 50, 33, 87, 85, 54, 39, 40, 21, 89, 60, 45, 30, 42, 78, 58, 92, 12, 27, 82, 56, 90, 25, 62, 80, 44, 75, 7, 88, 41, 49, 53, 38, 74, 0, 67, 16, 70, 76, 26, 84, 2, 55, 63, 36, 43, 35, 83, 68, 5, 9, 51, 10, 66, 73, 71, 28, 32, 65, 47, 37, 1};
const byte reflector[NUM_OF_CHARS] = {27, 7, 85, 77, 32, 72, 21, 1, 28, 41, 29, 84, 55, 18, 51, 62, 22, 88, 13, 70, 23, 6, 16, 20, 66, 86, 74, 0, 8, 10, 60, 75, 4, 76, 90, 52, 49, 83, 69, 80, 58, 9, 46, 93, 56, 92, 42, 53, 59, 36, 91, 14, 35, 47, 78, 12, 44, 82, 40, 48, 30, 67, 15, 87, 89, 81, 24, 61, 73, 38, 19, 79, 5, 68, 26, 31, 33, 3, 54, 71, 39, 65, 57, 37, 11, 2, 25, 63, 17, 64, 34, 50, 45, 43};
//Rotates arr by turns times
void rotate(uint8_t *arr, const size_t sz, int turns){
while(turns<0)
turns += sz;
int temp[NUM_OF_CHARS] = {0};
for(unsigned int i = 0;i<sz;i++)
temp[i] = arr[i];
for(unsigned int i = 0;i<sz;i++)
arr[i] = temp[(i+turns)%sz];
return;
}
//I know arduino has built in String functions, but I avoid using String variables to avoid memory issues down the line
int indexOf(const byte *arr, const size_t sz, const int x){
for(unsigned int i = 0;i<sz;i++)
if(arr[i] == x)
return i;
return -1;
}
// encode character:
// character in -> rotor -> reflector -> rotor -> character out
// reflector array and indexOf function ensure that the same message can be reversed to get original message
// if char is outside of ASCII vals 32 to 125 then just ignore it
char encodeChar(const char c){
return ((c < OFFSET ||c > (OFFSET + NUM_OF_CHARS + 1)) ? c : OFFSET + indexOf(rotor, ROTOR_SIZE, reflector[rotor[c - OFFSET]]));
}
//encrypt *m string. After encoding a character,
//rotate rotor by 1 to ensure characters don't repeat
void encrypt(char *m){
for(unsigned int i = 0;m[i]!='\0';i++){
m[i] = encodeChar(m[i]);
rotate(rotor,ROTOR_SIZE,1);
}
return;
}
#endif //MY_ENC
After running the code, the output in my Serial terminal looks like this:
So the code works exactly as I hoped.
The reason I think that this will be hard to crack is that the only way someone could get the Encrypted message back to the original is if they knew the arrays rotor[] = {...
and refelector[] = {...
. Creating these arrays is not too difficult and, just like the original Enigma machine, the header file could have multiple rotors, or the rotor array itself could be generated randomly based on the date or whatever.
I am aware that the algorithm cannot return a character as itself (i.e. 'c' will never be encoded to 'c' and 'Z' will never be encoded to 'Z' and so on), but I believe that this is not an issue unless people can make educated guesses as to what I might be saying...