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