From 199a93c1c7302d1f47da83cd3dc22af225affdad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anian=20B=C3=BChler?= <anian.buehler@reutlingen-university.de> Date: Fri, 26 Nov 2021 13:25:31 +0100 Subject: [PATCH] added DidacticEnc Lib --- .../com/ardublock/libraries/DidacticEnc.cpp | 203 ++++++++++++++++++ .../com/ardublock/libraries/DidacticEnc.h | 95 ++++++++ 2 files changed, 298 insertions(+) create mode 100644 src/main/resources/com/ardublock/libraries/DidacticEnc.cpp create mode 100644 src/main/resources/com/ardublock/libraries/DidacticEnc.h diff --git a/src/main/resources/com/ardublock/libraries/DidacticEnc.cpp b/src/main/resources/com/ardublock/libraries/DidacticEnc.cpp new file mode 100644 index 0000000..c81fc4d --- /dev/null +++ b/src/main/resources/com/ardublock/libraries/DidacticEnc.cpp @@ -0,0 +1,203 @@ +/**************************************************************************/ +/*! + @file didacticEnc.cpp + @author anian buehler @ letsgoING.org +*/ +/**************************************************************************/ + +#include "Arduino.h" +#include "DidacticEnc.h" + + +//************************************************************************** +//SYMETRIC +//************************************************************************** +DidacticEncSymetric::DidacticEncSymetric(){} +DidacticEncSymetric::~DidacticEncSymetric(){} + +int DidacticEncSymetric::setKey(char* key){ + if(strlen(key) == DE_LENGHT_KEY){ + memcpy(_key, key, DE_LENGHT_KEY+1); + return DE_ERROR_NOERROR; + } else if(strlen(key) > DE_LENGHT_KEY){ + return DE_ERROR_KEYLENGHT_LONG; + } else{ + return DE_ERROR_KEYLENGHT_SHORT; + } +} + +//Nachricht wird entschlüsselt und überschrieben +void DidacticEncSymetric::crypt(char* messageIn, int lengthMessage, char* messageOut, char* key, int lengthKey){ + //ACHTUNG: bei gleichem Zeichen in Schlüssel und Nachricht wird die Nachricht unterbrochen + int keyCounter = 0; + int msgCounter = 0; + + for (msgCounter = 0; msgCounter < lengthMessage; msgCounter++) { + keyCounter = msgCounter % lengthKey; //Zähler für key der nie größer wird als lengthKey (Restwert der Division durch Schlüssellänge) + messageOut[msgCounter] = messageIn[msgCounter] ^ key[keyCounter]; //XOR-Verknüpfung + } + messageOut[msgCounter + 1] = '\0'; //"EndOfString" an letzter Stelle +} + +void DidacticEncSymetric::crypt(char* messageIn, char* messageOut, char* key){ + crypt(messageIn, strlen(messageIn), messageOut, key, strlen(key) ); +} + +void DidacticEncSymetric::crypt(char* messageIn, char* messageOut){ + crypt(messageIn, strlen(messageIn), messageOut, _key, strlen(_key)); +} + + + + +//************************************************************************** +//ASYMETRIC +//************************************************************************** +DidacticEncAsymetric::DidacticEncAsymetric(){} +DidacticEncAsymetric::~DidacticEncAsymetric(){} + +void DidacticEncAsymetric::generateRsaKeys(long p, long q, long& n, long& e, long& d) { + long x = 0; + long y = 0; + long m = 0; + + n = p * q; + m = (p - 1) * (q - 1); + + e = 3; //start value + while (gcd(e, m) > 1) { + e += 2; + } + + if (egcd(e, m, x, y) == 1) { + if (x < 0) { + x += m; + } + + d = x % m; + } +} + +long DidacticEncAsymetric::cryptRsa(long key, long n, long message) { + return modPow(message, key, n); +} + +long DidacticEncAsymetric::getPrime(){ + return prime[random(0, MAX_NR_OF_PRIMES- MAX_PRIME_OFFSET)]; +} + +long DidacticEncAsymetric::getPrimeWithOffset(long basicPrime){ + int index = 0; + while(prime[index] != basicPrime && index <= MAX_NR_OF_PRIMES- MAX_PRIME_OFFSET){ + ++index; + } + return prime[index + random(1,MAX_PRIME_OFFSET)]; +} + +void DidacticEncAsymetric::setRandomSeedPin(int analogPin){ + if(analogPin <= A5 && analogPin >= A0){ + _randomPin = analogPin; + } +} + +void DidacticEncAsymetric::generateKeys(){ + randomSeed(analogRead(_randomPin)); + long firstPrime = getPrime(); + long secondPrime = getPrimeWithOffset(firstPrime); + generateRsaKeys(firstPrime, secondPrime, _rsaModule, _publicKey, _privateKey); +} + +long DidacticEncAsymetric::getPrivateKey(){ + return _privateKey; +} +long DidacticEncAsymetric::getPublicKey(){ + return _publicKey; +} +long DidacticEncAsymetric::getRsaModule(){ + return _rsaModule; +} + +int DidacticEncAsymetric::encrypt(char* plainText, int lengthplainText, char* cypherText, long key, long rsaModule){ + for(int i = 0; i< lengthplainText; ++i){ + long currentMessage = (long) plainText[i]; + snprintf(&(cypherText[strlen(cypherText)]), MAX_LEN_CYPHERTEXT, "%ld", cryptRsa( key, rsaModule, currentMessage)); + snprintf(&(cypherText[strlen(cypherText)]), MAX_LEN_CYPHERTEXT, DE_CYPHER_SEPARATOR); + } + return strlen(cypherText); +} + +int DidacticEncAsymetric::encrypt(char* plainText, char* cypherText, long key, long rsaModule){ + return encrypt(plainText, strlen(plainText), cypherText, key, rsaModule); +} + +int DidacticEncAsymetric::decrypt(char* cypherText, char* plainText, long key, long rsaModule) { + char *currentNumber; + char *savePointer = cypherText; + int counter = 0; + while ((currentNumber = strtok_r(savePointer, DE_CYPHER_SEPARATOR, &savePointer)) != NULL) // Don't use \n here it fails + { + long number = atol(currentNumber); + plainText[counter] = cryptRsa( key, rsaModule, number); + ++counter; + } + plainText[counter] = '\0'; + return counter; +} +//*************** + + +/********************************************** + * MATH FUNCTIONS FOR RSA + **********************************************/ + +// Basic Euclidean Algorithm for greatest common divider +long DidacticEncAsymetric::gcd (long a, long b) { + long r; + while (b != 0) { + r = a % b; + a = b; + b = r; + } + return a; +} + +/*recursive version of gcd + long gcd(long a, long b) + { + if (a == 0) + return b; + return gcd(b%a, a); + } */ + +// extended euclidean algorithm: also finds coefficients x and y +long DidacticEncAsymetric::egcd (long a, long b, long& x, long& y){ + if (a == 0) + { + x = 0; + y = 1; + return b; + } + + long _x, _y; + long gcd = egcd(b % a, a, _x, _y); + + x = _y - (b / a) * _x; + y = _x; + + return gcd; +} + +//modular exponentation (to keep values as small as possible) +long DidacticEncAsymetric::modPow(long base, long exponent, long modulus) { + if (modulus == 1) { + return 0; + } + long c = 1; + for (long i = 0; i < exponent; i++) { + c = c * base % modulus; + } + return c; +} + + + diff --git a/src/main/resources/com/ardublock/libraries/DidacticEnc.h b/src/main/resources/com/ardublock/libraries/DidacticEnc.h new file mode 100644 index 0000000..ec1782a --- /dev/null +++ b/src/main/resources/com/ardublock/libraries/DidacticEnc.h @@ -0,0 +1,95 @@ +/************************************************************************** + @file didacticNet.h + @author anian buehler @ letsgoING +**************************************************************************/ + + +#ifndef _DIDACTICENC_ +#define _DIDACTICENC_ + +#include "Arduino.h" + + +class DidacticEncSymetric +{ + #define DE_LENGHT_KEY 8 + + #define MAX_LEN_CYPHERTEXT DE_LENGHT_KEY*4 + #define MAX_LEN_PLAINTEXT DE_LENGHT_KEY*4 + + #define DE_ERROR_NOERROR 1 + #define DE_ERROR_KEYLENGHT_LONG -1 + #define DE_ERROR_KEYLENGHT_SHORT -2 + + private: + char _bufferCyphertext[MAX_LEN_CYPHERTEXT +1] = {0}; + char _bufferPlaintext[MAX_LEN_PLAINTEXT +1] = {0}; + char _key[DE_LENGHT_KEY +1] = {'0','0','0','0','0','0','0','0','\0'}; + + public: + DidacticEncSymetric(); + ~DidacticEncSymetric(); + + int setKey(char*); + void crypt(char*, int, char*, char*, int); + void crypt(char*, char*, char*); + void crypt(char*, char*); +}; + + +class DidacticEncAsymetric +{ + #define MAX_NR_OF_PRIMES 48 + #define MAX_PRIME_OFFSET 3 + #define MAX_LEN_PLAINTEXT 20 + #define MAX_LEN_CYPHERTEXT 250 + + #define DE_CYPHER_SEPARATOR ";" + + private: + const int prime[MAX_NR_OF_PRIMES] = { 17, 19, 23, 29, 31, 37, + 41, 43, 47, 53, 59, 61, 67, 71, 73, + 79, 83, 89, 97, 101, 103, 107, 109, + 113, 127, 131, 137, 139, 149, 151, 157, + 163, 167, 173, 179, 181, 191, 193, 197, + 199, 211, 223, 227, 229, 233, 239, 241, + 251};//, 257, 263, 269, 271, 277, 281}; + + char _bufferCyphertext[MAX_LEN_CYPHERTEXT +1] = {0}; + + long _privateKey = 0L; + long _publicKey = 0L; + long _rsaModule = 0L; + + int _randomPin = A5; + + void generateRsaKeys(long, long, long&, long&, long&); + long cryptRsa(long key, long rsaModul, long message); + + long getPrimeWithOffset(long); + long getPrime(); + + + //rsa math functions + long gcd (long, long); //basic euclidean algorithm + long egcd (long, long, long&, long&); //extended euclidean algorithm + long modPow(long, long, long); //modular exponentation + + public: + DidacticEncAsymetric(); + ~DidacticEncAsymetric(); + + void generateKeys(); + + void setRandomSeedPin(int); + + long getPrivateKey(); + long getPublicKey(); + long getRsaModule(); + + int encrypt(char*, int, char*, long, long); + int encrypt(char*, char*, long, long); + + int decrypt(char*, char*, long, long); +}; +#endif -- GitLab