Miller-rabin primality test for orders of magnitude lower computational complexity

This commit is contained in:
Imbus 2025-02-12 20:37:45 +01:00
parent 28209ca70e
commit 2c7904d2b3
3 changed files with 58 additions and 2 deletions

14
main.c
View file

@ -41,6 +41,20 @@ int main() {
uint64_t n = p * q;
int before = SysTick->CNT;
bool check_a = miller_rabin(p, 10);
int miller = SysTick->CNT - before;
before = SysTick->CNT;
bool check_b = is_prime(p);
int isprime = SysTick->CNT - before;
printf("Is prime: %s %s\n", check_a ? "true" : "false",
check_b ? "true" : "false");
printf("Miller took %d ticks\n", miller);
printf("Is_prime took %d ticks\n", isprime);
// Make these work by patching printf
printf("P: %u\n", (uint32_t)p);
printf("Q: %u\n", (uint32_t)q);

34
rsa.c
View file

@ -54,7 +54,7 @@ uint64_t modexp(uint64_t a, uint64_t b, uint64_t m) {
uint64_t gen_prime(uint64_t min, uint64_t max) {
uint64_t cand = 0;
while (!is_prime(cand)) cand = prand_range(min, max);
while (!miller_rabin(cand, 10)) cand = prand_range(min, max);
return cand;
}
@ -71,6 +71,38 @@ bool is_prime(int n) {
return true;
}
bool miller_rabin(int n, int k) {
if (n < 2)
return false;
int d = n - 1;
int s = 0;
while (d % 2 == 0) {
d /= 2;
s++;
}
for (int i = 0; i < k; i++) {
int a = prand_range(2, n - 2);
int x = modexp(a, d, n);
if (x == 1 || x == n - 1)
continue;
for (int r = 1; r < s; r++) {
x = modexp(x, 2, n);
if (x == n - 1)
break;
}
if (x != n - 1)
return false; // Not prime
}
return true; // Likely prime
}
int mod_inverse(int e, int phi) {
for (int d = 0; d < phi; d++) {
if ((d * e) % phi == 1)

12
rsa.h
View file

@ -1,6 +1,6 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <stdint.h>
/**
* @brief Calculates greatest common divider of two integers using the euclidean
@ -55,3 +55,13 @@ uint64_t gen_prime(uint64_t min, uint64_t max);
* @return true if n is prime, false otherwise.
*/
bool is_prime(int n);
/**
* @brief Performs the Miller-Rabin primality test to check if a number is
* probably prime.
*
* @param n The number to test for primality.
* @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(int n, int k);