/* SI 335 Spring 2012 * Project 4, RSA program * YOUR NAME HERE */ #include <iostream> #include <string> #include <sstream> #include <cstdlib> #include "posint.hpp" using namespace std; // Prints a message on proper usage and exits with the given code void usage (const char* progname, int ret); // Function prototype. You have to fill in the implementation below. void powmod (PosInt& result, const PosInt& a, const PosInt& b, const PosInt& n); int main (int argc, char** argv) { // Seed the random number generator srand (time(NULL)); // Pick the base to use in the PosInt class PosInt::setBase (10); if (argc < 2 || argv[1][0] != '-') usage(argv[0],1); if (argv[1][1] == 'k') { //////////////////////////////////////////////////////////////////// // KEY GENERATION // //////////////////////////////////////////////////////////////////// if (argc != 2) usage(argv[0],3); // These are just "dummy" values! Replace with your actual code PosInt n (11); PosInt e (5); PosInt d (9); // Print out the public key and private key cout << e << ' ' << n << endl; cout << d << ' ' << n << endl; } else if (argv[1][1] == 'e') { //////////////////////////////////////////////////////////////////// // ENCRYPTION WITH PUBLIC KEY // //////////////////////////////////////////////////////////////////// if (argc != 4) usage(argv[0],3); // Get public key from command-line arguments PosInt e (argv[2]); PosInt n (argv[3]); // Read characters from standard in and encrypt them int c; PosInt M (0); // Initialize M to zero int twoFiftySixCubed = 256 << 16; // = 256^3 PosInt twoFiftySix (256); PosInt power (twoFiftySixCubed); bool keepGoing = true; while (keepGoing) { c = cin.get(); if (c == '\n') keepGoing = false; else { PosInt next (c); // next character, converted to a PosInt next.mul(power); // next *= power M.add(next); // M = M + next power.div(twoFiftySix); } if (power.isZero() || !keepGoing) { // HERE'S WHERE YOU HAVE TO DO THE ENCRYPTION! PosInt C (M); // THIS IS JUST A "DUMMY" VALUE cout << C << ' '; // Now reset power and M and keep going power.set(twoFiftySixCubed); M.set(0); } } cout << endl; } else if (argv[1][1] == 'd') { //////////////////////////////////////////////////////////////////// // DECRYPTION WITH PRIVATE KEY // //////////////////////////////////////////////////////////////////// if (argc != 4) usage(argv[0],3); // Get private key from command-line arguments PosInt d (argv[2]); PosInt n (argv[3]); PosInt C; // Put the line of encoded numbers into a stringstream for reading string line; getline (cin, line); istringstream iss (line); while (iss >> C) { // You have to decrypt C and print out the four characters // Note: use the "convert" function to turn a PosInt into // a regular "int". cout << "abcd"; // THIS IS JUST A DUMMY! } cout << endl; } else if (argv[1][1] == 'h') usage(argv[0], 0); else usage(argv[0],2); return 0; } //////////////////////////////////////////////////////////// // MODULAR EXPONENTIATION // //////////////////////////////////////////////////////////// // Computes a^b mod n, and stores the answer in "result". void powmod (PosInt& result, const PosInt& a, const PosInt& b, const PosInt& n) { // YOU HAVE TO FILL THIS IN! } //////////////////////////////////////////////////////////// // KARATSUBA MULTIPLICATION // //////////////////////////////////////////////////////////// // Computes x * y, and stores the result in "this" PosInt object. PosInt& PosInt::fasterMul (const PosInt& x, const PosInt& y) { // This is a suggestion of how to do this one: // First figure out the larger of the two input sizes int n = x.digits.size(); if (n < y.digits.size()) n = y.digits.size(); // Now copy the inputs into arrays of that size, with zero-padding int* xcopy = new int[n]; int* ycopy = new int[n]; for (int i=0; i<n; ++i) { xcopy[i] = 0; ycopy[i] = 0; } for (int i=0; i<x.digits.size(); ++i) xcopy[i] = x.digits[i]; for (int i=0; i<y.digits.size(); ++i) ycopy[i] = y.digits[i]; // Set "this" digit vector to a zeroed-vector of size 2n digits.assign (2*n, 0); // Now call the array version to do the actual multiplication fastMulArray (&digits[0], xcopy, ycopy, n); // We have to call normalize in case there are leading zeros normalize(); // And we don't want memory leaks do we? delete [] xcopy; delete [] ycopy; // Finally return a reference to "this" PosInt return *this; } // This does the real work of Karatsuba's algorithm // (or whatever multiplication algorithm you might write). // The input is two arrays of digits, x and y, which both have length len. // The output is stored in the array dest, which is already allocated // to the proper length. void PosInt::fastMulArray (int* dest, const int* x, const int* y, int len) { // Again, this is just a suggested general outline... if (len == 1) { // base case // YOU FILL THIS IN } else { // recursive case // YOU FILL THIS IN TOO. // Hint: you will have to allocate some memory for U, V, P0, P1, and P2 // Another hint: use the addArray and subArray helper methods from the // PosInt class! } } // Prints a message on proper usage and exits with the given code void usage (const char* progname, int ret) { cout << "Generate a public-private key pair:" << endl << "\t" << progname << " -k" << endl << "Encrypt a message with public key:" << endl << "\t" << progname << " -e <e> <n>" << endl << "Decrypt a message with private key:" << endl << "\t" << progname << " -d <d> <n>" << endl; exit(ret); }