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,
библиотека на Паскале, и программа декодирования для ПК.



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
014
const
int
PS2DataPin = 2;
// white
015
const
int
PS2IRQpin = 3;
// yellow
016
// PS2 - GND blue +5V red
017
018
PS2Keyboard KBD;
019
020
SoftwareSerial BT(BTTXD, BTRXD);
021
Speck speck;
022
023
LiquidCrystal_1602_RUS LCD(8, 9, 4, 5, 6, 7 );
//For LCD Keypad Shield
024
025
word BufBlock32[2] = {0x0, 0x0};
026
byte
IndexBufBlock = 0;
// 0..3 bytes
027
byte
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
032
byte
Buf1byte[2];
033
byte
IndexEnterKey = 0;
// 0...15 char = 0..7 bytes
034
boolean setfc =
false
;
035
boolean entfc =
false
;
036
boolean EngKeys =
true
;
037
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};
038
byte
IdxLCD = 0;
// 0..31 - char on LCD
039
040
void
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
074
byte
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
095
String 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
112
String 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
122
void
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
168
void
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
175
void
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
221
void
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
442
void
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
}