public DsaParameters 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 = (size - 1) / 160;
byte[] w = new byte[size / 8];
BigInteger q = null, p = null, g = null;
int counter = 0;
bool primesFound = false;
while (!primesFound)
{
do
{
random.NextBytes(seed);
sha1.BlockUpdate(seed, 0, seed.Length);
sha1.DoFinal(part1, 0);
Array.Copy(seed, 0, part2, 0, seed.Length);
Add(part2, seed, 1);
sha1.BlockUpdate(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.BlockUpdate(part1, 0, part1.Length);
sha1.DoFinal(part1, 0);
Array.Copy(part1, 0, w, w.Length - (k + 1) * part1.Length, part1.Length);
}
Add(part1, seed, offset + n);
sha1.BlockUpdate(part1, 0, part1.Length);
sha1.DoFinal(part1, 0);
Array.Copy(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.ShiftLeft(1));
p = x.Subtract(c.Subtract(BigInteger.One));
if (p.TestBit(size - 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(size, 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;
}
return new DsaParameters(p, q, g, new DsaValidationParameters(seed, counter));
}