﻿using System;

/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
*/

/* test driver and function exerciser for MPIN API Functions */


public class TestMPIN
{
	internal static bool PERMITS = true;
	internal static bool PINERROR = true;
	internal static bool FULL = true;
	internal static bool SINGLE_PASS = false;

	internal static void printBinary(sbyte[] array)
	{
		int i;
		for (i = 0;i < array.Length;i++)
		{
			Console.Write("{0:x2}", array[i]);
		}
		Console.WriteLine();
	}

	public static void Main(string[] args)
	{
		RAND rng = new RAND();
		sbyte[] raw = new sbyte[100];
		for (int i = 0;i < 100;i++)
		{
			raw[i] = (sbyte)(i + 1);
		}
		rng.seed(100,raw);

		int EGS = MPIN.EGS;
		int EFS = MPIN.EFS;
		int G1S = 2 * EFS + 1; // Group 1 Size
		int G2S = 4 * EFS; // Group 2 Size
		int EAS = 16;

		sbyte[] S = new sbyte[EGS];
		sbyte[] SST = new sbyte[G2S];
		sbyte[] TOKEN = new sbyte[G1S];
		sbyte[] PERMIT = new sbyte[G1S];
		sbyte[] SEC = new sbyte[G1S];
		sbyte[] xID = new sbyte[G1S];
		sbyte[] xCID = new sbyte[G1S];
		sbyte[] X = new sbyte[EGS];
		sbyte[] Y = new sbyte[EGS];
		sbyte[] E = new sbyte[12 * EFS];
		sbyte[] F = new sbyte[12 * EFS];
		sbyte[] HID = new sbyte[G1S];
		sbyte[] HTID = new sbyte[G1S];

		sbyte[] G1 = new sbyte[12 * EFS];
		sbyte[] G2 = new sbyte[12 * EFS];
		sbyte[] R = new sbyte[EGS];
		sbyte[] Z = new sbyte[G1S];
		sbyte[] W = new sbyte[EGS];
		sbyte[] T = new sbyte[G1S];
		sbyte[] CK = new sbyte[EAS];
		sbyte[] SK = new sbyte[EAS];

/* Trusted Authority set-up */

		MPIN.RANDOM_GENERATE(rng,S);
		Console.Write("Master Secret s: 0x");
		printBinary(S);

 /* Create Client Identity */
		 string IDstr = "testUser@miracl.com";
		sbyte[] CLIENT_ID = IDstr.GetBytes();

		sbyte[] HCID = MPIN.HASH_ID(CLIENT_ID); // Either Client or TA calculates Hash(ID) - you decide!

		Console.Write("Client ID= ");
		printBinary(CLIENT_ID);

/* Client and Server are issued secrets by DTA */
		MPIN.GET_SERVER_SECRET(S,SST);
		Console.Write("Server Secret SS: 0x");
		printBinary(SST);

		MPIN.GET_CLIENT_SECRET(S,HCID,TOKEN);
		Console.Write("Client Secret CS: 0x");
		printBinary(TOKEN);

/* Client extracts PIN from secret to create Token */
		int pin = 1234;
		Console.WriteLine("Client extracts PIN= " + pin);
		int rtn = MPIN.EXTRACT_PIN(CLIENT_ID,pin,TOKEN);
		if (rtn != 0)
		{
			Console.WriteLine("FAILURE: EXTRACT_PIN rtn: " + rtn);
		}

		Console.Write("Client Token TK: 0x");
		printBinary(TOKEN);

		if (FULL)
		{
			MPIN.PRECOMPUTE(TOKEN,HCID,G1,G2);
		}
		int date;
		if (PERMITS)
		{
			date = MPIN.today();
			Console.WriteLine("Date= "+date);
/* Client gets "Time Token" permit from DTA */
			MPIN.GET_CLIENT_PERMIT(date,S,HCID,PERMIT);
			Console.Write("Time Permit TP: 0x");
			printBinary(PERMIT);

/* This encoding makes Time permit look random - Elligator squared */
			MPIN.ENCODING(rng,PERMIT);
			Console.Write("Encoded Time Permit TP: 0x");
			printBinary(PERMIT);
			MPIN.DECODING(PERMIT);
			Console.Write("Decoded Time Permit TP: 0x");
			printBinary(PERMIT);
		}
		else
		{
			date = 0;
		}

		Console.Write("\nPIN= ");
//		Scanner scan = new Scanner(System.in);
//		pin = scan.Next();

		pin=int.Parse(Console.ReadLine());

/* Set date=0 and PERMIT=null if time permits not in use

Client First pass: Inputs CLIENT_ID, optional RNG, pin, TOKEN and PERMIT. Output xID =x .H(CLIENT_ID) and re-combined secret SEC
If PERMITS are is use, then date!=0 and PERMIT is added to secret and xCID = x.(H(CLIENT_ID)+H(date|H(CLIENT_ID)))
Random value x is supplied externally if RNG=null, otherwise generated and passed out by RNG

IMPORTANT: To save space and time..
If Time Permits OFF set xCID = null, HTID=null and use xID and HID only
If Time permits are ON, AND pin error detection is required then all of xID, xCID, HID and HTID are required
If Time permits are ON, AND pin error detection is NOT required, set xID=null, HID=null and use xCID and HTID only.


*/

		sbyte[] pxID = xID;
		sbyte[] pxCID = xCID;
		sbyte[] pHID = HID;
		sbyte[] pHTID = HTID;
		sbyte[] pE = E;
		sbyte[] pF = F;
		sbyte[] pPERMIT = PERMIT;
		sbyte[] prHID;

		if (date != 0)
		{

			prHID = pHTID;
			if (!PINERROR)
			{
				pxID = null;
				pHID = null;
			}
		}
		else
		{
			prHID = pHID;
			pPERMIT = null;
			pxCID = null;
			pHTID = null;
		}
		if (!PINERROR)
		{
			pE = null;
			pF = null;
		}

				if (SINGLE_PASS)
				{
			Console.WriteLine("MPIN Single Pass");
				  int timeValue = MPIN.GET_TIME();
				  rtn = MPIN.CLIENT(date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT,timeValue,Y);
			if (rtn != 0)
			{
			  Console.WriteLine("FAILURE: CLIENT rtn: " + rtn);
			}

				  if (FULL)
				  {
					HCID = MPIN.HASH_ID(CLIENT_ID);
					MPIN.GET_G1_MULTIPLE(rng,1,R,HCID,Z); // Also Send Z=r.ID to Server, remember random r
				  }

				  rtn = MPIN.SERVER(date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF,CLIENT_ID,timeValue);
				  if (rtn != 0)
				  {
			  Console.WriteLine("FAILURE: SERVER rtn: " + rtn);
				  }

				  if (FULL)
				  {
					MPIN.GET_G1_MULTIPLE(rng,0,W,prHID,T); // Also send T=w.ID to client, remember random w
				  }
				}
				else
				{
			Console.WriteLine("MPIN Multi Pass");
				  /* Send U=x.ID to server, and recreate secret from token and pin */
			rtn = MPIN.CLIENT_1(date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT);
			if (rtn != 0)
			{
			  Console.WriteLine("FAILURE: CLIENT_1 rtn: " + rtn);
			}

			if (FULL)
			{
			  HCID = MPIN.HASH_ID(CLIENT_ID);
			  MPIN.GET_G1_MULTIPLE(rng,1,R,HCID,Z); // Also Send Z=r.ID to Server, remember random r
			}

				  /* Server calculates H(ID) and H(T|H(ID)) (if time permits enabled), and maps them to points on the curve HID and HTID resp. */
			MPIN.SERVER_1(date,CLIENT_ID,pHID,pHTID);

				  /* Server generates Random number Y and sends it to Client */
			MPIN.RANDOM_GENERATE(rng,Y);

				  if (FULL)
				  {
			  MPIN.GET_G1_MULTIPLE(rng,0,W,prHID,T); // Also send T=w.ID to client, remember random w
				  }

				  /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
			rtn = MPIN.CLIENT_2(X,Y,SEC);
			if (rtn != 0)
			{
			  Console.WriteLine("FAILURE: CLIENT_2 rtn: " + rtn);
			}

				  /* Server Second pass. Inputs hashed client id, random Y, -(x+y)*SEC, xID and xCID and Server secret SST. E and F help kangaroos to find error. */
				  /* If PIN error not required, set E and F = null */

			rtn = MPIN.SERVER_2(date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF);

			if (rtn != 0)
			{
			  Console.WriteLine("FAILURE: SERVER_1 rtn: " + rtn);
			}
				}

		if (rtn == MPIN.BAD_PIN)
		{
		  Console.WriteLine("Server says - Bad Pin. I don't know you. Feck off.\n");
		  if (PINERROR)
		  {
			int err = MPIN.KANGAROO(E,F);
			if (err != 0)
			{
				Console.Write("(Client PIN is out by {0:D})\n",err);
			}
		  }
		  return;
		}
		else
		{
			Console.WriteLine("Server says - PIN is good! You really are " + IDstr);
		}


		if (FULL)
		{
			MPIN.CLIENT_KEY(G1,G2,pin,R,X,T,CK);
			Console.Write("Client Key =  0x");
			printBinary(CK);

			MPIN.SERVER_KEY(Z,SST,W,pxID,pxCID,SK);
			Console.Write("Server Key =  0x");
			printBinary(SK);
		}
	}
}
