%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /proc/309157/root/home/waritko/suave/ondra/
Upload File :
Create Path :
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;
}

Zerion Mini Shell 1.0