1b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampackage org.bouncycastle.crypto.generators;
2b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
3b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.math.BigInteger;
4b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.SecureRandom;
5b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
6c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.crypto.params.DHParameters;
7d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport org.bouncycastle.math.ec.WNafUtil;
8c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.util.BigIntegers;
9c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
10b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamclass DHKeyGeneratorHelper
11b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{
12b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    static final DHKeyGeneratorHelper INSTANCE = new DHKeyGeneratorHelper();
13c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
14c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private static final BigInteger ONE = BigInteger.valueOf(1);
15c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private static final BigInteger TWO = BigInteger.valueOf(2);
16c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
17b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private DHKeyGeneratorHelper()
18b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
19b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
20c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
21c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    BigInteger calculatePrivate(DHParameters dhParams, SecureRandom random)
22b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
23c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        int limit = dhParams.getL();
24c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
25c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        if (limit != 0)
26b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
27d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            int minWeight = limit >>> 2;
28d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            for (;;)
29d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            {
30d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                BigInteger x = new BigInteger(limit, random).setBit(limit - 1);
31d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                if (WNafUtil.getNafWeight(x) >= minWeight)
32d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                {
33d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                    return x;
34d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                }
35d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            }
36b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
37b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
38c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        BigInteger min = TWO;
39c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        int m = dhParams.getM();
40c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        if (m != 0)
41b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
42c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            min = ONE.shiftLeft(m - 1);
43b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
44c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
45c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        BigInteger q = dhParams.getQ();
46d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        if (q == null)
47b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
48d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            q = dhParams.getP();
49b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
50d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        BigInteger max = q.subtract(TWO);
51c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
52d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        int minWeight = max.bitLength() >>> 2;
53d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        for (;;)
54d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        {
55d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            BigInteger x = BigIntegers.createRandomInRange(min, max, random);
56d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            if (WNafUtil.getNafWeight(x) >= minWeight)
57d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            {
58d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                return x;
59d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            }
60d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        }
61b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
62c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
63c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    BigInteger calculatePublic(DHParameters dhParams, BigInteger x)
64b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
65c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        return dhParams.getG().modPow(x, dhParams.getP());
66b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
67b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam}
68