#include <iostream>
#include <time.h>
#include <gmpxx.h>

using namespace std;

    unsigned long seed = time(NULL);   //inicializace generatoru nah.cisel

mpz_class prime(unsigned int bits)
{

	gmp_randclass generator(gmp_randinit_default);

	generator.seed(seed);


	mpz_class rand = generator.get_z_bits(bits);
	mpz_nextprime(rand.get_mpz_t(), rand.get_mpz_t());

	return rand;
}


mpz_class GCD(mpz_class a, mpz_class b) {

  mpz_t ans;
  mpz_init (ans);

  mpz_gcd(ans, a.get_mpz_t(), b.get_mpz_t());


  mpz_class ans2;
  ans2 = mpz_class(ans);


  mpz_clear(ans);

  return ans2;
}

int main() {

    cout << "--------------------------------------" << endl;
    cout << "Diffie-Hellman   by Jaroslav VALENTA" << endl;
    cout << "--------------------------------------" << endl;
    cout << "Zadejte delku klice v bitech" << endl;
    int key;
    cin >> key;
    mpz_class p=prime(key);
    seed = seed+time(NULL);  //inicializace generatoru nah.cisel
    mpz_class g=prime(key);
    seed = seed+time(NULL);  //inicializace generatoru nah.cisel
    cout << "\n"<<"     Verejne prvocislo p = " << p << endl;

    cout << "     Generator g         = "<< g << endl;

//a

    cout <<"\n"<<"Zadejte tajne cislo Petra" << endl;
    mpz_class a;
    cin >> a;
//b

    cout << "Zadejte tajne cislo Lucie" << endl;
    mpz_class b;
    cin >> b;

//vypocet alfa
    mpz_t alfa;
    mpz_init (alfa);
    mpz_powm(alfa,g.get_mpz_t(),a.get_mpz_t(),p.get_mpz_t());
    cout << "     alfa = " << alfa<< endl;

//vypocet beta
    mpz_t beta;
    mpz_init (beta);
    mpz_powm(beta,g.get_mpz_t(),b.get_mpz_t(),p.get_mpz_t());
    cout << "     beta = " << beta<< endl;

//klic Petr
    mpz_t petr;
    mpz_init (petr);
    mpz_powm(petr,beta,a.get_mpz_t(),p.get_mpz_t());
 //klic Lucie
    mpz_t lucie;
    mpz_init (lucie);
    mpz_powm(lucie,alfa,b.get_mpz_t(),p.get_mpz_t());

    cout << "\n"<<"klice" << endl;
    cout << "-------" << endl;
    cout << "     Klic Petra  = "<< petr<< endl;
    cout << "     Klic Lucky  = "<< lucie<< endl;
    mpz_clear(alfa);
    mpz_clear(beta);
    mpz_clear(petr);
    mpz_clear(lucie);
    cin.get();
    getchar();
return 0;
}
