package publickey;
import ssh.v2.BigInteger;
import ssh.v2.SHA1Digest;
public class DSAParamsGenerator {
private int strength = 1024;
private int certainty = 20;
private SecureRandom random = new SecureRandom();
private BigInteger p, q, g;
public static void main(String[] argv) {
DSAParamsGenerator gen = new DSAParamsGenerator();
gen.generateParameters();
System.out.println("P=" + gen.p.toString(16));
System.out.println("Q=" + gen.q.toString(16));
System.out.println("G=" + gen.g.toString(16));
}
/**
* add value to b, returning the result in a. The a value is treated
* as a BigInteger of length (a.length * 8) bits. The result is
* modulo 2^a.length in case of overflow.
*/
private void add(
byte[] a,
byte[] b,
int value)
{
int x = (b[b.length - 1] & 0xff) + value;
a[b.length - 1] = (byte)x;
x >>>= 8;
for (int i = b.length - 2; i >= 0; i--)
{
x += (b[i] & 0xff);
a[i] = (byte)x;
x >>>= 8;
}
}
/**
* which generates the p and g values from the given parameters,
* returning the DSAParameters object.
* <p>
* Note: can take a while...
*/
public void generateParameters()
{
byte[] seed = new byte[20];
byte[] part1 = new byte[20];
byte[] part2 = new byte[20];
byte[] u = new byte[20];
SHA1Digest sha1 = new SHA1Digest();
int n = (strength - 1) / 160;
byte[] w = new byte[strength / 8];
BigInteger q = null, p = null, g = null;
int counter = 0;
boolean primesFound = false;
while (!primesFound)
{
do
{
random.nextBytes(seed);
sha1.update(seed, 0, seed.length);
sha1.doFinal(part1, 0);
System.arraycopy(seed, 0, part2, 0, seed.length);
add(part2, seed, 1);
sha1.update(part2, 0, part2.length);
sha1.doFinal(part2, 0);
for (int i = 0; i != u.length; i++)
{
u[i] = (byte)(part1[i] ^ part2[i]);
}
u[0] |= (byte)0x80;
u[19] |= (byte)0x01;
q = new BigInteger(1, u);
}
while (!q.isProbablePrime(certainty));
counter = 0;
int offset = 2;
while (counter < 4096)
{
for (int k = 0; k < n; k++)
{
add(part1, seed, offset + k);
sha1.update(part1, 0, part1.length);
sha1.doFinal(part1, 0);
System.arraycopy(part1, 0, w, w.length - (k + 1) * part1.length, part1.length);
}
add(part1, seed, offset + n);
sha1.update(part1, 0, part1.length);
sha1.doFinal(part1, 0);
System.arraycopy(part1, part1.length - ((w.length - (n) * part1.length)), w, 0, w.length - n * part1.length);
w[0] |= (byte)0x80;
BigInteger x = new BigInteger(1, w);
BigInteger c = x.mod(q.multiply(BigInteger.TWO));
p = x.subtract(c.subtract(BigInteger.ONE));
if (p.testBit(strength - 1))
{
if (p.isProbablePrime(certainty))
{
primesFound = true;
break;
}
}
counter += 1;
offset += n + 1;
}
}
//
// calculate the generator g
//
BigInteger pMinusOneOverQ = p.subtract(BigInteger.ONE).divide(q);
for (;;)
{
BigInteger h = new BigInteger(strength, random);
if (h.compareTo(BigInteger.ONE) <= 0 || h.compareTo(p.subtract(BigInteger.ONE)) >= 0)
{
continue;
}
g = h.modPow(pMinusOneOverQ, p);
if (g.compareTo(BigInteger.ONE) <= 0)
{
continue;
}
break;
}
this.p = p;
this.q = q;
this.g = g;
}
}