static char *
rw_serialize_pub (const dckey *key)
{
  const rw_pub *pk = (const rw_pub *) key;
  char *res = NULL;

  if (cat_str (&res, rabin_1.name)
      || cat_str (&res, ":Pub,n=")
      || cat_mpz (&res, pk->n)) {
    free (res);
    res = NULL;
  }
  return res;
}
static char *
rw_encrypt (const dckey *key, const char *msg)
{
  const rw_pub *pk = (const rw_pub *) key;
  mpz_t m;
  char *res = NULL;

  mpz_init (m);
  if (pre_encrypt (m, msg, pk->nbits)) {
    mpz_clear (m);
    return NULL;
  }
  E1 (m, m, pk->n);
  E2 (m, m, pk->n);
  cat_mpz (&res, m);
  mpz_clear (m);
  return res;
}
static char *
rw_sign (const dckey *key, const char *msg)
{
  const rw_priv *sk = k2priv (key);
  sha1_ctx sc;
  mpz_t m;
  char *res = NULL;

  mpz_init (m);
  sha1_init (&sc);
  sha1_update (&sc, msg, strlen (msg));
  if (pre_sign (m, &sc, sk->nbits)) {
    mpz_clear (m);
    return NULL;
  }
  E1 (m, m, sk->n);
  D2 (m, m, sk, prng_getword ());
  cat_mpz (&res, m);
  mpz_clear (m);
  return res;
}
void
nidh (dckey *priv, dckey *pub, char *priv_id, char *pub_id, char *label)
{
  rawpub rpub;
  rawpriv rpriv;

  int reserve;
  /* Let's name it that! */

  /* step 0: check that the private and public keys are compatible,
     i.e., they use the same group parameters */
  if ((-1 == get_rawpub (&rpub, pub)) 
      || (-1 == get_rawpriv (&rpriv, priv))) {
    printf ("%s: trouble importing GMP values from ElGamal-like keys\n",
	    getprogname ());

    printf ("priv:\n%s\n", dcexport_priv (priv));
    printf ("pub:\n%s\n", dcexport_pub (pub));

    exit (-1);    
  } else if (mpz_cmp (rpub.p, rpriv.p)
	     || mpz_cmp (rpub.q, rpriv.q)
	     || mpz_cmp (rpub.g, rpriv.g)) {
        printf ("%s:  the private and public keys are incompatible\n",
	    getprogname ());
        printf ("priv:\n%s\n", dcexport_priv (priv));
        printf ("pub:\n%s\n", dcexport_pub (pub));

        exit (-1);
  } else {
    
    /* step 1a: compute the Diffie-Hellman secret
                (use mpz_init, mpz_powm, mpz_clear; look at elgamal.c in 
                 the libdcrypt source directory for sample usage 
     */
    char *Diffie_Hellman_Secret_String = 0;
    {
      
      mpz_t dhSecretInt;
      mpz_init(dhSecretInt);
      mpz_powm(dhSecretInt, rpub.y, rpriv.x, rpub.p); 
      reserve = cat_mpz(&Diffie_Hellman_Secret_String, dhSecretInt); /* EC need 0; MALLOC */
      mpz_clear(dhSecretInt);
      if (reserve) {
          free(Diffie_Hellman_Secret_String);
          printf("error allocating memory\n");
          exit(1);
      }
      /* printf("Diffie_Hellman_Secret_String: %s\n",Diffie_Hellman_Secret_String); */
    }

    /* step 1b: order the IDs lexicographically */
    char *firstId = NULL, *secondId = NULL;
    
    if (strcmp (priv_id, pub_id) < 0) {
      firstId = priv_id;
      secondId = pub_id;
    } else {
      firstId = pub_id;
      secondId = priv_id;
    }    
    
    /* step 1c: hash DH secret and ordered id pair into a master key */
    char key_master[20];
    {
      sha1_ctx shaCipherText;
      sha1_init(&shaCipherText);
      sha1_update(&shaCipherText, Diffie_Hellman_Secret_String, strlen(Diffie_Hellman_Secret_String));

      char *id12;
      size_t len1, len2;
      len1 = strlen(firstId); len2 = strlen(secondId);
      id12 = (char*)malloc(len1+len2+1); /* +1 for \0 */
      strcpy(id12, firstId);
      strcat(id12, secondId);
      assert(strlen(id12) == len1+len2); 
      sha1_update(&shaCipherText, id12, len1+len2);
      free(id12);
      
      sha1_final(&shaCipherText, (void*)key_master);
      /*20 bytes*/
      
    }    
    
    /* step 2: derive the shared key from the label and the master key */
    /*I will work with minimum requirement satisfaction model. Thanks to the open source community for providing me with enough reasoning for that.*/
    char sizeofkey[32];
    {
      char sizeofkey_0[20];
      size_t len0 = strlen(label)+7;
      char *label0 = (char*)malloc(len0);
      strcpy(label0, label);
      strcat(label0, "AES-CTR");
      hmac_sha1(key_master, 20, sizeofkey_0, label0, len0);
      free(label0);

      char sizeofkey_1[20];
      size_t len1 = strlen(label)+9;
      char *label1 = (char*)malloc(len1);
      strcpy(label1, label);
      strcat(label1, "CBC-MAC");
      hmac_sha1(key_master, 20, sizeofkey_1, label1, len1);
      free(label1);

      strncpy(sizeofkey, sizeofkey_0, 16);
      strncpy(sizeofkey+16, sizeofkey_1, 16);
    
    }
    
    /*
	step 3: armor the shared key and write it to file.
    Filename should be of the form <label>-<priv_id>.b64
	 
	size_t fn_len = strlen(label)+1+strlen(priv_id)+1+strlen(pub_id)+4+1;
	*/

    char *fn = (char *) malloc(32);
	fn = armor64(sizeofkey, 32);
	*(fn + 32) = '\0';
	int fdsk;
	fdsk = open (label, O_WRONLY|O_TRUNC|O_CREAT, 0600);
	int status;
	status = write (fdsk, fn, strlen (fn));
	printf("value of status: %d\n", status);
	status = write (fdsk, "\n", 1);
	printf("value of status: %d\n", status);
    free (fn);
    close (fdsk);	
  }
}