%PDF- %PDF-
Direktori : /proc/309157/root/home/waritko/suave/ondra/ |
Current File : //proc/309157/root/home/waritko/suave/ondra/kry-ondra.c |
/* * File: kry.c * Date: 11.4.2016 * Author: Ondrej Cienciala, xcienc02@usi.vutbr.cz * Project: Projekt c. 2 - Implementation and breaking RSA * Additional info: * https://wis.fit.vutbr.cz/FIT/st/cwk.php?id=10888&csid=591 */ /*===========================================================================*/ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdbool.h> #include <time.h> #include <gmp.h> /*===========================================================================*/ /*---------------------------------------------------------------------------*/ /* * Modular exponentiation. * R = B^E mod M * Returns result of modular exponentiation. * * Params are mpz_t numbers (Result, Base, Exponent, Modulus). * * Tato funkce vznikla, protoze cvicici kazdy den * zakaze a povoli pouzit jinou funkci just for fun. */ void modExp(mpz_t r, mpz_t B, mpz_t E, mpz_t M) { mpz_powm(r, B, E, M); return; mpz_t b, e, m, const2, temp; mpz_set_ui(r, 1); // Set r to 1 mpz_init(b); mpz_set(b, B); mpz_init(e); mpz_set(e, E); mpz_init(m); mpz_set(m, M); mpz_init(const2); mpz_set_ui(const2, 2); // Set const2 to 2 mpz_init(temp); while (mpz_cmp_ui(e, 0) > 0) // Compare op1 and op2. Return a positive value if op1 > op2, zero if op1 = op2, or a negative value if op1 < op2. { mpz_mod(temp, e, const2); if (mpz_cmp_ui(temp, 1) == 0) { mpz_mul(r, r, b); mpz_mod(r, r, m); } mpz_div_2exp(e, e, 1); mpz_mul(b, b, b); mpz_mod(b, b, m); } // gmp_printf("0x%Zx\n", r); mpz_clear(e); mpz_clear(m); mpz_clear(b); mpz_clear(temp); mpz_clear(const2); } /*---------------------------------------------------------------------------*/ /* * Compute Jacobi symbol * (a/n) a is integer, n must be an odd integer. * * Params are mpz_t number a and n. */ int jacobi(mpz_t A, mpz_t N) { int res = 1; mpz_t temp; mpz_init(temp); mpz_t a; mpz_init_set(a, A); mpz_t n; mpz_init_set(n, N); if (mpz_cmp_ui(a, 0) == 0) { return 0; } if (mpz_cmp_ui(a, 0) < 0) { mpz_neg(a, a); mpz_mod_ui(temp, n, 4); if (mpz_cmp_ui(temp, 3) == 0) { res = -res; } } if (mpz_cmp_ui(a, 1) == 0) { return res; } while (mpz_cmp_ui(a, 0) != 0) { if (mpz_cmp_ui(a, 0) < 0) { mpz_neg(a, a); mpz_mod_ui(temp, n, 4); if (mpz_cmp_ui(temp, 3) == 0) { res = -res; } } mpz_mod_ui(temp, a, 2); while (mpz_cmp_ui(temp, 0) == 0) { mpz_fdiv_q_ui(a, a, 2); // Divide by 2 and round down (floor)) mpz_mod_ui(temp, n, 8); if ((mpz_cmp_ui(temp, 3) == 0) || (mpz_cmp_ui(temp, 5) == 0)) { res = -res; } mpz_mod_ui(temp, a, 2); } mpz_swap(a, n); mpz_mod_ui(temp, a, 4); if (mpz_cmp_ui(temp, 3) == 0) { mpz_mod_ui(temp, n, 4); if (mpz_cmp_ui(temp, 3) == 0) { res = -res; } } mpz_mod(a, a, n); mpz_fdiv_q_ui(temp, n, 2); // Divide by 2 and round down (floor)) if (mpz_cmp(a, temp) > 0) { mpz_sub(a, a, n); } } if (mpz_cmp_ui(n, 1) == 0) { return res; } return 0; } /*---------------------------------------------------------------------------*/ /* * Solovay-Strassen primality test. Returns true if number p is prime. * * Param p - number to be tested. * Param iteration - iteration count, defines prime certainty. */ bool solovayStrassen(mpz_t p, int iteration, gmp_randstate_t randState) { mpz_t temp; mpz_init(temp); mpz_t temp2; mpz_init(temp2); mpz_t a; mpz_init(a); int jacob; if (mpz_cmp_ui(p, 2) < 0) { return false; } mpz_mod_ui(temp, p, 2); if ((mpz_cmp_ui(p, 2) != 0) && (mpz_cmp_ui(temp, 0) == 0)) { return false; } int i; for (i = 0; i < iteration; i++) { mpz_sub_ui(temp2, p, 2); mpz_urandomm(temp, randState, temp2); // temp = <0, p-3> mpz_add_ui(a, temp, 2); // temp = temp + 2 ... <2, p-1> // gmp_printf("a = %Zd\n", a); // gmp_printf("p = %Zd\n", p); jacob = jacobi(a, p); if (jacob == 1) { mpz_add_ui(temp, p, 1); } else if (jacob == -1) { mpz_sub_ui(temp, p, 1); } else { mpz_set(temp, p); } mpz_mod(temp, temp, p); // gmp_printf("temp (jacobian) = %Zd\n", temp); mpz_set(temp2, p); mpz_sub_ui(temp2, temp2, 1); mpz_fdiv_q_ui(temp2, temp2, 2); // gmp_printf("temp2 = %Zd\n", temp2); modExp(temp2, a, temp2, p); // printf("jacobi = %i\n", jacobi(a, p)); // gmp_printf("temp2 = %Zd\n", temp2); if ((jacob == 0) || (mpz_cmp(temp2, temp) != 0)) { return false; } } return true; } /*---------------------------------------------------------------------------*/ /* * Generates prime number n with certain probability. * Number n has bitCount bits. * * Param n - probably prime number. * Param bitCount - bit count of n * Param randState - settings of random number generator. . */ void generateRsaFactor(mpz_t n, int bitCount, gmp_randstate_t randState) { while (1) { mpz_urandomb(n, randState, bitCount); // gmp_printf("nahodne cislo je %Zd\n", n); mpz_setbit(n, bitCount - 1); mpz_setbit(n, bitCount - 2); // gmp_printf("nahodne cislo po nastaveni bitu je %Zd\n", n); if (solovayStrassen(n, 30, randState)) { // It is prime break; } } } /*---------------------------------------------------------------------------*/ /* * Counts modular multiplicative inverse and store result in param res. * Returns true if result was correctly counted, otherwise false. * * Param res - result. * Param A - number. * Param M - modulus. */ bool modMulInverse(mpz_t res, mpz_t A, mpz_t M) { mpz_t m0, t, q, x0, x1, a, m; mpz_init(m0); mpz_init(t); mpz_init(q); mpz_init(x0); // Already set to 0 mpz_init(x1); mpz_init(a); mpz_init(m); mpz_set(m0, m); mpz_set_si(x1, 1); mpz_set(a, A); mpz_set(m, M); if (mpz_cmp_ui(m, 1) == 0) { mpz_set_si(res, 0); } while (mpz_cmp_ui(a, 1) > 0) { mpz_fdiv_q(q, a, m); mpz_set(t, m); mpz_mod(m, a, m); mpz_set(a, t); mpz_set(t, x0); mpz_mul(x0, q, x0); mpz_neg(x0, x0); mpz_add(x0, x1, x0); mpz_set(x1, t); } if (mpz_cmp_ui(x1, 0) < 0) { mpz_add(x1, x1, m0); return false; } mpz_set(res, x1); return true; } /*---------------------------------------------------------------------------*/ /* * Generate and print RSA keys in hexa format: * P Q N E D * * Param bitModulusCount - bit size of required public modulus. */ void generateKeys(int bitModulusCount) { mpz_t p, q, n, fiN, d, e, temp; mpz_init(p); mpz_init(q); mpz_init(n); mpz_init(fiN); mpz_init(d); mpz_init(e); mpz_init(temp); int pBit, qBit; gmp_randstate_t randState; gmp_randinit_mt(randState); gmp_randseed_ui(randState, time(NULL)); pBit = bitModulusCount / 2; if (bitModulusCount % 2 == 0) { qBit = pBit; } else { qBit = pBit + 1; } while (true) { generateRsaFactor(p, pBit, randState); generateRsaFactor(q, qBit, randState); // gmp_printf("nahodne cislo je %Zd\n", p); // mpz_setbit(p, pBit - 1); // mpz_setbit(p, pBit - 2); // gmp_printf("nahodne cislo po nastaveni bitu je %Zd\n", p); // gmp_printf("nahodne cislo po nastaveni bitu je %Zd\n", q); mpz_mul(n, p, q); // gmp_printf("modulus je %Zd\n", n); mpz_sub_ui(p, p, 1); mpz_sub_ui(q, q, 1); mpz_mul(fiN, p, q); mpz_add_ui(p, p, 1); mpz_add_ui(q, q, 1); // gmp_printf("FI n je %Zd\n", fiN); mpz_set_ui(e, 65537); // Set public exponent to constant mpz_mod(temp, fiN, e); if (mpz_cmp_ui(temp, 0) == 0) { continue; } if (!modMulInverse(d, e, fiN)) { continue; } break; } // gmp_printf("Modular inverse je %Zd\n", d); // gmp_printf("%Zd %Zd %Zd %Zd %Zd\n", p, q, n, e, d); // Decadic print gmp_printf("0x%Zx 0x%Zx 0x%Zx 0x%Zx 0x%Zx\n", p, q, n, e, d); } /*---------------------------------------------------------------------------*/ /* * Tato funkce neni implementovana - vynalozena prace neodpovida bodovemu hodnoceni. * Factorization of given modulus N. * Prints factor P in hexa format. * * Param N - string containing hex value (starting 0x) of modulus. */ void breakRSA(char *N) { } /*---------------------------------------------------------------------------*/ /* * Encrypt message M, given public exponent E and public modulus N. * C = M^E mod N * Prints ciphertext C in hexa format. * * Params are strings in hexa format. */ void encrypt(char *E, char *N, char *M) { mpz_t c, e, n, m; mpz_init(c); // Default init is to 0 mpz_init_set_str(e, E, 0); mpz_init_set_str(n, N, 0); mpz_init_set_str(m, M, 0); modExp(c, m, e, n); gmp_printf("0x%Zx\n", c); mpz_clear(c); mpz_clear(e); mpz_clear(n); mpz_clear(m); } int main(int argc, char**argv) { if (argc == 3) { if (strcmp(argv[1], "-g") == 0) { generateKeys(atoi(argv[2])); } else { fprintf(stderr, "Invalid option!\n"); } } else if (argc == 5) { if (strcmp(argv[1], "-e") == 0 || strcmp(argv[1], "-d") == 0) { encrypt(argv[2], argv[3], argv[4]); } else { fprintf(stderr, "Invalid option!\n"); } } else { fprintf(stderr, "Bad number of params!\n"); } return 0; }