From 940e7beb010b0fc67dec2e4503cab13db92a7b08 Mon Sep 17 00:00:00 2001 From: geoffrey Date: Tue, 5 Mar 2024 14:15:03 +0100 Subject: [PATCH] First commit --- RSA_arduino.ino | 59 ++++++++++++++++++++++++++ constantes.h | 9 ++++ prng.cpp | 93 +++++++++++++++++++++++++++++++++++++++++ prng.cpp_bck | 98 +++++++++++++++++++++++++++++++++++++++++++ prng.h | 31 ++++++++++++++ prng.h_bck | 28 +++++++++++++ rsa.c_bck | 108 ++++++++++++++++++++++++++++++++++++++++++++++++ rsa.cpp | 88 +++++++++++++++++++++++++++++++++++++++ rsa.h | 22 ++++++++++ 9 files changed, 536 insertions(+) create mode 100644 RSA_arduino.ino create mode 100644 constantes.h create mode 100644 prng.cpp create mode 100644 prng.cpp_bck create mode 100644 prng.h create mode 100644 prng.h_bck create mode 100644 rsa.c_bck create mode 100644 rsa.cpp create mode 100644 rsa.h diff --git a/RSA_arduino.ino b/RSA_arduino.ino new file mode 100644 index 0000000..ec14884 --- /dev/null +++ b/RSA_arduino.ino @@ -0,0 +1,59 @@ +#include +#include +#include "rsa.h" +#include "prng.h" +#include "constantes.h" +#include + + +struct entropy_pool s_entropy; +int sensorValue = 0; +int switchState = 0; +// e -> public key +// d -> private key +unsigned long n, e, d = 0; +// LiquidCrystal(rs, enable, d0, d1, d2, d3, d4, d5, d6, d7) +LiquidCrystal lcd(11, 10, 5, 4, 3, 2); + +void setup(){ + pinMode(BUTTON, INPUT); + pinMode(LED_PIN, OUTPUT); + + digitalWrite(LED_PIN, LOW); + + Serial.begin(9600); + + lcd.begin(16, 2); + lcd.clear(); + + // Generate our entropy pool + init_entropy(); + + // Entropy pool if full, the switch on the red LED + digitalWrite(LED_PIN, HIGH); +} + +void loop(){ + Serial.println("Start generation key"); + + while(1){ + switchState = digitalRead(BUTTON); + + // If we push the button, we generate new keys + if (switchState == HIGH){ + lcd.clear(); + // Now, we can generate our keys + generateKeys(&e, &d, &n); + + if (DEBUG){ + Serial.println("e: " + String(e)); + Serial.println("d: " + String(d)); + Serial.println("n: " + String(n)); + } + lcd.setCursor(0, 0); + lcd.print("e:" + String(e) + "," + String(n)); + lcd.setCursor(0, 1); + lcd.print("d:" + String(d) + "," + String(n)); + } + } +} diff --git a/constantes.h b/constantes.h new file mode 100644 index 0000000..901367d --- /dev/null +++ b/constantes.h @@ -0,0 +1,9 @@ +#ifndef H_CONSTANTES +#define H_CONSTANTES + +#define BUTTON 12 // Button pin +#define LED_PIN 13 +#define DEBUG 0 +#define SENSOR_PIN 0 // Pin A0 + +#endif diff --git a/prng.cpp b/prng.cpp new file mode 100644 index 0000000..ca93a6f --- /dev/null +++ b/prng.cpp @@ -0,0 +1,93 @@ +#include +#include +#include +#include +#include "prng.h" +#include "constantes.h" +#include + +/* + * Fill the entropy structure with random data + */ +void init_entropy(){ + if (DEBUG) + Serial.println("Generation entropy"); + + // Generate entropy + int sensorValue = 0; + while(s_entropy.pool_size < BUFSIZE){ + generateEntropy(s_entropy.position++); + s_entropy.pool_size++; + + // Add a delay for avoiding the same value + delay(50); + } + if (DEBUG) + Serial.println("End generation"); +} +/* + * Generate a random value from the analog input + * Store the value in the entropy structure at the position specified in argument + */ +static void generateEntropy(int position){ + int sensorValue = 0; + + while( sensorValue == 0){ + sensorValue = analogRead(SENSOR_PIN); + + if (sensorValue != 0){ + if (DEBUG) + Serial.println("Value: " + String(sensorValue)); + + if(sensorValue <= 10) + sensorValue = sensorValue << 5; + else if(sensorValue > 10 && sensorValue <= 100) + sensorValue = sensorValue << 4; + + s_entropy.buf[position] = sensorValue; + Serial.println("Position: " + String(position)); + } + } +} + +/* + * For avoiding to reused the seed, we must generate a new one + */ +static unsigned long generateSeed(){ + unsigned long seed; + int sensorValue = 0; + if (DEBUG) + Serial.println("Generate seed"); + + while (sensorValue == 0){ + sensorValue = analogRead(SENSOR_PIN); + seed = sensorValue; + + if (DEBUG) + Serial.println("Seed: " + String(seed)); + } + + return seed; +} +/* + * Generate a random data from the entropy pool + */ +unsigned long prng(){ + unsigned long p = 0; + unsigned long pos = generateSeed(); + + pos += ( (pos << 4)); + pos ^= ( (pos >> 11)); + pos |= (pos << (pos % 15)); + pos = pos % 201; + + if (pos > BUFSIZE) + pos = pos / 2; + + p = s_entropy.buf[pos]; + + // Replace the old value + generateEntropy(pos); + + return p; +} diff --git a/prng.cpp_bck b/prng.cpp_bck new file mode 100644 index 0000000..f825cbb --- /dev/null +++ b/prng.cpp_bck @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include +#include +#include "prng.h" +#include + +#define MAX_ENTRIES_ENTROPY 100 + +void init_entropy(){ + struct entropy_pool s_pool; + randomSeed(analogRead(0)); + while (s_entropy.pool_size < BUFSIZE){ + s_entropy.buf[s_entropy.pool_size++] = random(300); + } +} + +// Define a range ??? +unsigned long prng(int seed){ + //int32_t p = 4242; + unsigned long p = seed; + + //p = 4242; + //p ^= p << 3; // XOR + // 1000010010010 -> 4242 + // 1000010010010000 -> 33936 + // 1001010000000010 -> 37890 + //printf("%d\n", p); + + // For small value, increase the value ? + p ^= (p << 1) | (p << 2); + + // Generate number between 1000 and 5000 ??? + // Or to add X bits to have the key number, for instance 32 bits + + return p; +} + +int prng2 () { + double *pool_entropy = entropy_pool(); + int pos = 0; + + entropy_cpu_clock(pool_entropy, 0, MAX_ENTRIES_ENTROPY); + pos++; + + for(int i = 0; i < MAX_ENTRIES_ENTROPY; i++){ + //printf("%f\n", pool_entropy[i]); + } + + // Get from pool + // Generate an integer from 0 to 100 (with clock CPU) for instance + // And to pick up to the pool + + // Generate entropy with the network ? + + free(pool_entropy); + return(0); +} +double *entropy_pool(){ + double *pool_entropy = (double *)malloc(sizeof(double) * MAX_ENTRIES_ENTROPY); + + if (pool_entropy == NULL){ + //printf("Failed to allocate variables\n"); + exit(-1); + } + return pool_entropy; +} +void entropy_cpu_clock(double *entropy, int pos, int max){ + clock_t start_t, end_t; + double total_t; + double res = 0; + + start_t = clock(); + //printf("Starting of the program, start_t = %ld\n", start_t); + + //printf("Going to scan a big loop, start_t = %ld\n", start_t); + for(int i = 0; i < 10000000; i++) { + } + end_t = clock(); + //printf("End of the big loop, end_t = %ld\n", end_t); + + total_t = (double)(end_t - start_t) / CLOCKS_PER_SEC; + //printf("Total time taken by CPU: %f\n", total_t ); + //printf("Exiting of the program...\n"); + + entropy[pos] = total_t; + + // Test - generate an iteger from 0 to 100 + + // Multiply the 10 first entries + for (int i = 0; i < 10; i++){ + res += entropy[0]; + } + + //printf("Pos: %f\n", ceil(res * 100)); +} diff --git a/prng.h b/prng.h new file mode 100644 index 0000000..55bc4c2 --- /dev/null +++ b/prng.h @@ -0,0 +1,31 @@ +#ifndef H_PRNG +#define H_PRNG + +#define BUFSIZE 128 + +struct entropy_pool{ + unsigned long buf[BUFSIZE]; + int pool_size; + int position; + int pool_count; +}; + +extern struct entropy_pool s_entropy; + +void init_entropy(); +static void generateEntropy(int); +static unsigned long generateSeed(); +unsigned long prng(); +int prng2(); +double *entropy_pool(); +void entropy_cpu_clock(double *, int, int); + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/prng.h_bck b/prng.h_bck new file mode 100644 index 0000000..ac1e78d --- /dev/null +++ b/prng.h_bck @@ -0,0 +1,28 @@ +#ifndef H_PRNG +#define H_PRNG + +#define BUFSIZE 128 + +struct entropy_pool{ + unsigned long buf[BUFSIZE]; + int pool_size; +}; + +extern struct entropy_pool s_entropy; + +void init_entropy(); +unsigned long prng(int); +int prng2(); +static void readDevRandom(char *); +double *entropy_pool(); +void entropy_cpu_clock(double *, int, int); + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/rsa.c_bck b/rsa.c_bck new file mode 100644 index 0000000..9d8e926 --- /dev/null +++ b/rsa.c_bck @@ -0,0 +1,108 @@ +#include +#include +#include "rsa.h" +#include "prng.h" + +void generateKeys(unsigned long *e, unsigned long *d, unsigned long *n){ + unsigned long p = prng(25); + unsigned long q = prng(47); + unsigned long phi = 0; + + // Generate big numbers of p and q + //generateBigNumber(&p); + //generateBigNumber(&q); + + // Check if p and q are prime numbers + if (isPrimeNumber(p) != 0) + prime_number_finder(&p); + + if (isPrimeNumber(q) != 0) + prime_number_finder(&q); + + // Calculate n + *n = p * q; + + // We're going to calcule the Euler's totient + // Our number are prime number, so, phi = (p - 1) * (q - 1) + phi = (p - 1)*(q - 1); + + /* We will calculate e for the public key */ + generatePublicKey(phi, e); + + /* We will calcuate d for the private key */ + generatePrivateKey(d, phi, e); + + /* For encrypting + m = ( message ** e) % n + exemple!: A -> 0x65 + (65 ** 4033) % 6938083 = 1140958 + For decrypting + ( m ** d) % n + Exemple: + (1140958 ** 830257) % 6938083 = 65 + */ +} +static void generateBigNumber(unsigned long *v){ + /*if (*v < 100) + *v = *v << 6; + else if (*v >= 100 || *v < 1000) + *v = *v << 4; + else + *v = *v << 2;*/ +} +/* + * This function will identify all the divider of the variable a + * with the Euclidean algorithm + */ +static int gcd(unsigned long a, unsigned long b){ + // Ou utiliser l'algorithme d'Euclide ? + int done = 0; + while (!done){ + if (b == 0) + done = 1; + else{ + int tmp = b; + b = a % b; + a = tmp; + } + } + return a; +} +/* + * This function will check if te variable e is a prime number + * is not, we increment the value to 1 and continue until is a prime number + */ +static void prime_number_finder(unsigned long *e){ + while(isPrimeNumber(*e) != 0) + *e += 1; +} +static int isPrimeNumber(unsigned long x){ + for (int i = 2; i < x; i++){ + if (x % i == 0) + return 1; + } + return 0; +} +static unsigned long generatePublicKey(unsigned long phi, unsigned long *e){ + // Generate e + *e = prng(61); + //generateBigNumber(e); + + // Get the coprime with phi + while ((gcd(phi, *e)) != 1) + *e += 1; + + return *e; +} +static unsigned long generatePrivateKey(unsigned long *d, unsigned long phi, unsigned long *e){ + // Calculate the modular inverse + int i = 0; + for (i = 0; i <= phi; i++){ + if ((i * (*e)) % phi == 1){ + *d = i; + break; + } + } + //*d = *e; + return *d; +} diff --git a/rsa.cpp b/rsa.cpp new file mode 100644 index 0000000..5ae64f4 --- /dev/null +++ b/rsa.cpp @@ -0,0 +1,88 @@ +#include +#include +#include "rsa.h" +#include "prng.h" + +/* + * We will generate the public and private RSA key + */ +void generateKeys(unsigned long *e, unsigned long *d, unsigned long *n){ + unsigned long p = prng(); + unsigned long q = prng(); + unsigned long phi = 0; + + // Check if p and q are different + if (p == q) + q ^= q << 2; + + // Check if p and q are prime numbers + if (isPrimeNumber(p) != 0) + prime_number_finder(&p); + + if (isPrimeNumber(q) != 0) + prime_number_finder(&q); + + // Calculate n + *n = p * q; + + // We're going to calcule the Euler's totient + phi = (p - 1)*(q - 1); + + /* We will calculate e for the public key */ + generatePublicKey(phi, e); + + /* We will calcuate d for the private key */ + generatePrivateKey(d, phi, e); +} +/* + * This function will identify all the divider of the variable a + * with the Euclidean algorithm + */ +static int gcd(unsigned long a, unsigned long b){ + if (b == 0) + return a; + return gcd(b, a%b); +} +/* + * This function will check if te variable e is a prime number + * is not, we increment the value to 1 and continue until is a prime number + */ +static void prime_number_finder(unsigned long *p){ + while(isPrimeNumber(*p) != 0) + *p += 1; +} +/* + * Check if the number specified is a prime number + */ +static int isPrimeNumber(unsigned long x){ + for (int i = 2; i < x; i++){ + if (x % i == 0) + return 1; + } + return 0; +} +/* + * Generate the public key and need to be coprime with phi(n) + */ +static unsigned long generatePublicKey(unsigned long phi, unsigned long *e){ + // Generate e + *e = prng(); + + while ((gcd(phi, *e)) != 1) + *e += 1; + + return *e; +} +/* + * We generate tne private key with the modular inverse of phi(n) + */ +static unsigned long generatePrivateKey(unsigned long *d, unsigned long phi, unsigned long *e){ + for (int i = 0; i <= phi; i++){ + if ((i * (*e)) % phi == 1){ + *d = i; + break; + } + } + + return *d; +} diff --git a/rsa.h b/rsa.h new file mode 100644 index 0000000..fb30163 --- /dev/null +++ b/rsa.h @@ -0,0 +1,22 @@ +#ifndef H_RSA +#define H_RSA + +#include + +void generateKeys(unsigned long *, unsigned long *, unsigned long *); + +#ifdef __cplusplus +extern "C" { +#endif + +static void prime_number_finder(unsigned long *); +static int gcd(unsigned long, unsigned long); +static int isPrimeNumber(unsigned long a); +static unsigned long generatePublicKey(unsigned long, unsigned long *); +static unsigned long generatePrivateKey(unsigned long *, unsigned long, unsigned long *); + +#ifdef __cplusplus +} +#endif + +#endif