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