package de.paillier;

import java.math.BigInteger;
import java.security.SecureRandom;

public class KeyPairBuilder {
	private int bits = 1024;
	private int certainty = 64;
	
	public void setBits(int bits) {
		this.bits = bits;
	}

	public KeyPair generateKeyPair() {
		SecureRandom sRandom = new SecureRandom();
		BigInteger p = new BigInteger(bits / 2, certainty, sRandom);
		BigInteger q = new BigInteger(bits / 2, certainty, sRandom);
		
		BigInteger n = p.multiply(q);
		BigInteger nSquared = n.multiply(n);
		
		BigInteger pMinusOne = p.subtract(BigInteger.ONE);
		BigInteger qMinusOne = q.subtract(BigInteger.ONE);
		BigInteger lambda  = this.lcm(pMinusOne, qMinusOne);
		
		BigInteger g = BigInteger.valueOf(2);
		BigInteger helper; 
		do {
			g = new BigInteger(bits, sRandom);
			helper = calculateL(g.modPow(lambda, nSquared), n);

		} while (!helper.gcd(n).equals(BigInteger.ONE));
		
		PublicKey publicKey = new PublicKey(n, nSquared, g, bits);
		PrivateKey privateKey = new PrivateKey(lambda, helper.modInverse(n));
		
		KeyPair result = new KeyPair(privateKey, publicKey);
		
		return result;
	}
	
	// TODO separate this somewhere
	private BigInteger calculateL(BigInteger u, BigInteger n) {
		BigInteger result = u.subtract(BigInteger.ONE);
		result = result.divide(n);
		return result;
	}
	
	// TODO add to own BigInteger extended class
	private BigInteger lcm(BigInteger a, BigInteger b)
	{
		BigInteger result;
		BigInteger gcd = a.gcd(b);
		
		result = a.abs().divide(gcd);
		result = result.multiply(b.abs());
		
		return result;
	}
}

@@ -179,12 +179,22 @@
 lic 
-void
+KeyPairBuilder
  set
@@ -230,16 +230,134 @@
 = bits;%0A
+%09%09return this;%0A%09%7D%0A%09%0A%09public KeyPairBuilder setCertainty(int certainty) %7B%0A%09%09this.certainty = certainty;%0A%09%09return this;%0A
 %09%7D%0A%0A%09pub
@@ -862,16 +862,19 @@
 elper; %0A
+%09%09%0A
 %09%09do %7B%0A%09

Add return statements to KeyPairBuilder's setters