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