// rsa.C // // #include //#include #include "bigint.h" #include #include #include "numlib.c" #include // Compute X^N ( mod P ) // Borrowed from Weiss' implementation, p. 231 // Will use bigint class, from Astrachan's implementation //template //HugeInt //Power( const HugeInt & X, const HugeInt & N, //const HugeInt & P ) //{ // if (N == 0) // return 1; // HugeInt Tmp = Power( ( X * X ) % P, N / 2, P ); // if ( N % 2 != 0 ) // Tmp = ( Tmp * X ) % P; // return Tmp; //} // Encrypt and Decrypt calculate M^e (mod N), taking the parameters // as the said variables in the same order. They essentially do the same // thing. template HugeInt Encrypt( const HugeInt & M, const HugeInt & E, const HugeInt & N ) { return power( M, E, N ); } template HugeInt Decrypt( const HugeInt & R, const HugeInt & D, const HugeInt & N ) { return power( R, D, N ); } EncryptTest() { long P = 127; long Q = 211; long E = 13379; long M = 10237; long D = 11099; long N = P * Q; long Nx = (P - 1) * (Q - 1); cout << "N and N' are: " << N << ", " << Nx << endl; long R = Encrypt(M, E, N); cout << "Encrypted, we get: " << R << "." << endl; long Mx = Decrypt( R, D, N); cout << "Decrypted, we get an M, " << Mx << ", that should be" << " the same as " << M << endl; return 1; } // Witness is the implementation of Theorem 9.1 (Fermat's // Little Theorem) and 9.2 from Weiss, p. 319-320. Together, // we are able to check, with 75% certainty, that N is prime. // Multiple tests found in IsPrime prove with much greater // certainty that it is indeed prime. // Witness and IsPrime were adapted from Weiss, p. 321. //template //HugeInt //Witness( const HugeInt & A, const HugeInt & i, //const HugeInt & N ) //{ //if (i == 0) // return 1; // Fermat's little theorem testing //HugeInt X = Witness( A, i/2, N ); //if ( X == 0 ) // return 0; // HugeInt Y = Power( X, X, N ); // more effecient to use power // if ( Y == 1 && X != 1 && X != N - 1 ) // return 0; // if ( i % 2 != 0 ) // Y = Power( A, Y, N ); // return Y; //} //template //int //IsPrime( const HugeInt & N ) //{ // const int NumTrials = 10; // for( int Counter = 0; Counter < NumTrials; Counter++ ){ // if( Witness( RandInt( 2, N - 2 ), N - 1, N ) != 1 ) // return 0; // } // return 1; //} // GetPrime randomly picks a large, odd number until it gets // one that is prime. It uses is_prime to check for primality. // The more failed primes that occur, the larger the N becomes. BigInt GetPrime( ) { srand48( (unsigned int) time(0) ); BigInt N = rand_int( 100000000, 100000000000 ); BigInt NN = rand_int( 100000000, 100000000000 ); N = N * NN * N; BigInt Odd = 2; if ( N % 2 == 0 ) N = N+1; while ( is_prime( N ) == 0 ){ N = N + Odd; } return N; } template HugeInt GetN( const HugeInt & P, const HugeInt & Q ) { return (P * Q); } template HugeInt GetNPrime( const HugeInt & P, const HugeInt & Q ) { return( ( P - 1 ) * ( Q - 1 ) ); } template HugeInt GetE( const HugeInt & NPrime ) { HugeInt E = 1000; while ( gcd ( E, NPrime ) != 1 ) { E = E+1; } return E; } template HugeInt GetD( const HugeInt & E, const HugeInt & NPrime ) { return ( inverse( E, NPrime ) ); } //main() //{ // BigInt P = GetPrime(); // BigInt Q = GetPrime(); // cout << "P and Q are: " << P << ", " << Q << endl; // BigInt N = GetN( P, Q ); // BigInt NPrime = GetNPrime( P, Q ); // cout << "And N and N' are: " << N << ", " << NPrime << endl; // BigInt E = GetE( NPrime ); // cout << "E is: " << E << endl; // BigInt D = GetD( E, NPrime ); // cout << "D is: " << D << endl; //}