/* 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);
}