RSA crypto initial draft

This commit is contained in:
Imbus 2025-02-12 19:48:32 +01:00
parent 1cd0b619ef
commit 24922e59c6
4 changed files with 179 additions and 15 deletions

View file

@ -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 \

52
main.c
View file

@ -1,9 +1,10 @@
#include <ch32fun.h>
#include <rand.h>
#include <rsa.h>
#include <stdint.h>
#include <stdio.h>
#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){};
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);
}

81
rsa.c Normal file
View file

@ -0,0 +1,81 @@
#include "rsa.h"
#include "rand.h"
#include <stdbool.h>
#include <stdint.h>
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;
}

57
rsa.h Normal file
View file

@ -0,0 +1,57 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
/**
* @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);