Arduino Bluetooth клавиатура с шифрованием Speck
- Войдите на сайт для отправки комментариев
Пт, 08/09/2017 - 18:33
Приветствую!
Задумался я как то после разговора с шефом, который пожаловался что
никакой конспирации в сети не осталось, о создании железки для шифрования
переписки в интернете. После поисков остановил свой выбор на алгоритме Speck.
В библиотеке реализовал самую слабую комбинацию алгоритма,
32 бита блок шифрования, 64 бита ключ. Думал мощности Arduino будет не хватать,
оказалось что всего хватает и для параноиков можно увеличить алгоритм
до максимума Speck 128/256.
Для реализации мне понадобилось: Arduino UNO, LCD Keypad shield, HC-05.
К Arduino подключена PS/2 клавиатура, все набираемые символы отображаются
на LCD дисплее, подключив HC-05 к Android смартфону и используя любой
BT Terminal (я использую Serial Bluetooth Terminal т.к. он умеет весь
выводимый текст отправлять или копировать) мы получаем шестнадцатиричный текст,
который например отправляем по почте и потом расшифровываем.
С клавиатуры выбираются режимы работы:
Escape - основной режим шифрования (по умолчанию) - на дисплее Ready
F1 - шифрование тестового блока из документации по Speck
F3 - нет шифрования - все набираемые символы идут в Bluetooth
в кодировке русских символов UTF-8 - на дисплее OFF
F8 - переключение русский/английский - на дисплее RUS/ENG
F12 - ввод ключа шифрования - Enter key на дисплее - система
ждет ввода 16 шестнацатиричных символов (0..9,a..f) - 8 байт
Ниже ссылка на Гугл диск - библиотека Speck для Arduino,
библиотека на Паскале, и программа декодирования для ПК.



#include <EEPROM.h> // address 0..7 - Crypto KEY // address 8..183 - Generated Key 0..21 #include <SoftwareSerial.h> #include <PS2Keyboard.h> #include <LiquidCrystal_1602_RUS.h> #include <Speck.h> #define BTRXD 11 // orange #define BTTXD 12 // yellow #define BTSTATUS A5 // red // BT - GND green +5V blue const int PS2DataPin = 2; // white const int PS2IRQpin = 3; // yellow // PS2 - GND blue +5V red PS2Keyboard KBD; SoftwareSerial BT(BTTXD, BTRXD); Speck speck; LiquidCrystal_1602_RUS LCD(8, 9, 4, 5, 6, 7 );//For LCD Keypad Shield word BufBlock32[2] = {0x0, 0x0}; byte IndexBufBlock = 0; // 0..3 bytes byte WorkMode = 0; // 0 - encode all bytes and Send HEX crypto text to BT // 1 - enter crypto key // 2 - without crypt - send byte to BT // 3 - encode test text byte Buf1byte[2]; byte IndexEnterKey = 0; // 0...15 char = 0..7 bytes boolean setfc = false; boolean entfc = false; boolean EngKeys = true; byte Rus1251keys[66] = {70, 60, 68, 85, 76, 84, 58, 80, 66, 81, 82, 75, 86, 89, 74, 71, 72, 67, 78, 69, 65, 123, 87, 88, 73, 79, 125, 83, 77, 34, 62, 90, 102, 44, 100, 117, 108, 116, 59, 112, 98, 113, 114, 107, 118, 121, 106, 103, 104, 99, 110, 101, 97, 91, 119, 120, 105, 111, 93, 115, 109, 39, 46, 122}; byte IdxLCD = 0; // 0..31 - char on LCD void setup() { delay(1000); // put your setup code here, to run once: KBD.begin(PS2DataPin, PS2IRQpin); pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, LOW); Serial.begin(9600); BT.begin(9600); KBD.clear; LCD.begin(16, 2); LCD.clear(); LCD.setCursor(0, 0); SendTextToLCD("Ready "); SendByteToLCD(195, false); SendByteToLCD(238, false); SendByteToLCD(242, false); SendByteToLCD(238, false); SendByteToLCD(226, false); SendByteToLCD(32, true); SendTextToLCD("Ready "); SendByteToLCD(195, false); SendByteToLCD(238, false); SendByteToLCD(242, false); SendByteToLCD(238, false); SendByteToLCD(226, false); SendByteToLCD(32, true); if (EngKeys == true) { Serial.println("KEYS = English"); SendTextToLCD("ENG "); } LCD.cursor(); LCD.blink(); } byte RusKeyTo1251(byte inByte) { switch (inByte) { case 126 : { return 168; break; } case 96 : { return 184; break; } default: { for (int i = 0; i <= 63; ++i) { if (inByte == Rus1251keys[i]) { return (i + 192); } } return inByte; } } } String byteToHEXstr(byte inByte) { byte p1 = inByte >> 4; byte p2 = inByte % 16; String s1, s2; if (p1 > 9) { s1 = char(p1 + 0x37); } else { s1 = char(p1 + 0x30); } if (p2 > 9) { s2 = char(p2 + 0x37); } else { s2 = char(p2 + 0x30); } return (s1 + s2); } String wordToHEXstr(word inWord) { word p1 = inWord >> 8; word p2 = inWord % 256; String s1, s2; s1 = byteToHEXstr(p1); s2 = byteToHEXstr(p2); return (s1 + s2); } // send win1251 byte to LCD void SendByteToLCD(byte inByte, boolean ET) { if (inByte == 13) { if (IdxLCD < 16) { LCD.setCursor(0, 1); LCD.print(" "); LCD.setCursor(0, 1); IdxLCD = 16; } else { LCD.setCursor(0, 0); LCD.print(" "); LCD.setCursor(0, 0); IdxLCD = 0; } return; } if (ET == false) { if ((inByte == 168) || (inByte == 184) || ((inByte >= 192) && (inByte <= 255))) { LCD.print(LCD.asciiutf8(inByte)); } else { LCD.print(char(inByte)); } } else { LCD.print(char(inByte)); } switch (IdxLCD) { case 15: { LCD.setCursor(0, 1); LCD.print(" "); LCD.setCursor(0, 1); ++IdxLCD; break; } case 31: { LCD.setCursor(0, 0); LCD.print(" "); LCD.setCursor(0, 0); IdxLCD = 0; break; } default : { ++IdxLCD; } } } // send text to LCD void SendTextToLCD(String s) { for (int i = 0 ; i < s.length(); ++i) { SendByteToLCD(s[i], true); } } // send byte to crypto void SendByteToOUT(byte inByte) { // save to buffer switch (IndexBufBlock) { case 0 : { word ww = BufBlock32[0]; ww = ww << 8; ww = ww >> 8; BufBlock32[0] = ww + (inByte * 256); ++IndexBufBlock; break; } case 1 : { word ww = BufBlock32[0]; ww = ww >> 8; ww = ww << 8; BufBlock32[0] = ww + inByte; ++IndexBufBlock; break; } case 2 : { word ww = BufBlock32[1]; ww = ww << 8; ww = ww >> 8; BufBlock32[1] = ww + (inByte * 256); ++IndexBufBlock; break; } case 3 : { word ww = BufBlock32[1]; ww = ww >> 8; ww = ww << 8; BufBlock32[1] = ww + inByte; IndexBufBlock = 0; // - crypt and send block speck.EnCrypt_32_64(BufBlock32); Serial.print(wordToHEXstr(BufBlock32[0])); Serial.print(' '); Serial.println(wordToHEXstr(BufBlock32[1])); if (analogRead(BTSTATUS) > 500) { BT.print(wordToHEXstr(BufBlock32[0])); BT.print(' '); BT.println(wordToHEXstr(BufBlock32[1])); } //-- break; } } } // operate press key void InputKey(byte inByte) { // - select function key switch (inByte) { case PS2_ESC : { Serial.println(); Serial.println("Main mode is ON"); WorkMode = 0; setfc = true; SendTextToLCD(" Ready "); break; } case 0xC3 : { setfc = true; entfc = true; break; } case 0xBA : { if (entfc != true) { break; } Serial.println(); Serial.println("Encode test text"); WorkMode = 3; setfc = true; entfc = false; SendTextToLCD(" Test crypto "); break; } case 0xBB : { if (entfc != true) { break; } Serial.println(); Serial.println("NO CRYPT!!! jast send text"); WorkMode = 2; setfc = true; entfc = false; SendTextToLCD(" OFF "); break; } case 0xBC : { if (entfc != true) { break; } Serial.println(); EngKeys = !EngKeys; if (EngKeys == true) { Serial.println("KEYS = English"); SendTextToLCD(" ENG "); } else { Serial.println("KEYS = Russian"); SendTextToLCD(" RUS "); } setfc = true; entfc = false; delay(500); break; } case 0xBD : { if (entfc != true) { break; } Serial.println(); Serial.println("Enter crypto key"); WorkMode = 1; setfc = true; entfc = false; SendTextToLCD(" Enter Key "); break; } default: { setfc = false; entfc = false; } } if (setfc == true) { return; } // - switch (WorkMode) { case 1 : { if (((inByte >= 0x30) && (inByte <= 0x39)) || ((inByte >= 0x41) && (inByte <= 0x46)) || ((inByte >= 0x61) && (inByte <= 0x66))) { byte bb; if ((inByte >= 0x30) && (inByte <= 0x39)) { bb = inByte - 0x30; } if ((inByte >= 0x41) && (inByte <= 0x46)) { bb = inByte - 0x37; } if ((inByte >= 0x61) && (inByte <= 0x66)) { bb = inByte - 0x57; } if (((IndexEnterKey + 2) % 2) == 0) { Buf1byte[0] = bb; } else { Buf1byte[1] = bb; EEPROM.write((IndexEnterKey / 2), ((Buf1byte[0] * 16) + (Buf1byte[1]))); } ++IndexEnterKey; } if (IndexEnterKey > 15) { IndexEnterKey = 0; WorkMode = 0; speck.Generate22keys(); Serial.print("NewKey = "); for (int i = 0 ; i <= 7 ; ++i) { Serial.print(byteToHEXstr(EEPROM.read(i))); } Serial.println(); SendTextToLCD(" Ready "); } break; } case 2 : { // convert rus key to win1251 if (EngKeys == false) { inByte = RusKeyTo1251(inByte); } SendByteToLCD(inByte, EngKeys); // convert WIN1251 to UTF-8 if (inByte > 127) { if ((inByte == 168) || (inByte == 184) || ((inByte >= 192) && (inByte <= 255))) { word ww; switch (inByte) { case 168 : { ww = 53349; break; } case 184 : { ww = 53649; break; } default : { if (inByte <= 239 ) { ww = 53200 + inByte; } else { ww = 53392 + inByte; } } } byte bb = ww >> 8; Serial.write(bb); if (analogRead(BTSTATUS) > 500) { BT.write(bb); } bb = ww % 256; Serial.write(bb); if (analogRead(BTSTATUS) > 500) { BT.write(bb); } } else { Serial.write(inByte); if (analogRead(BTSTATUS) > 500) { BT.write(inByte); } } } else { Serial.write(inByte); if (analogRead(BTSTATUS) > 500) { BT.write(inByte); } } break; } case 3 : { BufBlock32[0] = 0x6574; BufBlock32[1] = 0x694C; Serial.print("Test Encode Block = "); Serial.print(wordToHEXstr(BufBlock32[0])); Serial.print(' '); Serial.println(wordToHEXstr(BufBlock32[1])); speck.EnCrypt_32_64(BufBlock32); Serial.print("Result Block = "); Serial.print(wordToHEXstr(BufBlock32[0])); Serial.print(' '); Serial.println(wordToHEXstr(BufBlock32[1])); SendTextToLCD(wordToHEXstr(BufBlock32[0])); SendTextToLCD(" "); SendTextToLCD(wordToHEXstr(BufBlock32[1])); WorkMode = 0; SendTextToLCD(" Ready "); break; } default : { // mode 0 // convert rus key to win1251 if (EngKeys == false) { inByte = RusKeyTo1251(inByte); } SendByteToLCD(inByte, EngKeys); // convert WIN1251 to UTF-8 if (inByte > 127) { if ((inByte == 168) || (inByte == 184) || ((inByte >= 192) && (inByte <= 255))) { word ww; switch (inByte) { case 168 : { ww = 53349; break; } case 184 : { ww = 53649; break; } default : { if (inByte <= 239 ) { ww = 53200 + inByte; } else { ww = 53392 + inByte; } } } byte bb = ww >> 8; SendByteToOUT(bb); bb = ww % 256; SendByteToOUT(bb); } else { SendByteToOUT(inByte); } } else { SendByteToOUT(inByte); } // - end mode 0 } } } void loop() { // put your main code here, to run repeatedly: // wait press keys if (KBD.available()) while (KBD.available()) { byte bb = KBD.read(); //Serial.print(bb); Serial.print(' '); Serial.println(RusKeyTo1251(bb)); InputKey(bb); delay(50); } /*// - test Crypro functions Serial.println("test key FFFF FFFF FFFF FFFF"); for (int i = 0 ; i <= 7 ; ++i) { EEPROM.write(i, 255); } Serial.println("gen 22 keys"); speck.Generate22keys(); speck.ShowToSerial22keys(); Serial.println("un gen 22 keys"); speck.UnGenerate22keys(); speck.ShowToSerial22keys(); Serial.println("test block = FFFF FFFF"); word Block32[2] = {0xFFFF, 0xFFFF}; speck.EnCrypt_32_64(Block32); Serial.print("result encrypt = "); Serial.print(Block32[0], HEX); Serial.print(' '); Serial.println(Block32[1], HEX); speck.DeCrypt_32_64(Block32); Serial.print("result decrypt = "); Serial.print(Block32[0], HEX); Serial.print(' '); Serial.println(Block32[1], HEX); Serial.println("test key 1918 1110 0908 0100"); EEPROM.write(0, 0x19); EEPROM.write(1, 0x18); EEPROM.write(2, 0x11); EEPROM.write(3, 0x10); EEPROM.write(4, 0x09); EEPROM.write(5, 0x08); EEPROM.write(6, 0x01); EEPROM.write(7, 0x00); speck.Generate22keys(); Serial.println("test block = 6574 694C"); Block32[0] = 0x6574; Block32[1] = 0x694C; speck.EnCrypt_32_64(Block32); Serial.print("result encrypt = "); Serial.print(Block32[0], HEX); Serial.print(' '); Serial.println(Block32[1], HEX); speck.DeCrypt_32_64(Block32); Serial.print("result decrypt = "); Serial.print(Block32[0], HEX); Serial.print(' '); Serial.println(Block32[1], HEX); delay(20000);*/ /*// - test connection and configure BT device // - by AT command if (analogRead(BTSTATUS) > 500) { digitalWrite(LED_BUILTIN, HIGH); //BT.println("AT"); // AT+ORGL AT+ROLE=0 AT+UART=9600,0,0 AT+NAME=BTKEYS AT+PSWD=**** } else { digitalWrite(LED_BUILTIN, LOW); } if (Serial.available()) { while (Serial.available()) { BT.write(Serial.read()); delay(10); } } if (BT.available()) { while (BT.available()) { Serial.write(BT.read()); delay(10); } } // - end test and configure BT*/ }