1 /* 2 * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.crypto; 27 28 import java.util.*; 29 30 import java.security.*; 31 import java.security.Provider.Service; 32 import java.security.spec.*; 33 34 import sun.security.jca.*; 35 import sun.security.jca.GetInstance.Instance; 36 import sun.security.util.Debug; 37 38 /** 39 * This class provides the functionality of a secret (symmetric) key generator. 40 * 41 * <p>Key generators are constructed using one of the {@code getInstance} 42 * class methods of this class. 43 * 44 * <p>KeyGenerator objects are reusable, i.e., after a key has been 45 * generated, the same KeyGenerator object can be re-used to generate further 46 * keys. 47 * 48 * <p>There are two ways to generate a key: in an algorithm-independent 49 * manner, and in an algorithm-specific manner. 50 * The only difference between the two is the initialization of the object: 51 * 52 * <ul> 53 * <li><b>Algorithm-Independent Initialization</b> 54 * <p>All key generators share the concepts of a <i>keysize</i> and a 55 * <i>source of randomness</i>. 56 * There is an 57 * {@link #init(int, java.security.SecureRandom) init} 58 * method in this KeyGenerator class that takes these two universally 59 * shared types of arguments. There is also one that takes just a 60 * {@code keysize} argument, and uses the SecureRandom implementation 61 * of the highest-priority installed provider as the source of randomness 62 * (or a system-provided source of randomness if none of the installed 63 * providers supply a SecureRandom implementation), and one that takes just a 64 * source of randomness. 65 * 66 * <p>Since no other parameters are specified when you call the above 67 * algorithm-independent {@code init} methods, it is up to the 68 * provider what to do about the algorithm-specific parameters (if any) to be 69 * associated with each of the keys. 70 * 71 * <li><b>Algorithm-Specific Initialization</b> 72 * <p>For situations where a set of algorithm-specific parameters already 73 * exists, there are two 74 * {@link #init(java.security.spec.AlgorithmParameterSpec) init} 75 * methods that have an {@code AlgorithmParameterSpec} 76 * argument. One also has a {@code SecureRandom} argument, while the 77 * other uses the SecureRandom implementation 78 * of the highest-priority installed provider as the source of randomness 79 * (or a system-provided source of randomness if none of the installed 80 * providers supply a SecureRandom implementation). 81 * </ul> 82 * 83 * <p>In case the client does not explicitly initialize the KeyGenerator 84 * (via a call to an {@code init} method), each provider must 85 * supply (and document) a default initialization. 86 * 87 * <p> Every implementation of the Java platform is required to support the 88 * following standard {@code KeyGenerator} algorithms with the keysizes in 89 * parentheses: 90 * <ul> 91 * <li>{@code AES} (128)</li> 92 * <li>{@code DES} (56)</li> 93 * <li>{@code DESede} (168)</li> 94 * <li>{@code HmacSHA1}</li> 95 * <li>{@code HmacSHA256}</li> 96 * </ul> 97 * These algorithms are described in the <a href= 98 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator"> 99 * KeyGenerator section</a> of the 100 * Java Cryptography Architecture Standard Algorithm Name Documentation. 101 * Consult the release documentation for your implementation to see if any 102 * other algorithms are supported. 103 * 104 * @author Jan Luehe 105 * 106 * @see SecretKey 107 * @since 1.4 108 */ 109 110 public class KeyGenerator { 111 112 private static final Debug pdebug = 113 Debug.getInstance("provider", "Provider"); 114 private static final boolean skipDebug = 115 Debug.isOn("engine=") && !Debug.isOn("keygenerator"); 116 117 // see java.security.KeyPairGenerator for failover notes 118 119 private static final int I_NONE = 1; 120 private static final int I_RANDOM = 2; 121 private static final int I_PARAMS = 3; 122 private static final int I_SIZE = 4; 123 124 // The provider 125 private Provider provider; 126 127 // The provider implementation (delegate) 128 private volatile KeyGeneratorSpi spi; 129 130 // The algorithm 131 private final String algorithm; 132 133 private final Object lock = new Object(); 134 135 private Iterator<Service> serviceIterator; 136 137 private int initType; 138 private int initKeySize; 139 private AlgorithmParameterSpec initParams; 140 private SecureRandom initRandom; 141 142 /** 143 * Creates a KeyGenerator object. 144 * 145 * @param keyGenSpi the delegate 146 * @param provider the provider 147 * @param algorithm the algorithm 148 */ 149 protected KeyGenerator(KeyGeneratorSpi keyGenSpi, Provider provider, 150 String algorithm) { 151 this.spi = keyGenSpi; 152 this.provider = provider; 153 this.algorithm = algorithm; 154 155 if (!skipDebug && pdebug != null) { 156 pdebug.println("KeyGenerator." + algorithm + " algorithm from: " + 157 this.provider.getName()); 158 } 159 } 160 161 private KeyGenerator(String algorithm) throws NoSuchAlgorithmException { 162 this.algorithm = algorithm; 163 List<Service> list = 164 GetInstance.getServices("KeyGenerator", algorithm); 165 serviceIterator = list.iterator(); 166 initType = I_NONE; 167 // fetch and instantiate initial spi 168 if (nextSpi(null, false) == null) { 169 throw new NoSuchAlgorithmException 170 (algorithm + " KeyGenerator not available"); 171 } 172 173 if (!skipDebug && pdebug != null) { 174 pdebug.println("KeyGenerator." + algorithm + " algorithm from: " + 175 this.provider.getName()); 176 } 177 } 178 179 /** 180 * Returns the algorithm name of this {@code KeyGenerator} object. 181 * 182 * <p>This is the same name that was specified in one of the 183 * {@code getInstance} calls that created this 184 * {@code KeyGenerator} object. 185 * 186 * @return the algorithm name of this {@code KeyGenerator} object. 187 */ 188 public final String getAlgorithm() { 189 return this.algorithm; 190 } 191 192 /** 193 * Returns a {@code KeyGenerator} object that generates secret keys 194 * for the specified algorithm. 195 * 196 * <p> This method traverses the list of registered security Providers, 197 * starting with the most preferred Provider. 198 * A new KeyGenerator object encapsulating the 199 * KeyGeneratorSpi implementation from the first 200 * Provider that supports the specified algorithm is returned. 201 * 202 * <p> Note that the list of registered providers may be retrieved via 203 * the {@link Security#getProviders() Security.getProviders()} method. 204 * 205 * @implNote 206 * The JDK Reference Implementation additionally uses the 207 * {@code jdk.security.provider.preferred} property to determine 208 * the preferred provider order for the specified algorithm. This 209 * may be different than the order of providers returned by 210 * {@link Security#getProviders() Security.getProviders()}. 211 * 212 * @param algorithm the standard name of the requested key algorithm. 213 * See the KeyGenerator section in the <a href= 214 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator"> 215 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 216 * for information about standard algorithm names. 217 * 218 * @return the new {@code KeyGenerator} object. 219 * 220 * @exception NullPointerException if the specified algorithm is null. 221 * 222 * @exception NoSuchAlgorithmException if no Provider supports a 223 * KeyGeneratorSpi implementation for the 224 * specified algorithm. 225 * 226 * @see java.security.Provider 227 */ 228 public static final KeyGenerator getInstance(String algorithm) 229 throws NoSuchAlgorithmException { 230 return new KeyGenerator(algorithm); 231 } 232 233 /** 234 * Returns a {@code KeyGenerator} object that generates secret keys 235 * for the specified algorithm. 236 * 237 * <p> A new KeyGenerator object encapsulating the 238 * KeyGeneratorSpi implementation from the specified provider 239 * is returned. The specified provider must be registered 240 * in the security provider list. 241 * 242 * <p> Note that the list of registered providers may be retrieved via 243 * the {@link Security#getProviders() Security.getProviders()} method. 244 * 245 * @param algorithm the standard name of the requested key algorithm. 246 * See the KeyGenerator section in the <a href= 247 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator"> 248 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 249 * for information about standard algorithm names. 250 * 251 * @param provider the name of the provider. 252 * 253 * @return the new {@code KeyGenerator} object. 254 * 255 * @exception NullPointerException if the specified algorithm is null. 256 * 257 * @exception NoSuchAlgorithmException if a KeyGeneratorSpi 258 * implementation for the specified algorithm is not 259 * available from the specified provider. 260 * 261 * @exception NoSuchProviderException if the specified provider is not 262 * registered in the security provider list. 263 * 264 * @exception IllegalArgumentException if the {@code provider} 265 * is null or empty. 266 * 267 * @see java.security.Provider 268 */ 269 public static final KeyGenerator getInstance(String algorithm, 270 String provider) throws NoSuchAlgorithmException, 271 NoSuchProviderException { 272 Instance instance = JceSecurity.getInstance("KeyGenerator", 273 KeyGeneratorSpi.class, algorithm, provider); 274 return new KeyGenerator((KeyGeneratorSpi)instance.impl, 275 instance.provider, algorithm); 276 } 277 278 /** 279 * Returns a {@code KeyGenerator} object that generates secret keys 280 * for the specified algorithm. 281 * 282 * <p> A new KeyGenerator object encapsulating the 283 * KeyGeneratorSpi implementation from the specified Provider 284 * object is returned. Note that the specified Provider object 285 * does not have to be registered in the provider list. 286 * 287 * @param algorithm the standard name of the requested key algorithm. 288 * See the KeyGenerator section in the <a href= 289 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator"> 290 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 291 * for information about standard algorithm names. 292 * 293 * @param provider the provider. 294 * 295 * @return the new {@code KeyGenerator} object. 296 * 297 * @exception NullPointerException if the specified algorithm is null. 298 * 299 * @exception NoSuchAlgorithmException if a KeyGeneratorSpi 300 * implementation for the specified algorithm is not available 301 * from the specified Provider object. 302 * 303 * @exception IllegalArgumentException if the {@code provider} 304 * is null. 305 * 306 * @see java.security.Provider 307 */ 308 public static final KeyGenerator getInstance(String algorithm, 309 Provider provider) throws NoSuchAlgorithmException { 310 Instance instance = JceSecurity.getInstance("KeyGenerator", 311 KeyGeneratorSpi.class, algorithm, provider); 312 return new KeyGenerator((KeyGeneratorSpi)instance.impl, 313 instance.provider, algorithm); 314 } 315 316 /** 317 * Returns the provider of this {@code KeyGenerator} object. 318 * 319 * @return the provider of this {@code KeyGenerator} object 320 */ 321 public final Provider getProvider() { 322 synchronized (lock) { 323 disableFailover(); 324 return provider; 325 } 326 } 327 328 /** 329 * Update the active spi of this class and return the next 330 * implementation for failover. If no more implementations are 331 * available, this method returns null. However, the active spi of 332 * this class is never set to null. 333 */ 334 private KeyGeneratorSpi nextSpi(KeyGeneratorSpi oldSpi, 335 boolean reinit) { 336 synchronized (lock) { 337 // somebody else did a failover concurrently 338 // try that spi now 339 if ((oldSpi != null) && (oldSpi != spi)) { 340 return spi; 341 } 342 if (serviceIterator == null) { 343 return null; 344 } 345 while (serviceIterator.hasNext()) { 346 Service s = serviceIterator.next(); 347 if (JceSecurity.canUseProvider(s.getProvider()) == false) { 348 continue; 349 } 350 try { 351 Object inst = s.newInstance(null); 352 // ignore non-spis 353 if (inst instanceof KeyGeneratorSpi == false) { 354 continue; 355 } 356 KeyGeneratorSpi spi = (KeyGeneratorSpi)inst; 357 if (reinit) { 358 if (initType == I_SIZE) { 359 spi.engineInit(initKeySize, initRandom); 360 } else if (initType == I_PARAMS) { 361 spi.engineInit(initParams, initRandom); 362 } else if (initType == I_RANDOM) { 363 spi.engineInit(initRandom); 364 } else if (initType != I_NONE) { 365 throw new AssertionError 366 ("KeyGenerator initType: " + initType); 367 } 368 } 369 provider = s.getProvider(); 370 this.spi = spi; 371 return spi; 372 } catch (Exception e) { 373 // ignore 374 } 375 } 376 disableFailover(); 377 return null; 378 } 379 } 380 381 void disableFailover() { 382 serviceIterator = null; 383 initType = 0; 384 initParams = null; 385 initRandom = null; 386 } 387 388 /** 389 * Initializes this key generator. 390 * 391 * @param random the source of randomness for this generator 392 */ 393 public final void init(SecureRandom random) { 394 if (serviceIterator == null) { 395 spi.engineInit(random); 396 return; 397 } 398 RuntimeException failure = null; 399 KeyGeneratorSpi mySpi = spi; 400 do { 401 try { 402 mySpi.engineInit(random); 403 initType = I_RANDOM; 404 initKeySize = 0; 405 initParams = null; 406 initRandom = random; 407 return; 408 } catch (RuntimeException e) { 409 if (failure == null) { 410 failure = e; 411 } 412 mySpi = nextSpi(mySpi, false); 413 } 414 } while (mySpi != null); 415 throw failure; 416 } 417 418 /** 419 * Initializes this key generator with the specified parameter set. 420 * 421 * <p> If this key generator requires any random bytes, it will get them 422 * using the 423 * {@link java.security.SecureRandom} 424 * implementation of the highest-priority installed 425 * provider as the source of randomness. 426 * (If none of the installed providers supply an implementation of 427 * SecureRandom, a system-provided source of randomness will be used.) 428 * 429 * @param params the key generation parameters 430 * 431 * @exception InvalidAlgorithmParameterException if the given parameters 432 * are inappropriate for this key generator 433 */ 434 public final void init(AlgorithmParameterSpec params) 435 throws InvalidAlgorithmParameterException 436 { 437 init(params, JceSecurity.RANDOM); 438 } 439 440 /** 441 * Initializes this key generator with the specified parameter 442 * set and a user-provided source of randomness. 443 * 444 * @param params the key generation parameters 445 * @param random the source of randomness for this key generator 446 * 447 * @exception InvalidAlgorithmParameterException if {@code params} is 448 * inappropriate for this key generator 449 */ 450 public final void init(AlgorithmParameterSpec params, SecureRandom random) 451 throws InvalidAlgorithmParameterException 452 { 453 if (serviceIterator == null) { 454 spi.engineInit(params, random); 455 return; 456 } 457 Exception failure = null; 458 KeyGeneratorSpi mySpi = spi; 459 do { 460 try { 461 mySpi.engineInit(params, random); 462 initType = I_PARAMS; 463 initKeySize = 0; 464 initParams = params; 465 initRandom = random; 466 return; 467 } catch (Exception e) { 468 if (failure == null) { 469 failure = e; 470 } 471 mySpi = nextSpi(mySpi, false); 472 } 473 } while (mySpi != null); 474 if (failure instanceof InvalidAlgorithmParameterException) { 475 throw (InvalidAlgorithmParameterException)failure; 476 } 477 if (failure instanceof RuntimeException) { 478 throw (RuntimeException)failure; 479 } 480 throw new InvalidAlgorithmParameterException("init() failed", failure); 481 } 482 483 /** 484 * Initializes this key generator for a certain keysize. 485 * 486 * <p> If this key generator requires any random bytes, it will get them 487 * using the 488 * {@link java.security.SecureRandom} 489 * implementation of the highest-priority installed 490 * provider as the source of randomness. 491 * (If none of the installed providers supply an implementation of 492 * SecureRandom, a system-provided source of randomness will be used.) 493 * 494 * @param keysize the keysize. This is an algorithm-specific metric, 495 * specified in number of bits. 496 * 497 * @exception InvalidParameterException if the keysize is wrong or not 498 * supported. 499 */ 500 public final void init(int keysize) { 501 init(keysize, JceSecurity.RANDOM); 502 } 503 504 /** 505 * Initializes this key generator for a certain keysize, using a 506 * user-provided source of randomness. 507 * 508 * @param keysize the keysize. This is an algorithm-specific metric, 509 * specified in number of bits. 510 * @param random the source of randomness for this key generator 511 * 512 * @exception InvalidParameterException if the keysize is wrong or not 513 * supported. 514 */ 515 public final void init(int keysize, SecureRandom random) { 516 if (serviceIterator == null) { 517 spi.engineInit(keysize, random); 518 return; 519 } 520 RuntimeException failure = null; 521 KeyGeneratorSpi mySpi = spi; 522 do { 523 try { 524 mySpi.engineInit(keysize, random); 525 initType = I_SIZE; 526 initKeySize = keysize; 527 initParams = null; 528 initRandom = random; 529 return; 530 } catch (RuntimeException e) { 531 if (failure == null) { 532 failure = e; 533 } 534 mySpi = nextSpi(mySpi, false); 535 } 536 } while (mySpi != null); 537 throw failure; 538 } 539 540 /** 541 * Generates a secret key. 542 * 543 * @return the new key 544 */ 545 public final SecretKey generateKey() { 546 if (serviceIterator == null) { 547 return spi.engineGenerateKey(); 548 } 549 RuntimeException failure = null; 550 KeyGeneratorSpi mySpi = spi; 551 do { 552 try { 553 return mySpi.engineGenerateKey(); 554 } catch (RuntimeException e) { 555 if (failure == null) { 556 failure = e; 557 } 558 mySpi = nextSpi(mySpi, true); 559 } 560 } while (mySpi != null); 561 throw failure; 562 } 563 }