1 /* 2 * Copyright (c) 1997, 2016, 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} 208 * {@link Security#getProperty(String) Security} property to determine 209 * the preferred provider order for the specified algorithm. This 210 * may be different than the order of providers returned by 211 * {@link Security#getProviders() Security.getProviders()}. 212 * 213 * @param algorithm the standard name of the requested key algorithm. 214 * See the KeyGenerator section in the <a href= 215 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator"> 216 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 217 * for information about standard algorithm names. 218 * 219 * @return the new {@code KeyGenerator} object 220 * 221 * @throws NoSuchAlgorithmException if no {@code Provider} supports a 222 * {@code KeyGeneratorSpi} implementation for the 223 * specified algorithm 224 * 225 * @throws NullPointerException if {@code algorithm} is {@code null} 226 * 227 * @see java.security.Provider 228 */ 229 public static final KeyGenerator getInstance(String algorithm) 230 throws NoSuchAlgorithmException { 231 Objects.requireNonNull(algorithm, "null algorithm name"); 232 return new KeyGenerator(algorithm); 233 } 234 235 /** 236 * Returns a {@code KeyGenerator} object that generates secret keys 237 * for the specified algorithm. 238 * 239 * <p> A new KeyGenerator object encapsulating the 240 * KeyGeneratorSpi implementation from the specified provider 241 * is returned. The specified provider must be registered 242 * in the security provider list. 243 * 244 * <p> Note that the list of registered providers may be retrieved via 245 * the {@link Security#getProviders() Security.getProviders()} method. 246 * 247 * @param algorithm the standard name of the requested key algorithm. 248 * See the KeyGenerator section in the <a href= 249 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator"> 250 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 251 * for information about standard algorithm names. 252 * 253 * @param provider the name of the provider. 254 * 255 * @return the new {@code KeyGenerator} object 256 * 257 * @throws IllegalArgumentException if the {@code provider} 258 * is {@code null} or empty 259 * 260 * @throws NoSuchAlgorithmException if a {@code KeyGeneratorSpi} 261 * implementation for the specified algorithm is not 262 * available from the specified provider 263 * 264 * @throws NoSuchProviderException if the specified provider is not 265 * registered in the security provider list 266 * 267 * @throws NullPointerException if {@code algorithm} is {@code null} 268 * 269 * @see java.security.Provider 270 */ 271 public static final KeyGenerator getInstance(String algorithm, 272 String provider) throws NoSuchAlgorithmException, 273 NoSuchProviderException { 274 Objects.requireNonNull(algorithm, "null algorithm name"); 275 Instance instance = JceSecurity.getInstance("KeyGenerator", 276 KeyGeneratorSpi.class, algorithm, provider); 277 return new KeyGenerator((KeyGeneratorSpi)instance.impl, 278 instance.provider, algorithm); 279 } 280 281 /** 282 * Returns a {@code KeyGenerator} object that generates secret keys 283 * for the specified algorithm. 284 * 285 * <p> A new KeyGenerator object encapsulating the 286 * KeyGeneratorSpi implementation from the specified Provider 287 * object is returned. Note that the specified Provider object 288 * does not have to be registered in the provider list. 289 * 290 * @param algorithm the standard name of the requested key algorithm. 291 * See the KeyGenerator section in the <a href= 292 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator"> 293 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 294 * for information about standard algorithm names. 295 * 296 * @param provider the provider. 297 * 298 * @return the new {@code KeyGenerator} object 299 * 300 * @throws IllegalArgumentException if the {@code provider} 301 * is {@code null} 302 * 303 * @throws NoSuchAlgorithmException if a {@code KeyGeneratorSpi} 304 * implementation for the specified algorithm is not available 305 * from the specified {@code Provider} object 306 * 307 * @throws NullPointerException if {@code algorithm} is {@code null} 308 * 309 * @see java.security.Provider 310 */ 311 public static final KeyGenerator getInstance(String algorithm, 312 Provider provider) throws NoSuchAlgorithmException { 313 Objects.requireNonNull(algorithm, "null algorithm name"); 314 Instance instance = JceSecurity.getInstance("KeyGenerator", 315 KeyGeneratorSpi.class, algorithm, provider); 316 return new KeyGenerator((KeyGeneratorSpi)instance.impl, 317 instance.provider, algorithm); 318 } 319 320 /** 321 * Returns the provider of this {@code KeyGenerator} object. 322 * 323 * @return the provider of this {@code KeyGenerator} object 324 */ 325 public final Provider getProvider() { 326 synchronized (lock) { 327 disableFailover(); 328 return provider; 329 } 330 } 331 332 /** 333 * Update the active spi of this class and return the next 334 * implementation for failover. If no more implementations are 335 * available, this method returns null. However, the active spi of 336 * this class is never set to null. 337 */ 338 private KeyGeneratorSpi nextSpi(KeyGeneratorSpi oldSpi, 339 boolean reinit) { 340 synchronized (lock) { 341 // somebody else did a failover concurrently 342 // try that spi now 343 if ((oldSpi != null) && (oldSpi != spi)) { 344 return spi; 345 } 346 if (serviceIterator == null) { 347 return null; 348 } 349 while (serviceIterator.hasNext()) { 350 Service s = serviceIterator.next(); 351 if (JceSecurity.canUseProvider(s.getProvider()) == false) { 352 continue; 353 } 354 try { 355 Object inst = s.newInstance(null); 356 // ignore non-spis 357 if (inst instanceof KeyGeneratorSpi == false) { 358 continue; 359 } 360 KeyGeneratorSpi spi = (KeyGeneratorSpi)inst; 361 if (reinit) { 362 if (initType == I_SIZE) { 363 spi.engineInit(initKeySize, initRandom); 364 } else if (initType == I_PARAMS) { 365 spi.engineInit(initParams, initRandom); 366 } else if (initType == I_RANDOM) { 367 spi.engineInit(initRandom); 368 } else if (initType != I_NONE) { 369 throw new AssertionError 370 ("KeyGenerator initType: " + initType); 371 } 372 } 373 provider = s.getProvider(); 374 this.spi = spi; 375 return spi; 376 } catch (Exception e) { 377 // ignore 378 } 379 } 380 disableFailover(); 381 return null; 382 } 383 } 384 385 void disableFailover() { 386 serviceIterator = null; 387 initType = 0; 388 initParams = null; 389 initRandom = null; 390 } 391 392 /** 393 * Initializes this key generator. 394 * 395 * @param random the source of randomness for this generator 396 */ 397 public final void init(SecureRandom random) { 398 if (serviceIterator == null) { 399 spi.engineInit(random); 400 return; 401 } 402 RuntimeException failure = null; 403 KeyGeneratorSpi mySpi = spi; 404 do { 405 try { 406 mySpi.engineInit(random); 407 initType = I_RANDOM; 408 initKeySize = 0; 409 initParams = null; 410 initRandom = random; 411 return; 412 } catch (RuntimeException e) { 413 if (failure == null) { 414 failure = e; 415 } 416 mySpi = nextSpi(mySpi, false); 417 } 418 } while (mySpi != null); 419 throw failure; 420 } 421 422 /** 423 * Initializes this key generator with the specified parameter set. 424 * 425 * <p> If this key generator requires any random bytes, it will get them 426 * using the 427 * {@link java.security.SecureRandom} 428 * implementation of the highest-priority installed 429 * provider as the source of randomness. 430 * (If none of the installed providers supply an implementation of 431 * SecureRandom, a system-provided source of randomness will be used.) 432 * 433 * @param params the key generation parameters 434 * 435 * @exception InvalidAlgorithmParameterException if the given parameters 436 * are inappropriate for this key generator 437 */ 438 public final void init(AlgorithmParameterSpec params) 439 throws InvalidAlgorithmParameterException 440 { 441 init(params, JceSecurity.RANDOM); 442 } 443 444 /** 445 * Initializes this key generator with the specified parameter 446 * set and a user-provided source of randomness. 447 * 448 * @param params the key generation parameters 449 * @param random the source of randomness for this key generator 450 * 451 * @exception InvalidAlgorithmParameterException if {@code params} is 452 * inappropriate for this key generator 453 */ 454 public final void init(AlgorithmParameterSpec params, SecureRandom random) 455 throws InvalidAlgorithmParameterException 456 { 457 if (serviceIterator == null) { 458 spi.engineInit(params, random); 459 return; 460 } 461 Exception failure = null; 462 KeyGeneratorSpi mySpi = spi; 463 do { 464 try { 465 mySpi.engineInit(params, random); 466 initType = I_PARAMS; 467 initKeySize = 0; 468 initParams = params; 469 initRandom = random; 470 return; 471 } catch (Exception e) { 472 if (failure == null) { 473 failure = e; 474 } 475 mySpi = nextSpi(mySpi, false); 476 } 477 } while (mySpi != null); 478 if (failure instanceof InvalidAlgorithmParameterException) { 479 throw (InvalidAlgorithmParameterException)failure; 480 } 481 if (failure instanceof RuntimeException) { 482 throw (RuntimeException)failure; 483 } 484 throw new InvalidAlgorithmParameterException("init() failed", failure); 485 } 486 487 /** 488 * Initializes this key generator for a certain keysize. 489 * 490 * <p> If this key generator requires any random bytes, it will get them 491 * using the 492 * {@link java.security.SecureRandom} 493 * implementation of the highest-priority installed 494 * provider as the source of randomness. 495 * (If none of the installed providers supply an implementation of 496 * SecureRandom, a system-provided source of randomness will be used.) 497 * 498 * @param keysize the keysize. This is an algorithm-specific metric, 499 * specified in number of bits. 500 * 501 * @exception InvalidParameterException if the keysize is wrong or not 502 * supported. 503 */ 504 public final void init(int keysize) { 505 init(keysize, JceSecurity.RANDOM); 506 } 507 508 /** 509 * Initializes this key generator for a certain keysize, using a 510 * user-provided source of randomness. 511 * 512 * @param keysize the keysize. This is an algorithm-specific metric, 513 * specified in number of bits. 514 * @param random the source of randomness for this key generator 515 * 516 * @exception InvalidParameterException if the keysize is wrong or not 517 * supported. 518 */ 519 public final void init(int keysize, SecureRandom random) { 520 if (serviceIterator == null) { 521 spi.engineInit(keysize, random); 522 return; 523 } 524 RuntimeException failure = null; 525 KeyGeneratorSpi mySpi = spi; 526 do { 527 try { 528 mySpi.engineInit(keysize, random); 529 initType = I_SIZE; 530 initKeySize = keysize; 531 initParams = null; 532 initRandom = random; 533 return; 534 } catch (RuntimeException e) { 535 if (failure == null) { 536 failure = e; 537 } 538 mySpi = nextSpi(mySpi, false); 539 } 540 } while (mySpi != null); 541 throw failure; 542 } 543 544 /** 545 * Generates a secret key. 546 * 547 * @return the new key 548 */ 549 public final SecretKey generateKey() { 550 if (serviceIterator == null) { 551 return spi.engineGenerateKey(); 552 } 553 RuntimeException failure = null; 554 KeyGeneratorSpi mySpi = spi; 555 do { 556 try { 557 return mySpi.engineGenerateKey(); 558 } catch (RuntimeException e) { 559 if (failure == null) { 560 failure = e; 561 } 562 mySpi = nextSpi(mySpi, true); 563 } 564 } while (mySpi != null); 565 throw failure; 566 } 567 }