1package org.bouncycastle.jcajce.provider.asymmetric.dh;
2
3import java.security.InvalidAlgorithmParameterException;
4import java.security.KeyPair;
5import java.security.SecureRandom;
6import java.security.spec.AlgorithmParameterSpec;
7import java.util.Hashtable;
8
9import javax.crypto.spec.DHParameterSpec;
10
11import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
12import org.bouncycastle.crypto.generators.DHBasicKeyPairGenerator;
13import org.bouncycastle.crypto.generators.DHParametersGenerator;
14import org.bouncycastle.crypto.params.DHKeyGenerationParameters;
15import org.bouncycastle.crypto.params.DHParameters;
16import org.bouncycastle.crypto.params.DHPrivateKeyParameters;
17import org.bouncycastle.crypto.params.DHPublicKeyParameters;
18import org.bouncycastle.jce.provider.BouncyCastleProvider;
19import org.bouncycastle.util.Integers;
20
21public class KeyPairGeneratorSpi
22    extends java.security.KeyPairGenerator
23{
24    private static Hashtable params = new Hashtable();
25    private static Object    lock = new Object();
26
27    DHKeyGenerationParameters param;
28    DHBasicKeyPairGenerator engine = new DHBasicKeyPairGenerator();
29    int strength = 1024;
30    int certainty = 20;
31    SecureRandom random = new SecureRandom();
32    boolean initialised = false;
33
34    public KeyPairGeneratorSpi()
35    {
36        super("DH");
37    }
38
39    public void initialize(
40        int strength,
41        SecureRandom random)
42    {
43        this.strength = strength;
44        this.random = random;
45    }
46
47    public void initialize(
48        AlgorithmParameterSpec params,
49        SecureRandom random)
50        throws InvalidAlgorithmParameterException
51    {
52        if (!(params instanceof DHParameterSpec))
53        {
54            throw new InvalidAlgorithmParameterException("parameter object not a DHParameterSpec");
55        }
56        DHParameterSpec dhParams = (DHParameterSpec)params;
57
58        param = new DHKeyGenerationParameters(random, new DHParameters(dhParams.getP(), dhParams.getG(), null, dhParams.getL()));
59
60        engine.init(param);
61        initialised = true;
62    }
63
64    public KeyPair generateKeyPair()
65    {
66        if (!initialised)
67        {
68            Integer paramStrength = Integers.valueOf(strength);
69
70            if (params.containsKey(paramStrength))
71            {
72                param = (DHKeyGenerationParameters)params.get(paramStrength);
73            }
74            else
75            {
76                DHParameterSpec dhParams = BouncyCastleProvider.CONFIGURATION.getDHDefaultParameters(strength);
77
78                if (dhParams != null)
79                {
80                    param = new DHKeyGenerationParameters(random, new DHParameters(dhParams.getP(), dhParams.getG(), null, dhParams.getL()));
81                }
82                else
83                {
84                    synchronized (lock)
85                    {
86                        // we do the check again in case we were blocked by a generator for
87                        // our key size.
88                        if (params.containsKey(paramStrength))
89                        {
90                            param = (DHKeyGenerationParameters)params.get(paramStrength);
91                        }
92                        else
93                        {
94
95                            DHParametersGenerator pGen = new DHParametersGenerator();
96
97                            pGen.init(strength, certainty, random);
98
99                            param = new DHKeyGenerationParameters(random, pGen.generateParameters());
100
101                            params.put(paramStrength, param);
102                        }
103                    }
104                }
105            }
106
107            engine.init(param);
108
109            initialised = true;
110        }
111
112        AsymmetricCipherKeyPair pair = engine.generateKeyPair();
113        DHPublicKeyParameters pub = (DHPublicKeyParameters)pair.getPublic();
114        DHPrivateKeyParameters priv = (DHPrivateKeyParameters)pair.getPrivate();
115
116        return new KeyPair(new BCDHPublicKey(pub),
117            new BCDHPrivateKey(priv));
118    }
119}
120