diff --git a/Makefile b/Makefile index bdf06c6..ccd6d27 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,4 @@ -# 'master' or hash -REV := 8ba9981e5 +REV := master BASE := https://raw.githubusercontent.com/cnlohr/ch32v003fun/$(REV) CURL_FLAGS := -O -\# --fail --location --tlsv1.3 --proto =https --max-time 300 diff --git a/assert.h b/assert.h deleted file mode 100644 index e56b318..0000000 --- a/assert.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include -#include - -#define ASSERT(expr) \ - do { \ - if (!(expr)) { \ - printf("ASSERTION FAILED: %s at %s:%d\n", #expr, __FILE__, \ - __LINE__); \ - while (1); \ - } \ - } while (0) - -#define ASSERT_EQ(expr, expected) \ - do { \ - uint64_t result = (expr); \ - if (result != (expected)) { \ - printf("ASSERTION FAILED: %s at %s:%d\n", #expr, __FILE__, \ - __LINE__); \ - printf("Expected: %lu, Got: %lu\n", (unsigned long)(expected), \ - (unsigned long)result); \ - while (1); \ - } \ - } while (0) diff --git a/funconfig.h b/funconfig.h index 561ab22..998cf76 100644 --- a/funconfig.h +++ b/funconfig.h @@ -1,18 +1,7 @@ -#include - #ifndef _FUNCONFIG_H #define _FUNCONFIG_H -#define CH32V003 1 - -#define NULL ((void *)0) - -typedef int8_t i8; -typedef uint8_t u8; -typedef int16_t i16; -typedef uint32_t u32; -typedef int32_t i32; -typedef int64_t i64; -typedef uint64_t u64; +#define CH32V003 1 #endif + diff --git a/main.c b/main.c index 28a423d..29770df 100644 --- a/main.c +++ b/main.c @@ -1,14 +1,10 @@ -#include "assert.h" #include #include #include #include #include -#include #define LED_PIN PD6 -#define RANDOM -#define W 16 void exit_blink() { for (int i = 0; i < 4; i++) { @@ -28,30 +24,6 @@ void enter_blink() { } } -void test_mulmod() { - ASSERT_EQ(mulmod(3, 2, 4), 2); - ASSERT_EQ((3 * 2) % 4, 2); - - ASSERT_EQ(mulmod(31, 3, 8), 5); - ASSERT_EQ(mulmod((u64)1 << 63, 2, 1000000007ULL), 582344008); -} - -void test_modexp() { - ASSERT_EQ(modexp(3, 2, 4), 1); - ASSERT_EQ((3 ^ 2) % 4, 1); - - ASSERT_EQ(modexp(31, 3, 8), 7); - ASSERT_EQ(modexp((u64)1 << 63, 2, 1000000007ULL), 319908071); -} - -void debug_string(char *str) { - printf("Got string: %s\n", str); - for (int i = 0; i < strlen(str); i++) { - printf("decoded[%d] = '%c' (ASCII: %d)\n", i, str[i], - str[i]); // Print decoded chars and ASCII values - } -} - int main() { SystemInit(); sprand(0); @@ -61,59 +33,54 @@ int main() { enter_blink(); - test_mulmod(); - test_modexp(); +#ifdef RANDOM + uint64_t p = gen_prime(1 << 15, 1 << 16); + uint64_t q = p; - const u64 p = gen_prime(1 << (W - 1), 1 << W); - printf("P: %u\n", (u32)p); + while (p == q) p = gen_prime(1 << 15, 1 << 16); +#else + uint64_t p = 56857; + uint64_t q = 47963; +#endif - u64 qprev = p; - while (p == qprev) qprev = gen_prime(1 << (W - 1), 1 << W); + uint64_t n = p * q; + uint64_t phi_n = (p - 1) * (q - 1); - const u64 q = qprev; - printf("Q: %u\n", (u32)q); + // 'e' is public. E for encrypt. + uint64_t e = 0; + while (gcd(e, phi_n) != 1) e = prand_range(3, phi_n - 1); - ASSERT(gcd(p - 1, PUBEXP) == 1); - ASSERT(gcd(q - 1, PUBEXP) == 1); - - u64 n = p * q; - printf("N: %u\n", (u32)n); - - u64 phi_n = (p - 1) * (q - 1); - printf("Phi_N: %u\n", (u32)phi_n); - - u64 d = mod_inverse(PUBEXP, phi_n); - printf("D: %u\n", (u32)d); + // 'd' is our private key. D as in decrypt + uint64_t d = mod_inverse(e, phi_n); if (d == 0 || d == 1) { printf("Modular inverse not found..."); + while (1); } - ASSERT_EQ(mulmod(PUBEXP, d, phi_n), 1); - char msg[] = "Hello"; - u64 coded[sizeof(msg)] = {0}; + uint64_t coded[sizeof(msg)] = {0}; char decoded[sizeof(msg)] = {0}; // Encode the message - for (int i = 0; i < strlen(msg); i++) { - coded[i] = modexp((u64)msg[i], PUBEXP, n); + for (int i = 0; i < sizeof(msg); i++) { + coded[i] = (uint64_t)modexp((uint64_t)msg[i], e, n); } // Decode the message - for (int i = 0; i < strlen(msg); i++) { - u64 dec = modexp(coded[i], d, n); - decoded[i] = dec & 0xFF; + for (int i = 0; i < sizeof(msg); i++) { + decoded[i] = (char)modexp(coded[i], d, n); } { + printf("P: %u\n", (uint32_t)p); + printf("Q: %u\n", (uint32_t)q); + printf("N: %u\n", (uint32_t)n); + printf("Phi_N: %u\n", (uint32_t)phi_n); + printf("Pubkey (e): %u\n", (uint32_t)e); + printf("Privkey (d): %u\n", (uint32_t)d); + printf("Message: %s\n", msg); printf("Decoded: %s\n", decoded); - - for (int i = 0; i < strlen(msg); i++) { - printf("coded[%d] = 0x%016lx\n", i, (unsigned long)coded[i]); - } - - debug_string(decoded); } // Exit and hang forever diff --git a/rsa.c b/rsa.c index 89a3069..b547c93 100644 --- a/rsa.c +++ b/rsa.c @@ -1,11 +1,15 @@ #include "rsa.h" -#include "funconfig.h" #include "rand.h" #include +#include -u64 gcd(u64 a, u64 b) { return extended_euclid(a, b, NULL, NULL); } +#define NULL ((void *)0) -u64 extended_euclid(u64 a, u64 b, u64 *x, u64 *y) { +uint64_t gcd(uint64_t a, uint64_t b) { + return extended_euclid(a, b, NULL, NULL); +} + +int extended_euclid(int a, int b, int *x, int *y) { if (b == 0) { if (x) *x = 1; @@ -14,8 +18,8 @@ u64 extended_euclid(u64 a, u64 b, u64 *x, u64 *y) { return a; } - u64 x1, y1; - u64 gcd = extended_euclid(b, a % b, &x1, &y1); + int x1, y1; + int gcd = extended_euclid(b, a % b, &x1, &y1); if (x) *x = y1; @@ -25,7 +29,7 @@ u64 extended_euclid(u64 a, u64 b, u64 *x, u64 *y) { return gcd; } -u64 totient(u64 n) { +int totient(int n) { int result = n; // Check for prime factors @@ -47,24 +51,23 @@ u64 totient(u64 n) { return result; } -u64 mulmod(u64 a, u64 b, u64 m) { - u64 result = 0; +uint64_t mulmod(uint64_t a, uint64_t b, uint64_t m) { + uint64_t result = 0; a %= m; - // Perform the multiplication bit by bit (binary multiplication) while (b > 0) { if (b & 1) { - result = (result + a) % m; + result = (result + a) % m; // Avoid overflow } - a = (a * 2) % m; // Double a, keep it within the modulus - b >>= 1; // Right shift b (divide by 2) + a = (a * 2) % m; // Double a, keep within mod + b >>= 1; } return result; } -u64 modexp(u64 a, u64 b, u64 m) { - u64 result = 1; +uint64_t modexp(uint64_t a, uint64_t b, uint64_t m) { + uint64_t result = 1; a %= m; while (b > 0) { @@ -78,14 +81,14 @@ u64 modexp(u64 a, u64 b, u64 m) { return result; } -u64 gen_prime(u64 min, u64 max) { - u64 cand = 0; +uint64_t gen_prime(uint64_t min, uint64_t max) { + uint64_t cand = 0; while (!miller_rabin(cand, 10)) cand = prand_range(min, max); return cand; } -bool is_prime(u64 n) { +bool is_prime(int n) { if (n < 2) return false; @@ -97,26 +100,26 @@ bool is_prime(u64 n) { return true; } -bool miller_rabin(u64 n, u64 k) { +bool miller_rabin(uint64_t n, uint64_t k) { if (n < 2) return false; - u64 d = n - 1; - u64 s = 0; + uint64_t d = n - 1; + uint64_t s = 0; while (d % 2 == 0) { d /= 2; s++; } - for (u64 i = 0; i < k; i++) { - u64 a = prand_range(2, n - 2); - u64 x = modexp(a, d, n); + for (uint64_t i = 0; i < k; i++) { + uint64_t a = prand_range(2, n - 2); + uint64_t x = modexp(a, d, n); if (x == 1 || x == n - 1) continue; - for (u64 r = 1; r < s; r++) { + for (uint64_t r = 1; r < s; r++) { x = modexp(x, 2, n); if (x == n - 1) break; @@ -129,18 +132,17 @@ bool miller_rabin(u64 n, u64 k) { return true; // Likely prime } -u64 mod_inverse(u64 a, u64 m) { - u64 m0 = m; - u64 y = 0, x = 1; +uint64_t mod_inverse(uint64_t a, uint64_t m) { + uint64_t m0 = m; + uint64_t y = 0, x = 1; - // Modular inverse does not exist when m is 1 if (m == 1) return 0; while (a > 1) { // q is quotient - u64 q = a / m; - u64 t = m; + uint64_t q = a / m; + uint64_t t = m; // m is remainder now m = a % m; diff --git a/rsa.h b/rsa.h index 910ae1a..53bc78d 100644 --- a/rsa.h +++ b/rsa.h @@ -1,11 +1,7 @@ #pragma once -#include "funconfig.h" #include #include -// Common public exponent, in Fermat prime form -#define PUBEXP ((1 << 16) | 0x1) - /** * @brief Calculates greatest common divider of two integers using the euclidean * algorithm @@ -14,7 +10,7 @@ * @param b Second number * @return The greatest common divider */ -u64 gcd(u64 a, u64 b); +uint64_t gcd(uint64_t a, uint64_t b); /** * @brief Computes Euler's Totient function φ(n), which counts the number of @@ -23,7 +19,7 @@ u64 gcd(u64 a, u64 b); * @param n The input number. * @return The number of integers from 1 to n that are coprime to n. */ -u64 totient(u64 n); +int totient(int n); /** * @brief Computes (a * b) % m safely without overflow. @@ -36,7 +32,7 @@ u64 totient(u64 n); * @param m The modulus. * @return (a * b) % m computed safely. */ -u64 mulmod(u64 a, u64 b, u64 m); +uint64_t mulmod(uint64_t a, uint64_t b, uint64_t m); /** * @brief Modular exponentiation (a^b) mod m @@ -45,7 +41,7 @@ u64 mulmod(u64 a, u64 b, u64 m); * @param b The exponent * @param m The modulus */ -u64 modexp(u64 a, u64 b, u64 m); +uint64_t modexp(uint64_t a, uint64_t b, uint64_t m); /** * @brief Computes the modular inverse of a modulo m. @@ -54,7 +50,7 @@ u64 modexp(u64 a, u64 b, u64 m); * @param m The modulus. * @return The modular inverse of a modulo m, or -1 if no inverse exists. */ -u64 mod_inverse(u64 a, u64 m); +uint64_t mod_inverse(uint64_t a, uint64_t m); /** * @brief Generates a random prime number within the given range. @@ -63,7 +59,7 @@ u64 mod_inverse(u64 a, u64 m); * @param max The upper bound (inclusive). * @return A prime number in the range [min, max]. */ -u64 gen_prime(u64 min, u64 max); +uint64_t gen_prime(uint64_t min, uint64_t max); /** * @brief Checks if a number is prime. @@ -71,7 +67,7 @@ u64 gen_prime(u64 min, u64 max); * @param n The number to check. * @return true if n is prime, false otherwise. */ -bool is_prime(u64 n); +bool is_prime(int n); /** * @brief Performs the Miller-Rabin primality test to check if a number is @@ -81,7 +77,7 @@ bool is_prime(u64 n); * @param k The number of rounds of testing to perform. * @return true if n is probably prime, false if n is composite. */ -bool miller_rabin(u64 n, u64 k); +bool miller_rabin(uint64_t n, uint64_t k); /** * @brief Computes the greatest common divisor (GCD) of two integers a and b @@ -96,4 +92,4 @@ bool miller_rabin(u64 n, u64 k); * + by = gcd(a, b). * @return The greatest common divisor (gcd) of a and b. */ -u64 extended_euclid(u64 a, u64 b, u64 *x, u64 *y); +int extended_euclid(int a, int b, int *x, int *y);