1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | /* SI 335 Spring 2013 * Project 2, 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); } |