442 lines
7.7 KiB
C++
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;
|
|
}
|
|
}
|
|
}
|