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