From 24922e59c612d641d880a3fa3d9be1e4d545b65c Mon Sep 17 00:00:00 2001 From: Imbus <> Date: Wed, 12 Feb 2025 19:48:32 +0100 Subject: [PATCH] RSA crypto initial draft --- Makefile | 2 +- main.c | 54 +++++++++++++++++++++++++++---------- rsa.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ rsa.h | 57 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 179 insertions(+), 15 deletions(-) create mode 100644 rsa.c create mode 100644 rsa.h diff --git a/Makefile b/Makefile index 25b983d..da37ddd 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ CC := $(TOOL_PREFIX)-gcc OBJDUMP := $(TOOL_PREFIX)-objdump OBJCOPY := $(TOOL_PREFIX)-objcopy -SRC := ch32fun.c main.c +SRC := ch32fun.c main.c rsa.c rand.c CFLAGS = -g \ -Os \ diff --git a/main.c b/main.c index f7fded8..4128657 100644 --- a/main.c +++ b/main.c @@ -1,9 +1,10 @@ #include +#include #include +#include +#include #define LED_PIN PD6 -#define FREQ 2 -#define BLINK_DELAY 1000 / FREQ void exit_blink() { for (int i = 0; i < 4; i++) { @@ -12,28 +13,53 @@ void exit_blink() { funDigitalWrite(LED_PIN, FUN_LOW); Delay_Ms(50); } +} - while (1){}; - - funDigitalWrite(LED_PIN, FUN_HIGH); +void enter_blink() { + for (int i = 0; i < 2; i++) { + funDigitalWrite(LED_PIN, FUN_HIGH); + Delay_Ms(200); + funDigitalWrite(LED_PIN, FUN_LOW); + Delay_Ms(200); + } } int main() { SystemInit(); - // Enable GPIOs - funGpioInitAll(); + printf("Entering..."); + funGpioInitAll(); funPinMode(LED_PIN, GPIO_Speed_10MHz | GPIO_CNF_OUT_PP); - int i = 0; - while (i < gcd(930, 10)) { - i++; - funDigitalWrite(LED_PIN, FUN_HIGH); - Delay_Ms(BLINK_DELAY); - funDigitalWrite(LED_PIN, FUN_LOW); - Delay_Ms(BLINK_DELAY); + enter_blink(); + + uint64_t p = gen_prime(1 << 15, 1 << 16); + uint64_t q = gen_prime(1 << 15, 1 << 16); + + while (p == q) p = gen_prime(1 << 15, 1 << 16); + + uint64_t n = p * q; + + // Make these work by patching printf + printf("P: %llu\n", p); + printf("Q: %llu\n", q); + printf("N: %llu\n", n); + + for (int idx = 0; idx < 16; idx++) { + funDigitalWrite(LED_PIN, p >> idx & 1); + Delay_Ms(200); + } + for (int idx = 0; idx < 16; idx++) { + funDigitalWrite(LED_PIN, q >> idx & 1); + Delay_Ms(200); + } + for (int idx = 0; idx < 16; idx++) { + funDigitalWrite(LED_PIN, n >> idx & 1); + Delay_Ms(200); } + // Exit and hang forever exit_blink(); + while (1); } diff --git a/rsa.c b/rsa.c new file mode 100644 index 0000000..07e06bd --- /dev/null +++ b/rsa.c @@ -0,0 +1,81 @@ +#include "rsa.h" +#include "rand.h" +#include +#include + +int gcd(int a, int b) { + while (b != 0) { + int temp = b; + b = a % b; + a = temp; + } + + return a; +} + +int totient(int n) { + int result = n; + + // Check for prime factors + for (int p = 2; p * p <= n; p++) { + if (n % p == 0) { + // If p is a prime factor of n, remove all occurrences of p + while (n % p == 0) { + n /= p; + } + result -= result / p; + } + } + + // If n is still greater than 1, then it's a prime factor itself + if (n > 1) { + result -= result / n; + } + + return result; +} + +uint64_t modexp(uint64_t a, uint64_t b, uint64_t m) { + uint64_t result = 1; + a = a % m; // In case a is greater than m + + while (b > 0) { + // If b is odd, multiply a with result + if (b % 2 == 1) + result = (result * a) % m; + + // b must be even now + b = b >> 1; // b = b // 2 + a = (a * a) % m; // Change a to a^2 + } + + return result; +} + +uint64_t gen_prime(uint64_t min, uint64_t max) { + uint64_t cand = 0; + while (!is_prime(cand)) cand = prand_range(min, max); + + return cand; +} + +bool is_prime(int n) { + if (n < 2) + return false; + + for (int i = 2; i < n / 2 + 1; i++) { + if (n % i == 0) + return false; + } + + return true; +} + +int mod_inverse(int e, int phi) { + for (int d = 0; d < phi; d++) { + if ((d * e) % phi == 1) + return d; + } + + return 0; +} diff --git a/rsa.h b/rsa.h new file mode 100644 index 0000000..b84c43d --- /dev/null +++ b/rsa.h @@ -0,0 +1,57 @@ +#pragma once +#include +#include + +/** + * @brief Calculates greatest common divider of two integers using the euclidean + * algorithm + * + * @param a First number + * @param b Second number + * @return The greatest common divider + */ +int gcd(int a, int b); + +/** + * @brief Computes Euler's Totient function φ(n), which counts the number of + * integers from 1 to n that are coprime to n. + * + * @param n The input number. + * @return The number of integers from 1 to n that are coprime to n. + */ +int totient(int n); + +/** + * @brief Modular exponentiation (a^b) mod m + * + * @param a The base + * @param b The exponent + * @param m The modulus + */ +uint64_t modexp(uint64_t a, uint64_t b, uint64_t m); + +/** + * @brief Computes the modular inverse of e modulo phi. + * + * @param e The integer whose modular inverse is to be found. + * @param phi The modulus. + * @return The modular inverse of e modulo phi, or -1 if no inverse exists. + */ +int mod_inverse(int e, int phi); + +/** + * @brief Generates a random prime number within the given range. + * + * @param min The lower bound (inclusive). + * @param max The upper bound (inclusive). + * @return A prime number in the range [min, max]. + */ +uint64_t gen_prime(uint64_t min, uint64_t max); + +/** + * @brief Checks if a number is prime. + * + * @param n The number to check. + * @return true if n is prime, false otherwise. + */ +bool is_prime(int n);