Arduino Bluetooth клавиатура с шифрованием Speck

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017
Приветствую!
 
Задумался я как то после разговора с шефом, который пожаловался что
никакой конспирации в сети не осталось, о создании железки для шифрования
переписки в интернете. После поисков остановил свой выбор на алгоритме 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,
библиотека на Паскале, и программа декодирования для ПК.
 
 
andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017
001#include <EEPROM.h>
002// address 0..7 - Crypto KEY
003// address 8..183 - Generated Key 0..21
004#include <SoftwareSerial.h>
005#include <PS2Keyboard.h>
006#include <LiquidCrystal_1602_RUS.h>
007#include <Speck.h>
008 
009#define BTRXD 11 // orange
010#define BTTXD 12 // yellow
011#define BTSTATUS A5 // red
012// BT - GND green +5V blue
013 
014const int PS2DataPin = 2; // white
015const int PS2IRQpin =  3; // yellow
016// PS2 - GND blue +5V red
017 
018PS2Keyboard KBD;
019 
020SoftwareSerial BT(BTTXD, BTRXD);
021Speck speck;
022 
023LiquidCrystal_1602_RUS LCD(8, 9, 4, 5, 6, 7 );//For LCD Keypad Shield
024 
025word BufBlock32[2] = {0x0, 0x0};
026byte IndexBufBlock = 0; // 0..3 bytes
027byte WorkMode = 0;
028// 0 - encode all bytes and Send HEX crypto text to BT
029// 1 - enter crypto key
030// 2 - without crypt - send byte to BT
031// 3 - encode test text
032byte Buf1byte[2];
033byte IndexEnterKey = 0; // 0...15 char = 0..7 bytes
034boolean setfc = false;
035boolean entfc = false;
036boolean EngKeys = true;
037byte 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};
038byte IdxLCD = 0; // 0..31 - char on LCD
039 
040void setup() {
041  delay(1000);
042  // put your setup code here, to run once:
043  KBD.begin(PS2DataPin, PS2IRQpin);
044  pinMode(LED_BUILTIN, OUTPUT);
045  digitalWrite(LED_BUILTIN, LOW);
046  Serial.begin(9600);
047  BT.begin(9600);
048  KBD.clear;
049  LCD.begin(16, 2);
050  LCD.clear();
051  LCD.setCursor(0, 0);
052  SendTextToLCD("Ready ");
053  SendByteToLCD(195, false);
054  SendByteToLCD(238, false);
055  SendByteToLCD(242, false);
056  SendByteToLCD(238, false);
057  SendByteToLCD(226, false);
058  SendByteToLCD(32, true);
059  SendTextToLCD("Ready ");
060  SendByteToLCD(195, false);
061  SendByteToLCD(238, false);
062  SendByteToLCD(242, false);
063  SendByteToLCD(238, false);
064  SendByteToLCD(226, false);
065  SendByteToLCD(32, true);
066  if (EngKeys == true) {
067    Serial.println("KEYS = English");
068    SendTextToLCD("ENG ");
069  }
070  LCD.cursor();
071  LCD.blink();
072}
073 
074byte RusKeyTo1251(byte inByte) {
075  switch (inByte) {
076    case 126 : {
077        return 168;
078        break;
079      }
080    case 96 : {
081        return 184;
082        break;
083      }
084    default: {
085        for (int i = 0; i <= 63; ++i) {
086          if (inByte == Rus1251keys[i]) {
087            return (i + 192);
088          }
089        }
090        return inByte;
091      }
092  }
093}
094 
095String byteToHEXstr(byte inByte) {
096  byte p1 = inByte >> 4;
097  byte p2 = inByte % 16;
098  String s1, s2;
099  if (p1 > 9) {
100    s1 = char(p1 + 0x37);
101  } else {
102    s1 = char(p1 + 0x30);
103  }
104  if (p2 > 9) {
105    s2 = char(p2 + 0x37);
106  } else {
107    s2 = char(p2 + 0x30);
108  }
109  return (s1 + s2);
110}
111 
112String wordToHEXstr(word inWord) {
113  word p1 = inWord >> 8;
114  word p2 = inWord % 256;
115  String s1, s2;
116  s1 = byteToHEXstr(p1);
117  s2 = byteToHEXstr(p2);
118  return (s1 + s2);
119}
120 
121// send win1251 byte to LCD
122void SendByteToLCD(byte inByte, boolean ET) {
123  if (inByte == 13) {
124    if (IdxLCD < 16) {
125      LCD.setCursor(0, 1);
126      LCD.print("                ");
127      LCD.setCursor(0, 1);
128      IdxLCD = 16;
129    } else {
130      LCD.setCursor(0, 0);
131      LCD.print("                ");
132      LCD.setCursor(0, 0);
133      IdxLCD = 0;
134    }
135    return;
136  }
137  if (ET == false) {
138    if ((inByte == 168) || (inByte == 184) || ((inByte >= 192) && (inByte <= 255))) {
139      LCD.print(LCD.asciiutf8(inByte));
140    } else {
141      LCD.print(char(inByte));
142    }
143  } else {
144    LCD.print(char(inByte));
145  }
146  switch (IdxLCD) {
147    case 15: {
148        LCD.setCursor(0, 1);
149        LCD.print("                ");
150        LCD.setCursor(0, 1);
151        ++IdxLCD;
152        break;
153      }
154    case 31: {
155        LCD.setCursor(0, 0);
156        LCD.print("                ");
157        LCD.setCursor(0, 0);
158        IdxLCD = 0;
159        break;
160      }
161    default : {
162        ++IdxLCD;
163      }
164  }
165}
166 
167// send text to LCD
168void SendTextToLCD(String s) {
169  for (int i = 0 ; i < s.length(); ++i) {
170    SendByteToLCD(s[i], true);
171  }
172}
173 
174// send byte to crypto
175void SendByteToOUT(byte inByte) {
176  // save to buffer
177  switch (IndexBufBlock) {
178    case 0 : {
179        word ww = BufBlock32[0];
180        ww = ww << 8;
181        ww = ww >> 8;
182        BufBlock32[0] = ww + (inByte * 256);
183        ++IndexBufBlock;
184        break;
185      }
186    case 1 : {
187        word ww = BufBlock32[0];
188        ww = ww >> 8;
189        ww = ww << 8;
190        BufBlock32[0] = ww + inByte;
191        ++IndexBufBlock;
192        break;
193      }
194    case 2 : {
195        word ww = BufBlock32[1];
196        ww = ww << 8;
197        ww = ww >> 8;
198        BufBlock32[1] = ww + (inByte * 256);
199        ++IndexBufBlock;
200        break;
201      }
202    case 3 : {
203        word ww = BufBlock32[1];
204        ww = ww >> 8;
205        ww = ww << 8;
206        BufBlock32[1] = ww + inByte;
207        IndexBufBlock = 0;
208        // - crypt and send block
209        speck.EnCrypt_32_64(BufBlock32);
210        Serial.print(wordToHEXstr(BufBlock32[0])); Serial.print(' '); Serial.println(wordToHEXstr(BufBlock32[1]));
211        if (analogRead(BTSTATUS) > 500) {
212          BT.print(wordToHEXstr(BufBlock32[0])); BT.print(' '); BT.println(wordToHEXstr(BufBlock32[1]));
213        }
214        //--
215        break;
216      }
217  }
218}
219 
220// operate press key
221void InputKey(byte inByte)
222{
223  // - select function key
224  switch (inByte) {
225    case PS2_ESC : {
226        Serial.println();
227        Serial.println("Main mode is ON");
228        WorkMode = 0;
229        setfc = true;
230        SendTextToLCD(" Ready ");
231        break;
232      }
233    case 0xC3 : {
234        setfc = true;
235        entfc = true;
236        break;
237      }
238    case 0xBA : {
239        if (entfc != true) {
240          break;
241        }
242        Serial.println();
243        Serial.println("Encode test text");
244        WorkMode = 3;
245        setfc = true;
246        entfc = false;
247        SendTextToLCD(" Test crypto ");
248        break;
249      }
250    case 0xBB : {
251        if (entfc != true) {
252          break;
253        }
254        Serial.println();
255        Serial.println("NO CRYPT!!! jast send text");
256        WorkMode = 2;
257        setfc = true;
258        entfc = false;
259        SendTextToLCD(" OFF ");
260        break;
261      }
262    case 0xBC : {
263        if (entfc != true) {
264          break;
265        }
266        Serial.println();
267        EngKeys = !EngKeys;
268        if (EngKeys == true) {
269          Serial.println("KEYS = English");
270          SendTextToLCD(" ENG ");
271        } else {
272          Serial.println("KEYS = Russian");
273          SendTextToLCD(" RUS ");
274        }
275        setfc = true;
276        entfc = false;
277        delay(500);
278        break;
279      }
280    case 0xBD : {
281        if (entfc != true) {
282          break;
283        }
284        Serial.println();
285        Serial.println("Enter crypto key");
286        WorkMode = 1;
287        setfc = true;
288        entfc = false;
289        SendTextToLCD(" Enter Key ");
290        break;
291      }
292    default: {
293        setfc = false;
294        entfc = false;
295      }
296  }
297  if (setfc == true) {
298    return;
299  }
300  // -
301  switch (WorkMode) {
302    case 1 : {
303        if (((inByte >= 0x30) && (inByte <= 0x39)) || ((inByte >= 0x41) && (inByte <= 0x46))  || ((inByte >= 0x61) && (inByte <= 0x66))) {
304          byte bb;
305          if ((inByte >= 0x30) && (inByte <= 0x39)) {
306            bb = inByte - 0x30;
307          }
308          if ((inByte >= 0x41) && (inByte <= 0x46)) {
309            bb = inByte - 0x37;
310          }
311          if ((inByte >= 0x61) && (inByte <= 0x66)) {
312            bb = inByte - 0x57;
313          }
314          if (((IndexEnterKey + 2) % 2) == 0) {
315            Buf1byte[0] = bb;
316          } else {
317            Buf1byte[1] = bb;
318            EEPROM.write((IndexEnterKey / 2), ((Buf1byte[0] * 16) + (Buf1byte[1])));
319          }
320          ++IndexEnterKey;
321        }
322        if (IndexEnterKey > 15) {
323          IndexEnterKey = 0;
324          WorkMode = 0;
325          speck.Generate22keys();
326          Serial.print("NewKey = ");
327          for (int i = 0 ; i <= 7 ; ++i) {
328            Serial.print(byteToHEXstr(EEPROM.read(i)));
329          }
330          Serial.println();
331          SendTextToLCD(" Ready ");
332        }
333        break;
334      }
335    case 2 : {
336        // convert rus key to win1251
337        if (EngKeys == false) {
338          inByte = RusKeyTo1251(inByte);
339        }
340        SendByteToLCD(inByte, EngKeys);
341        // convert WIN1251 to UTF-8
342        if (inByte > 127) {
343          if ((inByte == 168) || (inByte == 184) || ((inByte >= 192) && (inByte <= 255))) {
344            word ww;
345            switch  (inByte)  {
346              case 168 : {
347                  ww =  53349;
348                  break;
349                }
350              case 184 : {
351                  ww =  53649;
352                  break;
353                }
354              default : {
355                  if (inByte <= 239 ) {
356                    ww = 53200 + inByte;
357                  } else {
358                    ww = 53392 + inByte;
359                  }
360                }
361            }
362            byte bb = ww >> 8;
363            Serial.write(bb);
364            if (analogRead(BTSTATUS) > 500) {
365              BT.write(bb);
366            }
367            bb = ww % 256;
368            Serial.write(bb);
369            if (analogRead(BTSTATUS) > 500) {
370              BT.write(bb);
371            }
372          } else {
373            Serial.write(inByte);
374            if (analogRead(BTSTATUS) > 500) {
375              BT.write(inByte);
376            }
377          }
378        } else {
379          Serial.write(inByte);
380          if (analogRead(BTSTATUS) > 500) {
381            BT.write(inByte);
382          }
383        }
384        break;
385      }
386    case 3 : {
387        BufBlock32[0] = 0x6574;
388        BufBlock32[1] = 0x694C;
389        Serial.print("Test Encode Block = "); Serial.print(wordToHEXstr(BufBlock32[0])); Serial.print(' '); Serial.println(wordToHEXstr(BufBlock32[1]));
390        speck.EnCrypt_32_64(BufBlock32);
391        Serial.print("Result Block = "); Serial.print(wordToHEXstr(BufBlock32[0])); Serial.print(' '); Serial.println(wordToHEXstr(BufBlock32[1]));
392        SendTextToLCD(wordToHEXstr(BufBlock32[0]));
393        SendTextToLCD("  ");
394        SendTextToLCD(wordToHEXstr(BufBlock32[1]));
395        WorkMode = 0;
396        SendTextToLCD(" Ready ");
397        break;
398      }
399    default : {
400        // mode 0
401        // convert rus key to win1251
402        if (EngKeys == false) {
403          inByte = RusKeyTo1251(inByte);
404        }
405        SendByteToLCD(inByte, EngKeys);
406        // convert WIN1251 to UTF-8
407        if (inByte > 127) {
408          if ((inByte == 168) || (inByte == 184) || ((inByte >= 192) && (inByte <= 255))) {
409            word ww;
410            switch  (inByte)  {
411              case 168 : {
412                  ww =  53349;
413                  break;
414                }
415              case 184 : {
416                  ww =  53649;
417                  break;
418                }
419              default : {
420                  if (inByte <= 239 ) {
421                    ww = 53200 + inByte;
422                  } else {
423                    ww = 53392 + inByte;
424                  }
425                }
426            }
427            byte bb = ww >> 8;
428            SendByteToOUT(bb);
429            bb = ww % 256;
430            SendByteToOUT(bb);
431          } else {
432            SendByteToOUT(inByte);
433          }
434        } else {
435          SendByteToOUT(inByte);
436        }
437        // - end mode 0
438      }
439  }
440}
441 
442void loop() {
443  // put your main code here, to run repeatedly:
444  // wait press keys
445  if (KBD.available())
446    while (KBD.available()) {
447      byte bb = KBD.read();
448      //Serial.print(bb); Serial.print(' '); Serial.println(RusKeyTo1251(bb));
449      InputKey(bb);
450      delay(50);
451    }
452  /*// - test Crypro functions
453    Serial.println("test key FFFF FFFF FFFF FFFF");
454    for (int i = 0 ; i <= 7 ; ++i)
455    {
456    EEPROM.write(i, 255);
457    }
458    Serial.println("gen 22 keys");
459    speck.Generate22keys();
460    speck.ShowToSerial22keys();
461    Serial.println("un gen 22 keys");
462    speck.UnGenerate22keys();
463    speck.ShowToSerial22keys();
464    Serial.println("test block = FFFF FFFF");
465    word Block32[2] = {0xFFFF, 0xFFFF};
466    speck.EnCrypt_32_64(Block32);
467    Serial.print("result encrypt = "); Serial.print(Block32[0], HEX); Serial.print(' '); Serial.println(Block32[1], HEX);
468    speck.DeCrypt_32_64(Block32);
469    Serial.print("result decrypt = "); Serial.print(Block32[0], HEX); Serial.print(' '); Serial.println(Block32[1], HEX);
470    Serial.println("test key 1918 1110 0908 0100");
471    EEPROM.write(0, 0x19); EEPROM.write(1, 0x18);
472    EEPROM.write(2, 0x11); EEPROM.write(3, 0x10);
473    EEPROM.write(4, 0x09); EEPROM.write(5, 0x08);
474    EEPROM.write(6, 0x01); EEPROM.write(7, 0x00);
475    speck.Generate22keys();
476    Serial.println("test block = 6574 694C");
477    Block32[0] = 0x6574;
478    Block32[1] = 0x694C;
479    speck.EnCrypt_32_64(Block32);
480    Serial.print("result encrypt = "); Serial.print(Block32[0], HEX); Serial.print(' '); Serial.println(Block32[1], HEX);
481    speck.DeCrypt_32_64(Block32);
482    Serial.print("result decrypt = "); Serial.print(Block32[0], HEX); Serial.print(' '); Serial.println(Block32[1], HEX);
483    delay(20000);*/
484  /*// - test connection and configure BT device
485    // - by AT command
486    if (analogRead(BTSTATUS) > 500) {
487    digitalWrite(LED_BUILTIN, HIGH);
488    //BT.println("AT"); // AT+ORGL AT+ROLE=0 AT+UART=9600,0,0 AT+NAME=BTKEYS AT+PSWD=****
489    } else {
490    digitalWrite(LED_BUILTIN, LOW);
491    }
492    if (Serial.available()) {
493    while (Serial.available()) {
494      BT.write(Serial.read());
495      delay(10);
496    }
497    }
498    if (BT.available()) {
499    while (BT.available()) {
500      Serial.write(BT.read());
501      delay(10);
502    }
503    }
504    // - end test and configure BT*/
505}