//****************************************************************************************************************************
//****************************************************************************************************************************
//**Autor: 					Mike Widmer																						**
//**Fertigstellung:																											**
//**Version:																												**
//**Zweck: 					Kodieren von Wörtern in Zahlen und Dekodieren von Zahlen in Buchstaben nach dem RSA				**
//**Benötigte Dateien: 		InOut.java																						**
//****************************************************************************************************************************
//****************************************************************************************************************************


class RSAEnDecoder
{
	public static void main (String[] args)
	{
		int Wahl;
		int p,q,n,e,d, grenze;
		int[] d1;
		char[] a;
		int[] Code;
		int Verschiebung;
		int counter=0;
		char[] Code2;
		boolean test;
		String Text;
		char[] text;
		do
		{
			System.out.println("Bitte waehlen Sie 1 um zu codieren und 2 um zu dekodieren");
			Wahl=InOut.getInt();
			if(Wahl!=1&&Wahl!=2)
			{
				System.out.println("Neee Sie muessen zwischen 1 und 2 waehlen und nix anderes");
			}
		}while(Wahl!=1&&Wahl!=2);
		if(Wahl==1)
		{
			System.out.println("Bitte geben Sie den zu kodierenden Text in KLEINBUCHSTABEN ein");
			Text=InOut.getLine();
			Text=InOut.getLine();
			System.out.println("Waehlen Sie wo der Zahlenbereich fuer die Buchstaben anfaengt.");
			System.out.println("Fuer ASCII Kleinbuchstaben waehle 97 fuer Grossbuchstaben 65.");
			Verschiebung=InOut.getInt();
			Verschiebung=97-Verschiebung;
			a=Text.toCharArray();
			Code=new int[a.length];
			for(int i=0;i<a.length;i++)
			{
				if((int)a[i]==32)
				{
					Code[i]= (int)a[i];
				}
				else
				{
					Code[i]= (int)a[i]-Verschiebung;
				}
			}
			do
			{
				System.out.println("Bitte geben Sie eine erste Primzahl ein");
				System.out.print("p= ");
				p=InOut.getInt();
				test=Testprim(p);
				if(test==false)
				{
					System.out.println("SIE MUESSEN EINE PRIMZAHL EINGEBEN, DIES WAR KEINE PRIMZAHL");
					System.out.println("Geben Sie diesmal eine Primzahl ein");
				}
			}while(test==false);
			do
			{
				System.out.println("Bitte geben Sie eine zweite Primzahl ein");
				System.out.print("q= ");
				q=InOut.getInt();
				test=Testprim(q);
				if(test==false)
				{
					System.out.println("SIE MUESSEN EINE PRIMZAHL EINGEBEN, DIES WAR KEINE PRIMZAHL");
					System.out.println("Geben Sie diesmal eine Primzahl ein");
				}
			}while(test==false);
			n=p*q;
			System.out.println("Der erste Teil des Public Key lautet:");
			System.out.println("n="+n);
			System.out.println("Bitte geben Sie eine der folgenden Zahlen als zweiten Teil des Public Keys ein");
			grenze=(p-1)*(q-1);
			int z, length=0;
			for(int i=2;i<n;i++)
			{
				z=ggt(i,grenze);
				if(z==1)
				{
					length++;
				}
			}
			d1=new int[length];
			relprim(d1,grenze,n);
			for(int i=0;i<d1.length;i++)
			{
			System.out.print(d1[i]+"  ");
			}
			System.out.println();
			do
			{
				test=false;
				System.out.print("e= ");
				e=InOut.getInt();
				for(int i=0;i<d1.length;i++)
				{
					if(e==d1[i])
					{
						test=true;
					}
				}
			}while(test==false);
			System.out.println("Der Privat Key lautet");
			d=ModInv(e,grenze);
			System.out.println("d= "+d);
			Kodierung(Code,e,n);
			System.out.println("Ihr Text ist wurde kodiert:");
			System.out.println();
			for(int i=0; i<Code.length;i++)
			{
				System.out.print(Code[i]+"  ");
			}
			System.out.println();
			System.out.println();
		}

		else
		{
			System.out.println("Bitte geben Sie den Code im Zehnersystem");
			System.out.println("mit einem Leerschlag zwischen den Zahlen ein");
			Text=InOut.getLine();
			Text=InOut.getLine();
			Code2=Text.toCharArray();
			for(int i=0;i<Code2.length;i++)
			{
				if((int)Code2[i]==32)
				{
					counter++;
				}
			}
			counter=counter+1;
			Code=new int[counter];
			int j=0;
			for(int i=0;i<Code2.length;i++)
			{
				if((int)Code2[i]!=32)
				{
					Code[j]=Code[j]+((int)Code2[i]-48);
				}
				if(i+1!=Code2.length)
				{
					if((int)Code2[i+1]==32)
					{
						j++;
					}
					else
					{
						Code[j]=Code[j]*10;
					}
				}

			}
			System.out.println("Falls Sie einen der Werte nicht haben geben Sie 0 an");
			System.out.println("Geben Sie die erste Primzahl p an");
			p=InOut.getInt();
			System.out.println("Geben Sie die zweite Primzahl q an");
			q=InOut.getInt();
			if(p==0||q==0)
			{
				System.out.println("Geben Sie den Public Key n an");
				n=InOut.getInt();
			}
			else
			{
				System.out.println("Der Public Key n lautet:");
				n=p*q;
				grenze=(p-1)*(q-1);
				System.out.println("n= "+n);
			}
			System.out.println("Geben Sie den Public Key e an");
			e=InOut.getInt();
			if(p==0||q==0||e==0)
			{
				System.out.println("Bitte geben Sie den Privat Key d an");
				d=InOut.getInt();
			}
			else
			{

				System.out.println("Der Privat Key d lautet:");
				grenze=(p-1)*(q-1);
				d=ModInv(e,grenze);
				System.out.println("d= "+d);
			}

			System.out.println("Waehlen Sie wo der Zahlenbereich fuer die Buchstaben anfaengt.");
			System.out.println("Fuer ASCII Kleinbuchstaben waehle 97 fuer Grossbuchstaben 65.");
			Verschiebung=InOut.getInt();
			Verschiebung=97-Verschiebung;
			text=new char[Code.length];
			for(int i=0;i<Code.length;i++)
			{
				text[i]=(char)((long)Math.pow(Code[i],d)%n+Verschiebung);
			}
			System.out.println("Der Text lautet:");
			System.out.println();
			for(int i=0;i<text.length;i++)
			{
				System.out.print(text[i]);
			}
			System.out.println();
			System.out.println();
		}


	}

//------------------------------------------------------------

	public static boolean Testprim(int x)
	{
		boolean test=true;
		for(int i=2;i<x;i++)
		{
			if(x%i==0)
			{
				test=false;
			}
		}
		return test;
	}

//---------------------------------------------------------------

	public static void relprim (int []d1,int grenze,int n)
	{
		int z;
		int j=0;
		for(int i=2;i<n;i++)
		{
			z=ggt(i,grenze);
			if(z==1)
			{
				d1[j]=i;
				j++;
			}
		}
	}

//--------------------------------------------------------------

	public static int ggt(int i, int y)
	{
		while(i>0&&y>0)
		{
			if(y>i)
			{
				i=y+i;
				y=i-y;
				i=i-y;
			}
			i=i-y;
		}
		return i+y;
	}

//-------------------------------------------------------------------

	public static int ModInv(int e, int grenze)
	{
		int d=0;
		for(int i=1; d==0;i++)
		{
			if((grenze*i+1)%e==0)
			{
				d=(grenze*i+1)/e;
			}
		}
		return d;
	}

//---------------------------------------------------------------------

	public static void Kodierung(int[] Code, int e, int n)
	{
		for(int i=0;i<Code.length;i++)
		{
			Code[i]=(int)(Math.pow(Code[i],e)%n);
		}
	}

//--------------------------------------------------------------------




}
