1b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampackage org.bouncycastle.crypto.generators;
2b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
3b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.AsymmetricCipherKeyPair;
4b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
5b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.KeyGenerationParameters;
6b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.params.DSAKeyGenerationParameters;
7b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.params.DSAParameters;
8b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
9b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.params.DSAPublicKeyParameters;
10c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.util.BigIntegers;
11c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
12c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport java.math.BigInteger;
13c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport java.security.SecureRandom;
14b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
15b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam/**
16b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * a DSA key pair generator.
17b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam *
18b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * This generates DSA keys in line with the method described
19c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom * in <i>FIPS 186-3 B.1 FFC Key Pair Generation</i>.
20b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */
21b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampublic class DSAKeyPairGenerator
22b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    implements AsymmetricCipherKeyPairGenerator
23b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{
24c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private static final BigInteger ONE = BigInteger.valueOf(1);
25b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
26b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private DSAKeyGenerationParameters param;
27b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
28b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public void init(
29b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        KeyGenerationParameters param)
30b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
31b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        this.param = (DSAKeyGenerationParameters)param;
32b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
33b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
34b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public AsymmetricCipherKeyPair generateKeyPair()
35b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
36c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        DSAParameters dsaParams = param.getParameters();
37b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
38c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        BigInteger x = generatePrivateKey(dsaParams.getQ(), param.getRandom());
39c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        BigInteger y = calculatePublicKey(dsaParams.getP(), dsaParams.getG(), x);
40b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
41c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        return new AsymmetricCipherKeyPair(
42c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            new DSAPublicKeyParameters(y, dsaParams),
43c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            new DSAPrivateKeyParameters(x, dsaParams));
44c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
45b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
46c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private static BigInteger generatePrivateKey(BigInteger q, SecureRandom random)
47c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
48c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        // TODO Prefer this method? (change test cases that used fixed random)
49c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        // B.1.1 Key Pair Generation Using Extra Random Bits
50c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom//        BigInteger c = new BigInteger(q.bitLength() + 64, random);
51c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom//        return c.mod(q.subtract(ONE)).add(ONE);
52b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
53c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        // B.1.2 Key Pair Generation by Testing Candidates
54c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        return BigIntegers.createRandomInRange(ONE, q.subtract(ONE), random);
55c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
56c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
57c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private static BigInteger calculatePublicKey(BigInteger p, BigInteger g, BigInteger x)
58c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
59c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        return g.modPow(x, p);
60b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
61b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam}
62