1package org.bouncycastle.jcajce.provider.asymmetric.ec; 2 3import java.math.BigInteger; 4import java.security.InvalidAlgorithmParameterException; 5import java.security.InvalidParameterException; 6import java.security.KeyPair; 7import java.security.SecureRandom; 8import java.security.spec.AlgorithmParameterSpec; 9import java.security.spec.ECGenParameterSpec; 10import java.util.Hashtable; 11 12import org.bouncycastle.asn1.ASN1ObjectIdentifier; 13import org.bouncycastle.asn1.x9.ECNamedCurveTable; 14import org.bouncycastle.asn1.x9.X9ECParameters; 15import org.bouncycastle.crypto.AsymmetricCipherKeyPair; 16import org.bouncycastle.crypto.generators.ECKeyPairGenerator; 17import org.bouncycastle.crypto.params.ECDomainParameters; 18import org.bouncycastle.crypto.params.ECKeyGenerationParameters; 19import org.bouncycastle.crypto.params.ECPrivateKeyParameters; 20import org.bouncycastle.crypto.params.ECPublicKeyParameters; 21import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util; 22import org.bouncycastle.jcajce.provider.config.ProviderConfiguration; 23import org.bouncycastle.jce.provider.BouncyCastleProvider; 24import org.bouncycastle.jce.spec.ECNamedCurveGenParameterSpec; 25import org.bouncycastle.jce.spec.ECNamedCurveSpec; 26import org.bouncycastle.jce.spec.ECParameterSpec; 27import org.bouncycastle.math.ec.ECCurve; 28import org.bouncycastle.math.ec.ECPoint; 29import org.bouncycastle.util.Integers; 30 31public abstract class KeyPairGeneratorSpi 32 extends java.security.KeyPairGenerator 33{ 34 public KeyPairGeneratorSpi(String algorithmName) 35 { 36 super(algorithmName); 37 } 38 39 public static class EC 40 extends KeyPairGeneratorSpi 41 { 42 ECKeyGenerationParameters param; 43 ECKeyPairGenerator engine = new ECKeyPairGenerator(); 44 Object ecParams = null; 45 int strength = 239; 46 int certainty = 50; 47 SecureRandom random = new SecureRandom(); 48 boolean initialised = false; 49 String algorithm; 50 ProviderConfiguration configuration; 51 52 static private Hashtable ecParameters; 53 54 static { 55 ecParameters = new Hashtable(); 56 57 ecParameters.put(Integers.valueOf(192), new ECGenParameterSpec("prime192v1")); // a.k.a P-192 58 ecParameters.put(Integers.valueOf(239), new ECGenParameterSpec("prime239v1")); 59 ecParameters.put(Integers.valueOf(256), new ECGenParameterSpec("prime256v1")); // a.k.a P-256 60 61 ecParameters.put(Integers.valueOf(224), new ECGenParameterSpec("P-224")); 62 ecParameters.put(Integers.valueOf(384), new ECGenParameterSpec("P-384")); 63 ecParameters.put(Integers.valueOf(521), new ECGenParameterSpec("P-521")); 64 } 65 66 public EC() 67 { 68 super("EC"); 69 this.algorithm = "EC"; 70 this.configuration = BouncyCastleProvider.CONFIGURATION; 71 } 72 73 public EC( 74 String algorithm, 75 ProviderConfiguration configuration) 76 { 77 super(algorithm); 78 this.algorithm = algorithm; 79 this.configuration = configuration; 80 } 81 82 public void initialize( 83 int strength, 84 SecureRandom random) 85 { 86 this.strength = strength; 87 // BEGIN android-added 88 if (random != null) { 89 // END android-added 90 this.random = random; 91 // BEGIN android-added 92 } 93 // END android-added 94 ECGenParameterSpec ecParams = (ECGenParameterSpec)ecParameters.get(Integers.valueOf(strength)); 95 96 if (ecParams != null) 97 { 98 try 99 { 100 initialize(ecParams, random); 101 } 102 catch (InvalidAlgorithmParameterException e) 103 { 104 throw new InvalidParameterException("key size not configurable."); 105 } 106 } 107 else 108 { 109 throw new InvalidParameterException("unknown key size."); 110 } 111 } 112 113 public void initialize( 114 AlgorithmParameterSpec params, 115 SecureRandom random) 116 throws InvalidAlgorithmParameterException 117 { 118 // BEGIN android-added 119 if (random == null) { 120 random = this.random; 121 } 122 // END android-added 123 if (params instanceof ECParameterSpec) 124 { 125 ECParameterSpec p = (ECParameterSpec)params; 126 this.ecParams = params; 127 128 param = new ECKeyGenerationParameters(new ECDomainParameters(p.getCurve(), p.getG(), p.getN()), random); 129 130 engine.init(param); 131 initialised = true; 132 } 133 else if (params instanceof java.security.spec.ECParameterSpec) 134 { 135 java.security.spec.ECParameterSpec p = (java.security.spec.ECParameterSpec)params; 136 this.ecParams = params; 137 138 ECCurve curve = EC5Util.convertCurve(p.getCurve()); 139 ECPoint g = EC5Util.convertPoint(curve, p.getGenerator(), false); 140 141 param = new ECKeyGenerationParameters(new ECDomainParameters(curve, g, p.getOrder(), BigInteger.valueOf(p.getCofactor())), random); 142 143 engine.init(param); 144 initialised = true; 145 } 146 else if (params instanceof ECGenParameterSpec || params instanceof ECNamedCurveGenParameterSpec) 147 { 148 String curveName; 149 150 if (params instanceof ECGenParameterSpec) 151 { 152 curveName = ((ECGenParameterSpec)params).getName(); 153 } 154 else 155 { 156 curveName = ((ECNamedCurveGenParameterSpec)params).getName(); 157 } 158 159 X9ECParameters ecP = ECNamedCurveTable.getByName(curveName); 160 if (ecP == null) 161 { 162 // See if it's actually an OID string (SunJSSE ServerHandshaker setupEphemeralECDHKeys bug) 163 try 164 { 165 ASN1ObjectIdentifier oid = new ASN1ObjectIdentifier(curveName); 166 ecP = ECNamedCurveTable.getByOID(oid); 167 if (ecP == null) 168 { 169 throw new InvalidAlgorithmParameterException("unknown curve OID: " + curveName); 170 } 171 } 172 catch (IllegalArgumentException ex) 173 { 174 throw new InvalidAlgorithmParameterException("unknown curve name: " + curveName); 175 } 176 } 177 178 this.ecParams = new ECNamedCurveSpec( 179 curveName, 180 ecP.getCurve(), 181 ecP.getG(), 182 ecP.getN(), 183 ecP.getH(), 184 null); // ecP.getSeed()); Work-around JDK bug -- it won't look up named curves properly if seed is present 185 186 java.security.spec.ECParameterSpec p = (java.security.spec.ECParameterSpec)ecParams; 187 188 ECCurve curve = EC5Util.convertCurve(p.getCurve()); 189 ECPoint g = EC5Util.convertPoint(curve, p.getGenerator(), false); 190 191 param = new ECKeyGenerationParameters(new ECDomainParameters(curve, g, p.getOrder(), BigInteger.valueOf(p.getCofactor())), random); 192 193 engine.init(param); 194 initialised = true; 195 } 196 else if (params == null && configuration.getEcImplicitlyCa() != null) 197 { 198 ECParameterSpec p = configuration.getEcImplicitlyCa(); 199 this.ecParams = params; 200 201 param = new ECKeyGenerationParameters(new ECDomainParameters(p.getCurve(), p.getG(), p.getN()), random); 202 203 engine.init(param); 204 initialised = true; 205 } 206 else if (params == null && configuration.getEcImplicitlyCa() == null) 207 { 208 throw new InvalidAlgorithmParameterException("null parameter passed but no implicitCA set"); 209 } 210 else 211 { 212 throw new InvalidAlgorithmParameterException("parameter object not a ECParameterSpec"); 213 } 214 } 215 216 public KeyPair generateKeyPair() 217 { 218 if (!initialised) 219 { 220 initialize(strength, new SecureRandom()); 221 } 222 223 AsymmetricCipherKeyPair pair = engine.generateKeyPair(); 224 ECPublicKeyParameters pub = (ECPublicKeyParameters)pair.getPublic(); 225 ECPrivateKeyParameters priv = (ECPrivateKeyParameters)pair.getPrivate(); 226 227 if (ecParams instanceof ECParameterSpec) 228 { 229 ECParameterSpec p = (ECParameterSpec)ecParams; 230 231 BCECPublicKey pubKey = new BCECPublicKey(algorithm, pub, p, configuration); 232 return new KeyPair(pubKey, 233 new BCECPrivateKey(algorithm, priv, pubKey, p, configuration)); 234 } 235 else if (ecParams == null) 236 { 237 return new KeyPair(new BCECPublicKey(algorithm, pub, configuration), 238 new BCECPrivateKey(algorithm, priv, configuration)); 239 } 240 else 241 { 242 java.security.spec.ECParameterSpec p = (java.security.spec.ECParameterSpec)ecParams; 243 244 BCECPublicKey pubKey = new BCECPublicKey(algorithm, pub, p, configuration); 245 246 return new KeyPair(pubKey, new BCECPrivateKey(algorithm, priv, pubKey, p, configuration)); 247 } 248 } 249 } 250 251 public static class ECDSA 252 extends EC 253 { 254 public ECDSA() 255 { 256 super("ECDSA", BouncyCastleProvider.CONFIGURATION); 257 } 258 } 259 260 public static class ECDH 261 extends EC 262 { 263 public ECDH() 264 { 265 super("ECDH", BouncyCastleProvider.CONFIGURATION); 266 } 267 } 268 269 public static class ECDHC 270 extends EC 271 { 272 public ECDHC() 273 { 274 super("ECDHC", BouncyCastleProvider.CONFIGURATION); 275 } 276 } 277 278 public static class ECMQV 279 extends EC 280 { 281 public ECMQV() 282 { 283 super("ECMQV", BouncyCastleProvider.CONFIGURATION); 284 } 285 } 286}