#ifndef RSA_H
#define RSA_H

#include <cassert>
#include <string>
using namespace std;

#include <NTL/ZZ.h>
using namespace NTL;

#include <primegen.h>
#include <print.h>

/*!
\brief RSA Encryption

The product n is public but not its factors.
 Choose e to be large, do not use a small e.

This class encrypts a message string of digits to 
 another string of digits.
*/
class rsaE
{
public:

  /** Public product p*q. */
  ZZ n;
  /** Public exponent. */
  ZZ e;

  /** Encrypt a message string. m is a string of digits. */
  void operator() ( string & c, string const & m ) const;
};



/*!
\brief RSA Decryption

The factors p and q are secret. This class decrypts a
 message string of digits to their original message string
 of digits.
*/
class rsaD
{
  /** The inverse of e. */
  ZZ d; 
  /** p*q. */
  ZZ n; 
public:

  /** The secret prime factor p. */
  ZZ p;
  /** The secret prime factor q. */
  ZZ q;
  /** Public exponent. */
  ZZ e;

  /** Call after changing p, q, or e. */
  void init();

  /** Decrypt a string of digits. */
  void operator() ( string & m, string const & c ) const;
};

/*!
\brief Key Generation.

There are two ways to generate keys, these are accessed
 by two different constructor calls.

The result is two files generated, encrypt.txt and decrypt.txt .
 The encrypt.txt sould be public, but the decrypt.txt must
 be private because it contains the key.
*/
class rsaGenKey
{
  /** Finds a large e value by random means. */
  void finde();
  /** Calculate the block size. */
  void blocksizecalc();
  /** Handles some prime number operations. */
  largePrimeGenerator lpg;
  /** Generates everything such as the block size, encrypt 
      and decrypt text files. */
  void genkey();
public:

  /** Randomly generate key. */
  rsaGenKey(uintc _nbits);
  /** Sequentially generate key. */
  rsaGenKey
  (
    uintc _nbits,
    string const & _p,
    string const & _q
  );

  /** The number of bits. */
  uintc nbits;

  /** The block size. */
  uint blocksize;

  /** The secret factor p. */
  ZZ p;
  /** The secret factor q. */
  ZZ q;
  /** The public exponent e. */
  ZZ e;
  /** The public product p*q. */
  ZZ n;
  /** The secret (p-1)*(q-1). */
  ZZ n2;

  /** Prints the state, for debug purposes. */
  void print() const;

};



#endif



