/* -------------------------------------------------------------
Signature Generation Process of HFEv- Signature Scheme
loads private key from private_key.txt and generates HFEv- signature for a random hash value
signature and hash value are stored in signature.txt
---------------------------------------------------------------*/

printf "****************************************************** \n";
printf "*** HFEv- Signature Scheme - Signature Generation *** \n";
printf "****************************************************** \n \n";

clear ;

timet := Cputime() ;

load "private_key.txt";

r1 := Floor(Log(D)/Log(q)) ;

Q<X>:= quo < Pol | irrpol>;
Poly<A>:=PolynomialRing(Q);

hash:=Random(hashspace);
printf"Generate Signature for the message %o \n \n", hash;

//S invertieren
_,k,kernel:=IsConsistent(Transpose(MS), hash - cS);

k:=Eltseq(k+Random(kernel));
printf "S^(-1)(hashvalue):= %o \n \n", k;

//central map

B:=Q!0;
for i:=1 to m do
	B:=B+k[i]*X^(i-1);
end for;

printf "B:= %o \n\n", B;

Vinegar:=[];
repeat // --------------------------------------------------------------
//random values for Vinegar variables

	for i:=1 to v do
		Vinegar[i]:=Random(GF);
	end for;

	printf "Vinegar:= %o \n\n", Vinegar;


     // evaluate gamma 
     polA := Q!gamma[1] ;
     ij := 1 ;
	for i:=1 to v do
           ij +:= 1 ;
		polA +:= (Q!gamma[ij]) * Vinegar[i];
	end for;

	for i:=1 to v do
		for j:=i to v do
                ij +:= 1 ;
			polA +:= (Q!gamma[ij]) * Vinegar[i]*Vinegar[j];
		end for;
	end for;


	printf"Evaluate Vinegar maps \n \n";
	//Evaluate Beta B

      ij := 1 ;
	for i:=0 to r1 do
           Beta := Q!beta[ij];   // constant term
           ij +:=1 ;
		for j:=1 to v do
		   Beta +:=  (Q!beta[ij])*Vinegar[j];
              ij +:= 1 ;
		end for;
           printf "B[%o]: %o \n", i, Beta;
           polA +:= Beta * A^(q^i) ;
	end for;


	printf "Gamma: %o \n", polA;
	

     ij := 1 ;
	// Build the central map
	for i:=1 to r1 do
		for j:=0 to i-1 do
              qij := q^i+ q^j;
			if qij le D then
				polA +:=Q!Alpha[ij]*A^(qij);
                      ij := ij + 1 ;
			end if;
		end for;
	end for;
	
	polB:=polA-B;

	fact:= Roots(polB);
      print "fact:",fact;
     tr := #fact gt 0 ;
	if tr then
		AA:= fact[1][1] ;
		printf "Found Solution AA:= %o \n \n", AA;
	else printf "Found no Solution. Choose other values for the Vinegar Variables. \n \n";
		;
	end if; 

until tr ; //-----------------------------------------------------------------------

y:=[];
for i:=1 to m do
	y[i]:=MonomialCoefficient(AA,X^(i-1));
end for;

for i:=1 to v do // append Vinegar Variables
	y:=y cat [Vinegar[i]];
end for;

printf "y:= %o \n\n", y;

// T invertieren
_,signature,kernel:=IsConsistent(Transpose(MT), signspace!(y) - cT);
signature:=Eltseq(signature);

printf"signature := %o \n \n", signspace!signature;
printf "Write signature.txt \n \n";
printf "Time to sign with HFEv- : %o\n",Cputime(timet) ;

SetOutputFile("signature.txt":Overwrite:=true);
printf "hashspace:=VectorSpace(GF,m-a); \n \n";
printf "signspace:=VectorSpace(GF,n); \n \n";
printf "hash:= hashspace!(%o) ; \n \n", Eltseq(hash);
printf "signature:= signspace!(%o); \n \n", Eltseq(signature);
UnsetOutputFile();
