1package org.bouncycastle.crypto.generators;
2
3import java.math.BigInteger;
4import java.security.SecureRandom;
5
6import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
7import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
8import org.bouncycastle.crypto.KeyGenerationParameters;
9import org.bouncycastle.crypto.params.ECDomainParameters;
10import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
11import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
12import org.bouncycastle.crypto.params.ECPublicKeyParameters;
13import org.bouncycastle.math.ec.ECConstants;
14import org.bouncycastle.math.ec.ECMultiplier;
15import org.bouncycastle.math.ec.ECPoint;
16import org.bouncycastle.math.ec.FixedPointCombMultiplier;
17import org.bouncycastle.math.ec.WNafUtil;
18
19public class ECKeyPairGenerator
20    implements AsymmetricCipherKeyPairGenerator, ECConstants
21{
22    ECDomainParameters  params;
23    SecureRandom        random;
24
25    public void init(
26        KeyGenerationParameters param)
27    {
28        ECKeyGenerationParameters  ecP = (ECKeyGenerationParameters)param;
29
30        this.random = ecP.getRandom();
31        this.params = ecP.getDomainParameters();
32
33        if (this.random == null)
34        {
35            this.random = new SecureRandom();
36        }
37    }
38
39    /**
40     * Given the domain parameters this routine generates an EC key
41     * pair in accordance with X9.62 section 5.2.1 pages 26, 27.
42     */
43    public AsymmetricCipherKeyPair generateKeyPair()
44    {
45        BigInteger n = params.getN();
46        int nBitLength = n.bitLength();
47        int minWeight = nBitLength >>> 2;
48
49        BigInteger d;
50        for (;;)
51        {
52            d = new BigInteger(nBitLength, random);
53
54            if (d.compareTo(TWO) < 0  || (d.compareTo(n) >= 0))
55            {
56                continue;
57            }
58
59            if (WNafUtil.getNafWeight(d) < minWeight)
60            {
61                continue;
62            }
63
64            break;
65        }
66
67        ECPoint Q = createBasePointMultiplier().multiply(params.getG(), d);
68
69        return new AsymmetricCipherKeyPair(
70            new ECPublicKeyParameters(Q, params),
71            new ECPrivateKeyParameters(d, params));
72    }
73
74    protected ECMultiplier createBasePointMultiplier()
75    {
76        return new FixedPointCombMultiplier();
77    }
78}
79