116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giropackage org.bouncycastle.jcajce.provider.asymmetric.dh;
216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport java.security.InvalidAlgorithmParameterException;
416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport java.security.KeyPair;
516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport java.security.SecureRandom;
616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport java.security.spec.AlgorithmParameterSpec;
716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport java.util.Hashtable;
816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport javax.crypto.spec.DHParameterSpec;
1016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
1116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.AsymmetricCipherKeyPair;
1216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.generators.DHBasicKeyPairGenerator;
1316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.generators.DHParametersGenerator;
1416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.params.DHKeyGenerationParameters;
1516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.params.DHParameters;
1616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.params.DHPrivateKeyParameters;
1716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.params.DHPublicKeyParameters;
18823ad5bac1616941ae772fe6b69560b49c89d7b3Adam Vartanianimport org.bouncycastle.jcajce.provider.asymmetric.util.PrimeCertaintyCalculator;
1916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.jce.provider.BouncyCastleProvider;
2016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.util.Integers;
2116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
2216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giropublic class KeyPairGeneratorSpi
2316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    extends java.security.KeyPairGenerator
2416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro{
2516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private static Hashtable params = new Hashtable();
2616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private static Object    lock = new Object();
2716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
2816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    DHKeyGenerationParameters param;
2916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    DHBasicKeyPairGenerator engine = new DHBasicKeyPairGenerator();
30823ad5bac1616941ae772fe6b69560b49c89d7b3Adam Vartanian    int strength = 2048;
3116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    SecureRandom random = new SecureRandom();
3216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    boolean initialised = false;
3316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
3416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public KeyPairGeneratorSpi()
3516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
3616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        super("DH");
3716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
3816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
3916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public void initialize(
4016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int strength,
4116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        SecureRandom random)
4216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
4316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        this.strength = strength;
4416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        this.random = random;
454caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro        this.initialised = false;
4616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
4716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
4816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public void initialize(
4916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        AlgorithmParameterSpec params,
5016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        SecureRandom random)
5116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        throws InvalidAlgorithmParameterException
5216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
5316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        if (!(params instanceof DHParameterSpec))
5416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
5516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            throw new InvalidAlgorithmParameterException("parameter object not a DHParameterSpec");
5616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
5716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        DHParameterSpec dhParams = (DHParameterSpec)params;
5816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
5916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        param = new DHKeyGenerationParameters(random, new DHParameters(dhParams.getP(), dhParams.getG(), null, dhParams.getL()));
6016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
6116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        engine.init(param);
6216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        initialised = true;
6316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
6416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
6516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public KeyPair generateKeyPair()
6616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
6716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        if (!initialised)
6816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
6916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            Integer paramStrength = Integers.valueOf(strength);
7016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
7116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            if (params.containsKey(paramStrength))
7216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
7316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                param = (DHKeyGenerationParameters)params.get(paramStrength);
7416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
7516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            else
7616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
7716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                DHParameterSpec dhParams = BouncyCastleProvider.CONFIGURATION.getDHDefaultParameters(strength);
7816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
7916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                if (dhParams != null)
8016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                {
8116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                    param = new DHKeyGenerationParameters(random, new DHParameters(dhParams.getP(), dhParams.getG(), null, dhParams.getL()));
8216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                }
8316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                else
8416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                {
8516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                    synchronized (lock)
8616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                    {
8716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                        // we do the check again in case we were blocked by a generator for
8816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                        // our key size.
8916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                        if (params.containsKey(paramStrength))
9016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                        {
9116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                            param = (DHKeyGenerationParameters)params.get(paramStrength);
9216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                        }
9316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                        else
9416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                        {
9516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
9616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                            DHParametersGenerator pGen = new DHParametersGenerator();
9716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
98823ad5bac1616941ae772fe6b69560b49c89d7b3Adam Vartanian                            pGen.init(strength, PrimeCertaintyCalculator.getDefaultCertainty(strength), random);
9916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
10016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                            param = new DHKeyGenerationParameters(random, pGen.generateParameters());
10116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
10216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                            params.put(paramStrength, param);
10316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                        }
10416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                    }
10516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                }
10616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
10716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
10816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            engine.init(param);
10916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
11016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            initialised = true;
11116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
11216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
11316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        AsymmetricCipherKeyPair pair = engine.generateKeyPair();
11416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        DHPublicKeyParameters pub = (DHPublicKeyParameters)pair.getPublic();
11516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        DHPrivateKeyParameters priv = (DHPrivateKeyParameters)pair.getPrivate();
11616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
1174caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro        return new KeyPair(new BCDHPublicKey(pub), new BCDHPrivateKey(priv));
11816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
11916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro}
120