#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/timeb.h>

#include <cryptlib.h>
#include <dsa.h>
#include <osrng.h>
#include <des.h>

#include <hex.h>
#include <filters.h>

#define MAXLINESIZE        2048
#define PUBLIC_KEY_NAME       "PUBLICKEY"
#define PRIVATE_KEY_NAME      "PRIVATEKEY"

char delimiters[] = "= \t\n\0";

USING_NAMESPACE(CryptoPP)
USING_NAMESPACE(std)

RandomPool rng;

/*-----------------------------------------------------------------*/

static void init_RNG()
{
  struct timeb tp;
  char         time_str[18];

  struct tm *temp;
  struct tm  detailed;

  ftime(&tp);
  temp = localtime(&tp.time);
  detailed = *temp;
  
  sprintf(time_str,"%04i%02i%02i%02i%02i%02i%03i",
	detailed.tm_year+1900,
	detailed.tm_mon+1,
	detailed.tm_mday,
	detailed.tm_hour,
	detailed.tm_min,
	detailed.tm_sec,
	tp.millitm);

  rng.Put((unsigned char*)time_str,17);
}

/*-----------------------------------------------------------------*/

void sign(const char *privateKey, const char *publicKey)
{
  init_RNG();

  StringSource fs((byte*)privateKey,strlen(privateKey), true, new HexDecoder());
  GDSA<SHA>::Signer priv(fs);
  GDSA<SHA>::Verifier pub(priv);
  
  if (!priv.GetKey().Validate(rng,2))
  {
	printf("Could not validate private key\n%s\n",privateKey);
	//return ;
  }
  else
	printf("Validated private key\n");
  
  if (!pub.GetKey().Validate(rng,2))
  {
	printf("Could not validate public key\n");
  }
  else 
	printf("Validated public key\n");
}

/*-----------------------------------------------------------------*/

int readKeyFile(const char *filename,char *privKey,char *pubKey)
{
  FILE *keyFile;
  int   count = 0;
  char *token;

  char line[MAXLINESIZE];

  if ((keyFile = fopen(filename,"r")) == NULL) 
  {
	fprintf(stderr,"Could not open key file\n");
	return -1;
  }

  fgets (line, MAXLINESIZE, keyFile);
  while (!feof(keyFile)) 
  {
	token = (char*)strtok(line,delimiters);

	if (token!=NULL)
	{
	  if (strcmp(token,PRIVATE_KEY_NAME) == 0)
	  {
		token = (char*) strtok(NULL,delimiters);
		if (token != NULL)
		{
		  strcpy(privKey,token);
		  count += 1;
		}
	  }
	  else if (strcmp(token,PUBLIC_KEY_NAME) == 0)
	  {
		token = (char*) strtok(NULL,delimiters);
		if (token != NULL)
		{
		  strcpy(pubKey,token);
		  count += 2;
		}
	  }
	}
	
	fgets (line, MAXLINESIZE, keyFile);
  }

  fclose(keyFile);

  return count;
}

/*-----------------------------------------------------------------*/

int main(int argc,char *argv[])
{
  if (argc<2)
  {
	printf("Usage: %s keyfilename\n",argv[0]);
	return 1;
  }

  char privKey[MAXLINESIZE] = "";
  char pubKey[MAXLINESIZE]  = "";
  int  stat;

  stat = readKeyFile(argv[1],privKey,pubKey);

  switch(stat){
  case -1 : return 1;//"Could not open key file";
  case  0 : return 2;//"Could not find private key and public key!";
  case  1 : return 3;//"Could not find public key";
  case  2 : return 4;//"Could not find private key";
  case  3 : break;
  default : return 5;//"Unknown error occured reading key file";
  }

  sign(privKey,pubKey);

  return 0;
}
