1/* 2 * Copyright (c) 1997, 2017, 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 26package javax.crypto; 27 28import java.util.*; 29 30import java.security.*; 31import java.security.Provider.Service; 32import java.security.spec.*; 33 34import sun.security.jca.*; 35import sun.security.jca.GetInstance.Instance; 36import 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 * See the Keysize Restriction sections of the 87 * {@extLink security_guide_jdk_providers JDK Providers} 88 * document for information on the KeyGenerator defaults used by 89 * JDK providers. 90 * However, note that defaults may vary across different providers. 91 * Additionally, the default value for a provider may change in a future 92 * version. Therefore, it is recommended to explicitly initialize the 93 * KeyGenerator instead of relying on provider-specific defaults. 94 * 95 * <p> Every implementation of the Java platform is required to support the 96 * following standard {@code KeyGenerator} algorithms with the keysizes in 97 * parentheses: 98 * <ul> 99 * <li>{@code AES} (128)</li> 100 * <li>{@code DES} (56)</li> 101 * <li>{@code DESede} (168)</li> 102 * <li>{@code HmacSHA1}</li> 103 * <li>{@code HmacSHA256}</li> 104 * </ul> 105 * These algorithms are described in the <a href= 106 * "{@docRoot}/../specs/security/standard-names.html#keygenerator-algorithms"> 107 * KeyGenerator section</a> of the 108 * Java Security Standard Algorithm Names Specification. 109 * Consult the release documentation for your implementation to see if any 110 * other algorithms are supported. 111 * 112 * @author Jan Luehe 113 * 114 * @see SecretKey 115 * @since 1.4 116 */ 117 118public class KeyGenerator { 119 120 private static final Debug pdebug = 121 Debug.getInstance("provider", "Provider"); 122 private static final boolean skipDebug = 123 Debug.isOn("engine=") && !Debug.isOn("keygenerator"); 124 125 // see java.security.KeyPairGenerator for failover notes 126 127 private static final int I_NONE = 1; 128 private static final int I_RANDOM = 2; 129 private static final int I_PARAMS = 3; 130 private static final int I_SIZE = 4; 131 132 // The provider 133 private Provider provider; 134 135 // The provider implementation (delegate) 136 private volatile KeyGeneratorSpi spi; 137 138 // The algorithm 139 private final String algorithm; 140 141 private final Object lock = new Object(); 142 143 private Iterator<Service> serviceIterator; 144 145 private int initType; 146 private int initKeySize; 147 private AlgorithmParameterSpec initParams; 148 private SecureRandom initRandom; 149 150 /** 151 * Creates a KeyGenerator object. 152 * 153 * @param keyGenSpi the delegate 154 * @param provider the provider 155 * @param algorithm the algorithm 156 */ 157 protected KeyGenerator(KeyGeneratorSpi keyGenSpi, Provider provider, 158 String algorithm) { 159 this.spi = keyGenSpi; 160 this.provider = provider; 161 this.algorithm = algorithm; 162 163 if (!skipDebug && pdebug != null) { 164 pdebug.println("KeyGenerator." + algorithm + " algorithm from: " + 165 getProviderName()); 166 } 167 } 168 169 private KeyGenerator(String algorithm) throws NoSuchAlgorithmException { 170 this.algorithm = algorithm; 171 List<Service> list = 172 GetInstance.getServices("KeyGenerator", algorithm); 173 serviceIterator = list.iterator(); 174 initType = I_NONE; 175 // fetch and instantiate initial spi 176 if (nextSpi(null, false) == null) { 177 throw new NoSuchAlgorithmException 178 (algorithm + " KeyGenerator not available"); 179 } 180 181 if (!skipDebug && pdebug != null) { 182 pdebug.println("KeyGenerator." + algorithm + " algorithm from: " + 183 getProviderName()); 184 } 185 } 186 187 private String getProviderName() { 188 return (provider == null) ? "(no provider)" : provider.getName(); 189 } 190 191 /** 192 * Returns the algorithm name of this {@code KeyGenerator} object. 193 * 194 * <p>This is the same name that was specified in one of the 195 * {@code getInstance} calls that created this 196 * {@code KeyGenerator} object. 197 * 198 * @return the algorithm name of this {@code KeyGenerator} object. 199 */ 200 public final String getAlgorithm() { 201 return this.algorithm; 202 } 203 204 /** 205 * Returns a {@code KeyGenerator} object that generates secret keys 206 * for the specified algorithm. 207 * 208 * <p> This method traverses the list of registered security Providers, 209 * starting with the most preferred Provider. 210 * A new KeyGenerator object encapsulating the 211 * KeyGeneratorSpi implementation from the first 212 * Provider that supports the specified algorithm is returned. 213 * 214 * <p> Note that the list of registered providers may be retrieved via 215 * the {@link Security#getProviders() Security.getProviders()} method. 216 * 217 * @implNote 218 * The JDK Reference Implementation additionally uses the 219 * {@code jdk.security.provider.preferred} 220 * {@link Security#getProperty(String) Security} property to determine 221 * the preferred provider order for the specified algorithm. This 222 * may be different than the order of providers returned by 223 * {@link Security#getProviders() Security.getProviders()}. 224 * 225 * @param algorithm the standard name of the requested key algorithm. 226 * See the KeyGenerator section in the <a href= 227 * "{@docRoot}/../specs/security/standard-names.html#keygenerator-algorithms"> 228 * Java Security Standard Algorithm Names Specification</a> 229 * for information about standard algorithm names. 230 * 231 * @return the new {@code KeyGenerator} object 232 * 233 * @throws NoSuchAlgorithmException if no {@code Provider} supports a 234 * {@code KeyGeneratorSpi} implementation for the 235 * specified algorithm 236 * 237 * @throws NullPointerException if {@code algorithm} is {@code null} 238 * 239 * @see java.security.Provider 240 */ 241 public static final KeyGenerator getInstance(String algorithm) 242 throws NoSuchAlgorithmException { 243 Objects.requireNonNull(algorithm, "null algorithm name"); 244 return new KeyGenerator(algorithm); 245 } 246 247 /** 248 * Returns a {@code KeyGenerator} object that generates secret keys 249 * for the specified algorithm. 250 * 251 * <p> A new KeyGenerator object encapsulating the 252 * KeyGeneratorSpi implementation from the specified provider 253 * is returned. The specified provider must be registered 254 * in the security provider list. 255 * 256 * <p> Note that the list of registered providers may be retrieved via 257 * the {@link Security#getProviders() Security.getProviders()} method. 258 * 259 * @param algorithm the standard name of the requested key algorithm. 260 * See the KeyGenerator section in the <a href= 261 * "{@docRoot}/../specs/security/standard-names.html#keygenerator-algorithms"> 262 * Java Security Standard Algorithm Names Specification</a> 263 * for information about standard algorithm names. 264 * 265 * @param provider the name of the provider. 266 * 267 * @return the new {@code KeyGenerator} object 268 * 269 * @throws IllegalArgumentException if the {@code provider} 270 * is {@code null} or empty 271 * 272 * @throws NoSuchAlgorithmException if a {@code KeyGeneratorSpi} 273 * implementation for the specified algorithm is not 274 * available from the specified provider 275 * 276 * @throws NoSuchProviderException if the specified provider is not 277 * registered in the security provider list 278 * 279 * @throws NullPointerException if {@code algorithm} is {@code null} 280 * 281 * @see java.security.Provider 282 */ 283 public static final KeyGenerator getInstance(String algorithm, 284 String provider) throws NoSuchAlgorithmException, 285 NoSuchProviderException { 286 Objects.requireNonNull(algorithm, "null algorithm name"); 287 Instance instance = JceSecurity.getInstance("KeyGenerator", 288 KeyGeneratorSpi.class, algorithm, provider); 289 return new KeyGenerator((KeyGeneratorSpi)instance.impl, 290 instance.provider, algorithm); 291 } 292 293 /** 294 * Returns a {@code KeyGenerator} object that generates secret keys 295 * for the specified algorithm. 296 * 297 * <p> A new KeyGenerator object encapsulating the 298 * KeyGeneratorSpi implementation from the specified Provider 299 * object is returned. Note that the specified Provider object 300 * does not have to be registered in the provider list. 301 * 302 * @param algorithm the standard name of the requested key algorithm. 303 * See the KeyGenerator section in the <a href= 304 * "{@docRoot}/../specs/security/standard-names.html#keygenerator-algorithms"> 305 * Java Security Standard Algorithm Names Specification</a> 306 * for information about standard algorithm names. 307 * 308 * @param provider the provider. 309 * 310 * @return the new {@code KeyGenerator} object 311 * 312 * @throws IllegalArgumentException if the {@code provider} 313 * is {@code null} 314 * 315 * @throws NoSuchAlgorithmException if a {@code KeyGeneratorSpi} 316 * implementation for the specified algorithm is not available 317 * from the specified {@code Provider} object 318 * 319 * @throws NullPointerException if {@code algorithm} is {@code null} 320 * 321 * @see java.security.Provider 322 */ 323 public static final KeyGenerator getInstance(String algorithm, 324 Provider provider) throws NoSuchAlgorithmException { 325 Objects.requireNonNull(algorithm, "null algorithm name"); 326 Instance instance = JceSecurity.getInstance("KeyGenerator", 327 KeyGeneratorSpi.class, algorithm, provider); 328 return new KeyGenerator((KeyGeneratorSpi)instance.impl, 329 instance.provider, algorithm); 330 } 331 332 /** 333 * Returns the provider of this {@code KeyGenerator} object. 334 * 335 * @return the provider of this {@code KeyGenerator} object 336 */ 337 public final Provider getProvider() { 338 synchronized (lock) { 339 disableFailover(); 340 return provider; 341 } 342 } 343 344 /** 345 * Update the active spi of this class and return the next 346 * implementation for failover. If no more implementations are 347 * available, this method returns null. However, the active spi of 348 * this class is never set to null. 349 */ 350 private KeyGeneratorSpi nextSpi(KeyGeneratorSpi oldSpi, 351 boolean reinit) { 352 synchronized (lock) { 353 // somebody else did a failover concurrently 354 // try that spi now 355 if ((oldSpi != null) && (oldSpi != spi)) { 356 return spi; 357 } 358 if (serviceIterator == null) { 359 return null; 360 } 361 while (serviceIterator.hasNext()) { 362 Service s = serviceIterator.next(); 363 if (JceSecurity.canUseProvider(s.getProvider()) == false) { 364 continue; 365 } 366 try { 367 Object inst = s.newInstance(null); 368 // ignore non-spis 369 if (inst instanceof KeyGeneratorSpi == false) { 370 continue; 371 } 372 KeyGeneratorSpi spi = (KeyGeneratorSpi)inst; 373 if (reinit) { 374 if (initType == I_SIZE) { 375 spi.engineInit(initKeySize, initRandom); 376 } else if (initType == I_PARAMS) { 377 spi.engineInit(initParams, initRandom); 378 } else if (initType == I_RANDOM) { 379 spi.engineInit(initRandom); 380 } else if (initType != I_NONE) { 381 throw new AssertionError 382 ("KeyGenerator initType: " + initType); 383 } 384 } 385 provider = s.getProvider(); 386 this.spi = spi; 387 return spi; 388 } catch (Exception e) { 389 // ignore 390 } 391 } 392 disableFailover(); 393 return null; 394 } 395 } 396 397 void disableFailover() { 398 serviceIterator = null; 399 initType = 0; 400 initParams = null; 401 initRandom = null; 402 } 403 404 /** 405 * Initializes this key generator. 406 * 407 * @param random the source of randomness for this generator 408 */ 409 public final void init(SecureRandom random) { 410 if (serviceIterator == null) { 411 spi.engineInit(random); 412 return; 413 } 414 RuntimeException failure = null; 415 KeyGeneratorSpi mySpi = spi; 416 do { 417 try { 418 mySpi.engineInit(random); 419 initType = I_RANDOM; 420 initKeySize = 0; 421 initParams = null; 422 initRandom = random; 423 return; 424 } catch (RuntimeException e) { 425 if (failure == null) { 426 failure = e; 427 } 428 mySpi = nextSpi(mySpi, false); 429 } 430 } while (mySpi != null); 431 throw failure; 432 } 433 434 /** 435 * Initializes this key generator with the specified parameter set. 436 * 437 * <p> If this key generator requires any random bytes, it will get them 438 * using the 439 * {@link java.security.SecureRandom} 440 * implementation of the highest-priority installed 441 * provider as the source of randomness. 442 * (If none of the installed providers supply an implementation of 443 * SecureRandom, a system-provided source of randomness will be used.) 444 * 445 * @param params the key generation parameters 446 * 447 * @exception InvalidAlgorithmParameterException if the given parameters 448 * are inappropriate for this key generator 449 */ 450 public final void init(AlgorithmParameterSpec params) 451 throws InvalidAlgorithmParameterException 452 { 453 init(params, JceSecurity.RANDOM); 454 } 455 456 /** 457 * Initializes this key generator with the specified parameter 458 * set and a user-provided source of randomness. 459 * 460 * @param params the key generation parameters 461 * @param random the source of randomness for this key generator 462 * 463 * @exception InvalidAlgorithmParameterException if {@code params} is 464 * inappropriate for this key generator 465 */ 466 public final void init(AlgorithmParameterSpec params, SecureRandom random) 467 throws InvalidAlgorithmParameterException 468 { 469 if (serviceIterator == null) { 470 spi.engineInit(params, random); 471 return; 472 } 473 Exception failure = null; 474 KeyGeneratorSpi mySpi = spi; 475 do { 476 try { 477 mySpi.engineInit(params, random); 478 initType = I_PARAMS; 479 initKeySize = 0; 480 initParams = params; 481 initRandom = random; 482 return; 483 } catch (Exception e) { 484 if (failure == null) { 485 failure = e; 486 } 487 mySpi = nextSpi(mySpi, false); 488 } 489 } while (mySpi != null); 490 if (failure instanceof InvalidAlgorithmParameterException) { 491 throw (InvalidAlgorithmParameterException)failure; 492 } 493 if (failure instanceof RuntimeException) { 494 throw (RuntimeException)failure; 495 } 496 throw new InvalidAlgorithmParameterException("init() failed", failure); 497 } 498 499 /** 500 * Initializes this key generator for a certain keysize. 501 * 502 * <p> If this key generator requires any random bytes, it will get them 503 * using the 504 * {@link java.security.SecureRandom} 505 * implementation of the highest-priority installed 506 * provider as the source of randomness. 507 * (If none of the installed providers supply an implementation of 508 * SecureRandom, a system-provided source of randomness will be used.) 509 * 510 * @param keysize the keysize. This is an algorithm-specific metric, 511 * specified in number of bits. 512 * 513 * @exception InvalidParameterException if the keysize is wrong or not 514 * supported. 515 */ 516 public final void init(int keysize) { 517 init(keysize, JceSecurity.RANDOM); 518 } 519 520 /** 521 * Initializes this key generator for a certain keysize, using a 522 * user-provided source of randomness. 523 * 524 * @param keysize the keysize. This is an algorithm-specific metric, 525 * specified in number of bits. 526 * @param random the source of randomness for this key generator 527 * 528 * @exception InvalidParameterException if the keysize is wrong or not 529 * supported. 530 */ 531 public final void init(int keysize, SecureRandom random) { 532 if (serviceIterator == null) { 533 spi.engineInit(keysize, random); 534 return; 535 } 536 RuntimeException failure = null; 537 KeyGeneratorSpi mySpi = spi; 538 do { 539 try { 540 mySpi.engineInit(keysize, random); 541 initType = I_SIZE; 542 initKeySize = keysize; 543 initParams = null; 544 initRandom = random; 545 return; 546 } catch (RuntimeException e) { 547 if (failure == null) { 548 failure = e; 549 } 550 mySpi = nextSpi(mySpi, false); 551 } 552 } while (mySpi != null); 553 throw failure; 554 } 555 556 /** 557 * Generates a secret key. 558 * 559 * @return the new key 560 */ 561 public final SecretKey generateKey() { 562 if (serviceIterator == null) { 563 return spi.engineGenerateKey(); 564 } 565 RuntimeException failure = null; 566 KeyGeneratorSpi mySpi = spi; 567 do { 568 try { 569 return mySpi.engineGenerateKey(); 570 } catch (RuntimeException e) { 571 if (failure == null) { 572 failure = e; 573 } 574 mySpi = nextSpi(mySpi, true); 575 } 576 } while (mySpi != null); 577 throw failure; 578 } 579} 580