/*-
 * Copyright (c) 1999,2000 Joao Cabral (jcnc@dhis.org)
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *      DHIS(c)  Dynamic Host Information System Release 4.0
 */


#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<gmp.h>
#include<string.h>



/* qrc_random() - Generates a random integer of n digits
 *		  n may be up to 1024
 */
void qrc_random(mpz_t x,int n) {

	char buff[1024],temp[128];
	static int seed=0;

	if(!seed) { seed++; srandom(time(NULL)); }
	memset(buff,0,256);	
	memset(temp,0,128);	

	do {
		sprintf(temp,"%lu",random());
		strcat(buff,temp);
		
	} while(strlen(buff) < n);
	buff[n]='\0';
	
	mpz_set_str(x,buff,10);
	return;
}
		



/* qrc_genkey() - Generates an integer of 100 digits being congruent 
 * 		  to 3 mod 4
 *
 */

void qrc_genkey(mpz_t k) {
	
	int flag=1;

	do {
	

	mpz_t a,b;

	/* Get a prime number */
	do qrc_random(k,100); while(!mpz_probab_prime_p(k,5));

	/* Now see if it is congruent to 3 mod 4 */
	mpz_init(a);mpz_init(b);
	mpz_set_ui(a,4);
	mpz_mod(b,k,a);
	mpz_set_ui(a,3);
	if(!mpz_cmp(a,b)) flag=0;
	mpz_clear(a);
	mpz_clear(b);

	} while(flag);

}



void show_key(mpz_t key,int n,char *s) {
	
	unsigned char buff[1024];
	unsigned char chunk[128];
	unsigned char *cp;
	int i;
	
	mpz_get_str(buff,10,key);
	
	cp=buff;
	for(i=0;i<n;i++) {
		memcpy(chunk,cp,50);
		chunk[50]='\0';
		printf("\t%s\t\t%s\n",s,chunk);
		cp+=50;
	}
}

int main() {

	mpz_t p,q,n;
	
	mpz_init(p);
	mpz_init(q);
	mpz_init(n);

	qrc_genkey(p);
	show_key(p,2,"authp");
	qrc_genkey(q);
	show_key(q,2,"authq");
	mpz_mul(n,p,q);
	show_key(n,4,"authn");
	mpz_clear(p);
	mpz_clear(q);
	mpz_clear(n);
	return(0);
}
