arduino/enigma/enigma.ino
2017-11-05 18:30:54 +01:00

442 lines
7.7 KiB
C++

// Copyright (C) 2017 Marius Schellenberger
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <LiquidCrystal_I2C.h>
/* Display
GND (Display) -> GND (Arduino UNO)
VCC (Display) -> 5V (Arduino UNO)
SDA (Display) -> A4 (Arduino UNO)
SCL (Display) -> A5 (Arduino UNO)
*/
// control
#define TRUE 1
#define D8 8
#define D9 9
#define D10 10
#define D11 11
#define D12 12
int b1, b2, b3, b4, b5;
void read_b(void) {
b1 = digitalRead(D12);
b2 = digitalRead(D11);
b3 = digitalRead(D10);
b4 = digitalRead(D9);
b5 = digitalRead(D8);
}
// data
#define ALPHA_MAX 36
char _itoa[ALPHA_MAX];
int _atoi[91];
void cont(void) {
while (digitalRead(D8) != HIGH);
delay(200);
}
void init_itoa(void) {
for (int i = 0; i < 10; i++)
_itoa[i] = (char)48 + i;
for (int i = 10; i < ALPHA_MAX; i++)
_itoa[i] = (char)55 + i;
}
void init_atoi(void) {
int c = 0;
for (int i = 48; i < 58; i++)
_atoi[i] = c++;
for (int i = 65; i < 91; i++)
_atoi[i] = c++;
}
// random
#define CHAR_MAX 256
const unsigned char _r_max = CHAR_MAX - (CHAR_MAX % ALPHA_MAX);
volatile unsigned char _r_sample = 0;
volatile char _r_new = 0;
unsigned char _r = 0;
ISR(WDT_vect) {
_r_sample = TCNT1L;
_r_new = 1;
}
void _r_init(void) {
cli();
MCUSR = 0;
WDTCSR |= _BV(WDCE) | _BV(WDE);
WDTCSR = _BV(WDIE);
sei();
}
char _r_rotl_one(const char v) {
int shift = 1;
if ((shift &= sizeof(v) * 8 - 1) == 0)
return v;
return (v << shift) | (v >> (sizeof(v) * 8 - shift));
}
char _r_char(void) {
char i = 0;
while (TRUE) {
if (_r_new) {
_r_new = 0;
_r = _r_rotl_one(_r);
_r ^= _r_sample;
if (i++ > 7) {
if (_r < _r_max)
return _itoa[_r % ALPHA_MAX];
else
i = 0;
}
}
}
}
// LCD
#define COLS 20
#define ROWS 4
#define WS ' '
#define NULL_CHAR '\0';
LiquidCrystal_I2C lcd(0x27, COLS, ROWS);
void clr_all(void) {
for (int r = 0; r < ROWS; r++)
clr(r);
}
void clr(const int row) {
for (int c = 0; c < COLS; c++) {
lcd.setCursor(c, row);
lcd.print(WS);
}
}
void prntl(const int row, const char *str) {
int len = strlen(str);
for (int i = 0; i < len; i++)
prntc(row, i, str[i]);
while (len < COLS)
prntc(row, len++, WS);
}
void prntlong(int row, const char *str) {
clr_all();
int c = 0;
for (int i = 0; i < strlen(str); i++) {
prntc(row, c++, str[i]);
if (i == (COLS - 1) || i == ((COLS * 2) - 1) || i == ((COLS * 3) - 1)) {
row++;
c = 0;
}
}
}
void prntstr(const int row, const int col, const int len, const char *str) {
for (int i = 0; i < len; i++)
prntc(row, col+i, str[i]);
}
void prntc(const int row, const int col, const char c) {
lcd.setCursor(col, row);
lcd.print(c);
}
void prnti(const int row, const int col, const int i) {
char buf[10];
itoa(i, buf, 10);
prntstr(row, col, strlen(buf), buf);
}
// char ops
char add_ten(char c) {
for (int i = 0; i < 10; i++)
c = add_one(c);
return c;
}
char add_one(const char c) {
int n = (int)c + 1;
if (n == 91)
return '0';
if (n == 64)
return '9';
if (n == 58)
return 'A';
if (n == 47)
return 'Z';
return (char)n;
}
char sub_ten(char c) {
for (int i = 0; i < 10; i++)
c = sub_one(c);
return c;
}
char sub_one(const char c) {
int n = (int)c - 1;
if (n == 91)
return '0';
if (n == 64)
return '9';
if (n == 58)
return 'A';
if (n == 47)
return 'Z';
return (char)n;
}
// crypto
char *keygen(const int len) {
char *key = (char*)malloc(sizeof(char) * (len + 1));
for (int i = 0; i < len; i++)
key[i] = _r_char();
key[len] = NULL_CHAR;
return key;
}
char *encrypt(const char *txt, const char *key) {
int i = 0, c = 0;
int len = strlen(key);
char *enc = (char*)malloc(sizeof(char) * (len + 1));
while (*txt) {
c = _atoi[(int)*txt++] + _atoi[(int)*key++];
if (c > 36) {
c -= 36;
}
enc[i++] = _itoa[c];
}
enc[len] = NULL_CHAR;
return enc;
}
char *decrypt(const char *enc, const char *key) {
int i = 0, c = 0;
int len = strlen(key);
char *txt = (char*)malloc(sizeof(char) * (len + 1));
while (*enc) {
c = _atoi[(int)*enc++] - _atoi[(int)*key++];
if (c < 0) {
c += 36;
}
txt[i++] = _itoa[c];
}
txt[len] = NULL_CHAR;
return txt;
}
void enc_test(void) {
char txt[] = "0ZYX";
char key[] = "EU16";
char *enc = encrypt(txt, key);
clr_all();
prntl(0, "Encrypt Test");
prntl(2, enc);
prntl(3, "ETZ3");
free(enc);
cont();
}
void dec_test(void) {
char enc[] = "KU69";
char key[] = "AJU9";
char *dec = decrypt(enc, key);
clr_all();
prntl(0, "Decrypt Test");
prntl(2, dec);
prntl(3, "ABC0");
free(dec);
cont();
}
char *input(void) {
char p = 0, in = 'A';
int row = 0, col = 0, c = 0;
int len = COLS;
char *buf = (char*)malloc(sizeof(char) * len);
prntc(row, col, in);
while (TRUE) {
read_b();
if (b1 == HIGH) {
delay(100);
if (b2 == HIGH) {
prntc(row, col--, WS);
if (c > 0)
c--;
if (row > 0 && col < 0) {
row--;
col = (COLS - 1);
}
in = 'A';
delay(300);
}
}
if (b3 == HIGH) {
delay(100);
if (b4 == HIGH) {
prntc(row, col, WS);
buf = (char*)realloc(buf, sizeof(char) * c);
buf[c] = NULL_CHAR;
return buf;
}
}
if (b5 == HIGH) {
if (col == COLS || col == (COLS * 2) || col == (COLS * 3)) {
row++;
col = 0;
}
prntc(row, col++, in);
buf[c++] = in;
if (c == len) {
len += COLS;
buf = (char*)realloc(buf, sizeof(char) * len);
}
delay(300);
}
if (b1 == HIGH) {
in = sub_ten(in);
p = 1;
}
if (b2 == HIGH) {
in = sub_one(in);
p = 1;
}
if (b3 == HIGH) {
in = add_one(in);
p = 1;
}
if (b4 == HIGH) {
in = add_ten(in);
p = 1;
}
if (p) {
p = 0;
prntc(row, col, in);
delay(200);
}
}
}
void enc_mode(void) {
clr_all();
char *txt, *key, *enc;
txt = input();
key = keygen(strlen(txt));
enc = encrypt(txt, key);
prntlong(0, key);
cont();
prntlong(0, enc);
free(txt);
free(key);
free(enc);
cont();
}
void dec_mode(void) {
clr_all();
int len = 0;
char *enc, *key, *dec;
enc = input();
clr_all();
key = input();
dec = decrypt(enc, key);
prntlong(0, dec);
free(enc);
free(key);
free(dec);
cont();
}
void key_mode(void) {
clr_all();
char p = 0;
char *key;
int len = COLS * 2;
prnti(0, 0, len);
while (TRUE) {
read_b();
if (b1 == HIGH && len > 10) {
len -= 10;
p = 1;
}
if (b2 == HIGH && len > 1) {
len--;
p = 1;
}
if (b3 == HIGH && len < (COLS * ROWS)) {
len++;
p = 1;
}
if (b4 == HIGH && len <= ((COLS * ROWS) - 10)) {
len += 10;
p = 1;
}
if (p) {
p = 0;
prntl(0, "");
prnti(0, 0, len);
delay(150);
}
if (b5 == HIGH)
break;
}
key = keygen(len);
prntlong(0, key);
free(key);
cont();
}
void setup(void) {
pinMode(D8, INPUT);
pinMode(D9, INPUT);
pinMode(D10, INPUT);
pinMode(D11, INPUT);
pinMode(D12, INPUT);
_r_init();
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
init_atoi();
init_itoa();
}
void loop(void) {
clr_all();
prntl(0, "Encrypt: 1 KeyGen: 5");
prntl(1, "Decrypt: 2");
prntl(2, "Encrypt Test: 3");
prntl(3, "Decrypt Test: 4");
while (TRUE) {
read_b();
if (b1 == HIGH) {
enc_mode();
break;
}
if (b2 == HIGH) {
dec_mode();
break;
}
if (b3 == HIGH) {
enc_test();
break;
}
if (b4 == HIGH) {
dec_test();
break;
}
if (b5 == HIGH) {
key_mode();
break;
}
}
}