/*
  verify: This program should be run on the DSS to verify the DSS-signature of the student's hashed ID.
  source: http://www.ter.se/dss
*/

#include <stdio.h>
#include <gnunet/platform.h>
#include <gnunet/gnunet_util_lib.h>
#include "common.c"

/**
 * Declaration of functions
 */
int  checkParams (int nrParams, char* params[]);
void showHelp ();

/**
 * Main
 */
int main (int nrParams, char* params[])
{
  // Check parameters to the program.
  if (checkParams (nrParams, params))
  {
    return (1);
  }

  // Read the ID from file.
  char*  fileNameID = params[nrParams - 2]; // The second last argument to the program should be the file.
  char*  ID;
  size_t sizeID;
  if (readDataFromFile (fileNameID, &ID, &sizeID))
  {
    return (1);
  }
  printf ("Student's ID: %s", ID);

  // Hash the ID
  struct GNUNET_HashCode hashedID; // Hashed ID
  GNUNET_CRYPTO_hash (ID, sizeID, &hashedID); // Generate a SHA-512 hash of ID

  // Read the DSS RSA-signed hashed ID from file.
  char*  fileNameSignedHashedID = params[nrParams - 1]; // The last argument to the program should be the file.
  struct GNUNET_CRYPTO_rsa_Signature *signedHashedID;
  if (readSignatureFromFile (fileNameSignedHashedID, &signedHashedID))
  {
    return (1);
  }

  // Read the DSS RSA public pass key from file.
  struct GNUNET_CRYPTO_rsa_PublicKey *publicPassKeyDSS;
  if (readPublicKeyFromFile (DSS_PUBLIC_PASS_KEY, &publicPassKeyDSS))
  {
    return (1);
  }

  // Read the DSS RSA public fail key from file.
  struct GNUNET_CRYPTO_rsa_PublicKey *publicFailKeyDSS;
  if (readPublicKeyFromFile (DSS_PUBLIC_FAIL_KEY, &publicFailKeyDSS))
  {
    return (1);
  }

  // Verify if the hash corresponds to the DSS-signature and that the signature is valid with respect to the DSS public pass key.
  if (GNUNET_CRYPTO_rsa_verify (&hashedID, signedHashedID, publicPassKeyDSS) == GNUNET_OK)
  {
    printf ("The signature of the hashed ID is valid with respect to the public pass key of the DSS, i.e. it corresponds to the grade pass.\n");
    GNUNET_CRYPTO_rsa_public_key_free (publicPassKeyDSS); // Free the DSS RSA public pass key
  }
  else // Verify if the hash corresponds to the DSS-signature and that the signature is valid with respect to the DSS public fail key.
  if (GNUNET_CRYPTO_rsa_verify (&hashedID, signedHashedID, publicFailKeyDSS) == GNUNET_OK)
  {
    printf ("The signature of the hashed ID is vaild with respect to the public fail key of the DSS, i.e. it corresponds to the grade fail.\n");
    GNUNET_CRYPTO_rsa_public_key_free (publicFailKeyDSS); // Free the DSS RSA public fail key
  }
  else
  {
    // This can occur if the ID has been changed, e.g. if the signature is for another student's ID data.
    printf ("The signature of the hashed ID is not valid with respect to the public pass and fail key of the DSS.\n");
    return (1);
  }

  // Free the signed hashed ID
  GNUNET_CRYPTO_rsa_signature_free (signedHashedID);

  return (0);
}

/**
 * Check parameters to the program.
 */
int checkParams (int nrParams, char* params[])
{
  int i;

  if (nrParams < 3)
  {
    showHelp ();
    return (1);
  }

  for (i = 1 ; i < (nrParams - 1); i++)
  {
    if (strcmp (params[i], "-h") == 0 || strcmp (params[i], "--help") == 0)
    {
      showHelp ();
      return (1);
    }

    if (strcmp (params[i], "-v") == 0 || strcmp (params[i], "--version") == 0)
    {
      printf (VERSION"\n");
      return (1);
    }

    if (i < (nrParams - 2))
    {
      printf ("Invalid option: %s\n", params[i]);
      printf ("Use \"-h\" for help.\n");
      return (1);
    }
  }

  return (0);
}

/**
 * Show help
 */
void showHelp ()
{
  printf ("Description:\n");
  printf ("  verify: This program should be run on the DSS to verify the DSS-signature of the student's hashed ID.\n");
  printf ("Usage:\n");
  printf ("  verify <ID file> <signed hashed ID file>\n");
  printf ("Output:\n");
  printf ("  Information whether the student's hashed ID has a valid signature made by the DSS.\n");
  printf ("Dependencies:\n");
  printf ("  This program relies on GNUnet and Libgcrypt.\n");
  printf ("License:\n");
  printf ("  GNU General Public License, version 3+.\n");
}

