1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage org.bouncycastle.crypto.generators;
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.math.BigInteger;
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.SecureRandom;
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.digests.SHA1Digest;
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.params.DSAParameters;
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.params.DSAValidationParameters;
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * generate suitable parameters for DSA, in line with FIPS 186-2.
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class DSAParametersGenerator
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int             size;
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int             certainty;
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private SecureRandom    random;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static BigInteger ONE = BigInteger.valueOf(1);
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static BigInteger TWO = BigInteger.valueOf(2);
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * initialise the key generator.
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param size size of the key (range 2^512 -> 2^1024 - 64 bit increments)
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param certainty measure of robustness of prime (for FIPS 186-2 compliance this should be at least 80).
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param random random byte source.
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void init(
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int             size,
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int             certainty,
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        SecureRandom    random)
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.size = size;
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.certainty = certainty;
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.random = random;
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * add value to b, returning the result in a. The a value is treated
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * as a BigInteger of length (a.length * 8) bits. The result is
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * modulo 2^a.length in case of overflow.
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void add(
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]  a,
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]  b,
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int     value)
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int     x = (b[b.length - 1] & 0xff) + value;
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        a[b.length - 1] = (byte)x;
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        x >>>= 8;
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = b.length - 2; i >= 0; i--)
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            x += (b[i] & 0xff);
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            a[i] = (byte)x;
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            x >>>= 8;
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * which generates the p and g values from the given parameters,
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * returning the DSAParameters object.
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <p>
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Note: can take a while...
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public DSAParameters generateParameters()
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]          seed = new byte[20];
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]          part1 = new byte[20];
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]          part2 = new byte[20];
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]          u = new byte[20];
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        SHA1Digest      sha1 = new SHA1Digest();
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int             n = (size - 1) / 160;
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]          w = new byte[size / 8];
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        BigInteger      q = null, p = null, g = null;
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int             counter = 0;
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        boolean         primesFound = false;
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        while (!primesFound)
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            do
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                random.nextBytes(seed);
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sha1.update(seed, 0, seed.length);
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sha1.doFinal(part1, 0);
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                System.arraycopy(seed, 0, part2, 0, seed.length);
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                add(part2, seed, 1);
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sha1.update(part2, 0, part2.length);
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sha1.doFinal(part2, 0);
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                for (int i = 0; i != u.length; i++)
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                {
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    u[i] = (byte)(part1[i] ^ part2[i]);
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                u[0] |= (byte)0x80;
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                u[19] |= (byte)0x01;
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                q = new BigInteger(1, u);
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            while (!q.isProbablePrime(certainty));
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            counter = 0;
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int offset = 2;
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            while (counter < 4096)
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                for (int k = 0; k < n; k++)
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                {
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    add(part1, seed, offset + k);
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    sha1.update(part1, 0, part1.length);
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    sha1.doFinal(part1, 0);
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    System.arraycopy(part1, 0, w, w.length - (k + 1) * part1.length, part1.length);
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                add(part1, seed, offset + n);
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sha1.update(part1, 0, part1.length);
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sha1.doFinal(part1, 0);
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                System.arraycopy(part1, part1.length - ((w.length - (n) * part1.length)), w, 0, w.length - n * part1.length);
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                w[0] |= (byte)0x80;
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                BigInteger  x = new BigInteger(1, w);
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                BigInteger  c = x.mod(q.multiply(TWO));
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                p = x.subtract(c.subtract(ONE));
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (p.testBit(size - 1))
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                {
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (p.isProbablePrime(certainty))
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    {
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        primesFound = true;
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                counter += 1;
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                offset += n + 1;
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // calculate the generator g
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        BigInteger  pMinusOneOverQ = p.subtract(ONE).divide(q);
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (;;)
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            BigInteger h = new BigInteger(size, random);
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (h.compareTo(ONE) <= 0 || h.compareTo(p.subtract(ONE)) >= 0)
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                continue;
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            g = h.modPow(pMinusOneOverQ, p);
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (g.compareTo(ONE) <= 0)
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                continue;
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return new DSAParameters(p, q, g, new DSAValidationParameters(seed, counter));
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
179