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