diff --git a/helper.c b/helper.c index 83bdafc..deff16c 100644 --- a/helper.c +++ b/helper.c @@ -2,6 +2,8 @@ #include #include +uint32_t rand32() { return (rand() << 16) | (rand() & 0xFFFF); } + void print_uint128(unsigned __int128 n) { if (n == 0) { printf("0\n"); diff --git a/main b/main new file mode 100755 index 0000000..9d8503b Binary files /dev/null and b/main differ diff --git a/main.c b/main.c index c03bb15..4208e95 100644 --- a/main.c +++ b/main.c @@ -24,8 +24,8 @@ uint64_t *dec_to_bin(uint64_t d, uint64_t *length) { return binary_form; } -unsigned __int128 quick_pow(uint64_t *d_binary, unsigned __int128 a, unsigned __int128 n, uint64_t length) { - unsigned __int128 *powed = calloc(100, sizeof(unsigned __int128)); +uint64_t quick_pow(uint64_t *d_binary, uint64_t a, uint64_t n, uint64_t length) { + uint64_t *powed = calloc(100, sizeof(uint64_t)); powed[0] = a; for (int i = 1; i <= length; i++) { @@ -59,6 +59,17 @@ bool prime_test(uint64_t n, int a) { // S: see above // r = {0,... S-1} + // this should not happen but just in case + if (n <= 1) { + return false; + } + if (n == 2) { + return true; + } + if (n % 2 == 0) { + return false; + } + uint64_t d = n - 1; uint64_t S = 0; @@ -98,7 +109,7 @@ bool prime_test(uint64_t n, int a) { typedef struct { int base; - uint64_t prime; + uint32_t prime; } prime_test_t; void *prime_thread_worker(void *arg) { @@ -120,7 +131,7 @@ typedef struct { __int128 y; } euklidian_result_t; -euklidian_result_t euklidian_algorigthm_extended(unsigned __int128 a, unsigned __int128 b) { +euklidian_result_t euklidian_algorigthm_extended(uint64_t a, uint64_t b) { __int128 r = a % b, q = a / b, k = 1, xk = 0, yk = 1, next_r; __int128 prev_r = b, prev_q, prev_xk = 0, prev_yk = 1, prev_prev_xk = 1, prev_prev_yk = 0; euklidian_result_t res = {0, 0, 0}; @@ -147,17 +158,17 @@ euklidian_result_t euklidian_algorigthm_extended(unsigned __int128 a, unsigned _ __int128 x = k % 2 == 0 ? prev_xk : -prev_xk; __int128 y = k % 2 == 0 ? -prev_yk : prev_yk; - res.lnko = prev_r; + res.lnko = (uint64_t)prev_r; res.x = x; res.y = y; return res; } -unsigned __int128 kinai_maradek_tetel(uint64_t *m, unsigned __int128 d, prime_test_t *p, prime_test_t *q) { +uint64_t kinai_maradek_tetel(uint64_t *m, uint64_t d, prime_test_t *p, prime_test_t *q) { // sum(i: 1,2): Ci * Yi * Mi mod M // M: P*Q, Mp: M/P, Mq: M/Q - unsigned __int128 M = p->prime * q->prime; + uint64_t M = (uint64_t)p->prime * q->prime; uint64_t Mp = q->prime; uint64_t Mq = p->prime; @@ -165,66 +176,79 @@ unsigned __int128 kinai_maradek_tetel(uint64_t *m, unsigned __int128 d, prime_te uint64_t temp_exponent = d % (p->prime - 1); uint64_t exponent_bin_length = 0; uint64_t *exponent_as_binary = dec_to_bin(temp_exponent, &exponent_bin_length); - unsigned __int128 c1 = quick_pow(exponent_as_binary, *m, p->prime, exponent_bin_length); + uint64_t c1 = quick_pow(exponent_as_binary, *m, p->prime, exponent_bin_length); free(exponent_as_binary); // C2: c^(d mod Q-1) mod Q temp_exponent = d % (q->prime - 1); exponent_as_binary = dec_to_bin(temp_exponent, &exponent_bin_length); - unsigned __int128 c2 = quick_pow(exponent_as_binary, *m, q->prime, exponent_bin_length); + uint64_t c2 = quick_pow(exponent_as_binary, *m, q->prime, exponent_bin_length); free(exponent_as_binary); euklidian_result_t y = euklidian_algorigthm_extended(Mp, Mq); // in the struct the x will mean the y1 and y will mean the y2 // if either of them is less a negative number shift them into postive range with with hte modulo - y.x %= p->prime; - if (y.x < 0) - y.x += p->prime; + // y.x %= p->prime; + // if (y.x < 0) + // y.x += p->prime; + // + // y.y %= q->prime; + // if (y.y < 0) + // y.y += q->prime; + // + // unsigned __int128 s1 = (c1 * y.x * Mp) % M; + // unsigned __int128 s2 = (c2 * y.y * Mq) % M; + // return (s1 + s2) % M; + uint64_t y1_pos; + if (y.x < 0) { + y1_pos = p->prime - (uint64_t)(-y.x % p->prime); + } else { + y1_pos = (uint64_t)y.x % p->prime; + } - y.y %= q->prime; - if (y.y < 0) - y.y += q->prime; + uint64_t y2_pos; + if (y.y < 0) { + y2_pos = q->prime - (uint64_t)(-y.y % q->prime); + } else { + y2_pos = (uint64_t)y.y % q->prime; + } - unsigned __int128 s1 = (c1 * y.x * Mp) % M; - unsigned __int128 s2 = (c2 * y.y * Mq) % M; - return (s1 + s2) % M; + // Apply the modulo between multiplications to prevent 192-bit overflows! + uint64_t s1 = (uint64_t)((((unsigned __int128)c1 * y1_pos) % M * Mp) % M); + uint64_t s2 = (uint64_t)((((unsigned __int128)c2 * y2_pos) % M * Mq) % M); + return (uint64_t)(((unsigned __int128)s1 + s2) % M); } -unsigned __int128 rsa_encrypt(uint64_t *m, prime_test_t *p, prime_test_t *q, uint64_t *out_e, unsigned __int128 *out_d) { - unsigned __int128 n = (unsigned __int128)p->prime * q->prime; - printf("n: "); - print_uint128(n); - printf("\n"); +uint64_t rsa_encrypt(uint64_t *m, prime_test_t *p, prime_test_t *q, uint64_t *out_e, uint64_t *out_d) { + uint64_t n = (uint64_t)p->prime * q->prime; + printf("n: %ju\n", n); - unsigned __int128 fi_n = (unsigned __int128)(p->prime - 1) * (q->prime - 1); - printf("fi_n: "); - print_uint128(fi_n); - printf("\n"); + uint64_t fi_n = (uint64_t)(p->prime - 1) * (q->prime - 1); + printf("n: %ju\n", fi_n); // 2. kulcsgeneralas - uint64_t e = 0; - do { - e = rand64() % fi_n; - } while (e <= 1 && prime_test(e, p->base)); // the p and q base is used everywhere anyways, i wont pass in another arg + uint64_t e = 65537; + // TODO: put this back after debug + // do { + // e = ran32() % fi_n; + // } while (e <= 1 || !prime_test(e, p->base)); // the p and q base is used everywhere anyways, i wont pass in another arg euklidian_result_t calc_d = euklidian_algorigthm_extended(fi_n, e); // if either of them is less a negative number shift them into postive range with with hte modulo - calc_d.x %= fi_n; - if (calc_d.x < 0) - calc_d.x += fi_n; + uint64_t d; + if (calc_d.y < 0) { + d = fi_n - (uint64_t)(-calc_d.y); + } else { + d = (uint64_t)calc_d.y; + } - calc_d.y %= fi_n; - if (calc_d.y < 0) - calc_d.y += fi_n; - - unsigned __int128 d = calc_d.y; *out_e = e; *out_d = d; uint64_t length = 0; uint64_t *nyenye = dec_to_bin(e, &length); - unsigned __int128 c = quick_pow(nyenye, *m, n, length); + uint64_t c = quick_pow(nyenye, *m, n, length); free(nyenye); printf("\nc: "); @@ -256,8 +280,13 @@ int main() { pthread_join(thread_q, NULL); printf("\n"); + p.prime = 3000000019; + q.prime = 4000000007; + printf("p: %u\n", p.prime); + printf("q: %u\n", q.prime); + uint64_t e = 0; - unsigned __int128 d = 0; + uint64_t d = 0; if (!isSignature) { // rsa encryption @@ -275,22 +304,20 @@ int main() { rsa_encrypt(&dummy, &p, &q, &e, &d); printf("\n"); - unsigned __int128 signature = kinai_maradek_tetel(&m, (uint64_t)d, &p, &q); + uint64_t signature = kinai_maradek_tetel(&m, d, &p, &q); printf("Alairas (Signature): "); print_uint128(signature); // key verifacation uint64_t e_length = 0; uint64_t *e_binary = dec_to_bin(e, &e_length); - unsigned __int128 n = p.prime * q.prime; + uint64_t n = (uint64_t)p.prime * q.prime; - unsigned __int128 verified_message = quick_pow(e_binary, (uint64_t)signature, n, e_length); + uint64_t verified_message = quick_pow(e_binary, signature, n, e_length); free(e_binary); - printf("Verified Message: "); - print_uint128(verified_message); + printf("Verified Message: %ju", verified_message); - // 4. THE RESULT if (verified_message == m) { printf("\nSignature correct\n"); } else {