Example #1
0
        private DSA_Secret_Key GenerateParams(int keyLength)
        {
            byte[] seed = new byte[20];
            byte[] part1 = new byte[20];
            byte[] part2 = new byte[20];
            byte[] u = new byte[20];
            RandomNumberGenerator rng = RandomNumberGenerator.Create();

            BigInteger p = new BigInteger();	    // prime
            BigInteger q = new BigInteger();	    // group order
            BigInteger g;	    // group generator
            DSA_Secret_Key dskKey = new DSA_Secret_Key();

            SHA1 sha = SHA1.Create();

            int n = (keyLength - 1) / 160;
            byte[] w = new byte [keyLength / 8];
            bool primesFound = false;

            while (!primesFound) {
                do {
                    rng.GetBytes(seed);
                    part1 = sha.ComputeHash(seed);
                    Array.Copy(seed, 0, part2, 0, seed.Length);

                    add(part2, seed, 1);

                    part2 = sha.ComputeHash(part2);

                    for (int i = 0; i != u.Length; i++)
                        u[i] = (byte)(part1[i] ^ part2[i]);

                    // first bit must be set (to respect key length)
                    u[0] |= (byte)0x80;
                    // last bit must be set (prime are all odds - except 2)
                    u[19] |= (byte)0x01;

                    q = new BigInteger(u);
                } while (!q.isProbablePrime());

                int counter = 0;
                int offset = 2;
                while (counter < 4096) {
                    for (int k = 0; k < n; k++) {
                        add(part1, seed, offset + k);
                        part1 = sha.ComputeHash(part1);
                        Array.Copy(part1, 0, w, w.Length - (k + 1) * part1.Length, part1.Length);
                    }

                    add(part1, seed, offset + n);
                    part1 = sha.ComputeHash(part1);
                    Array.Copy(part1, part1.Length - ((w.Length - (n) * part1.Length)), w, 0, w.Length - n * part1.Length);

                    w[0] |= (byte)0x80;
                    BigInteger xx = new BigInteger (w);

                    BigInteger c = xx % (q * 2);

                    p = xx - (c - 1);

                    if (p.testBit((uint)(keyLength - 1))) {
                        if (p.isProbablePrime()) {
                            primesFound = true;
                            break;
                        }
                    }

                    counter += 1;
                    offset += n + 1;
                }

            }

            // calculate the generator g
            BigInteger pMinusOneOverQ = (p - 1) / q;
            for (;;) {
                BigInteger h = new BigInteger();
                h = BigInteger.genRandom(keyLength);
                if ((h <= 1) || (h >= (p - 1)))
                    continue;

                g = h.modPow(pMinusOneOverQ, p);
                if (g <= 1)
                    continue;
                break;
            }

            dskKey.p = p;
            dskKey.q = q;
            dskKey.g = g;

            return dskKey;
        }