1 /* 2 * Copyright (c) 1997, 2011, 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 37 /** 38 * This class represents a factory for secret keys. 39 * 40 * <P> Key factories are used to convert <I>keys</I> (opaque 41 * cryptographic keys of type <code>Key</code>) into <I>key specifications</I> 42 * (transparent representations of the underlying key material), and vice 43 * versa. 44 * Secret key factories operate only on secret (symmetric) keys. 45 * 46 * <P> Key factories are bi-directional, i.e., they allow to build an opaque 47 * key object from a given key specification (key material), or to retrieve 48 * the underlying key material of a key object in a suitable format. 49 * 50 * <P> Application developers should refer to their provider's documentation 51 * to find out which key specifications are supported by the 52 * {@link #generateSecret(java.security.spec.KeySpec) generateSecret} and 53 * {@link #getKeySpec(javax.crypto.SecretKey, java.lang.Class) getKeySpec} 54 * methods. 55 * For example, the DES secret-key factory supplied by the "SunJCE" provider 56 * supports <code>DESKeySpec</code> as a transparent representation of DES 57 * keys, and that provider's secret-key factory for Triple DES keys supports 58 * <code>DESedeKeySpec</code> as a transparent representation of Triple DES 59 * keys. 60 * 61 * <p> Android provides the following <code>SecretKeyFactory</code> algorithms: 62 * <table> 63 * <thead> 64 * <tr> 65 * <th>Algorithm</th> 66 * <th>Supported API Levels</th> 67 * </tr> 68 * </thead> 69 * <tbody> 70 * <tr> 71 * <td>AES</td> 72 * <td>23+</td> 73 * </tr> 74 * <tr> 75 * <td>DES</td> 76 * <td>1+</td> 77 * </tr> 78 * <tr> 79 * <td>DESede</td> 80 * <td>1+</td> 81 * </tr> 82 * <tr> 83 * <td>HmacSHA1</td> 84 * <td>23+</td> 85 * </tr> 86 * <tr> 87 * <td>HmacSHA224</td> 88 * <td>23+</td> 89 * </tr> 90 * <tr> 91 * <td>HmacSHA256</td> 92 * <td>23+</td> 93 * </tr> 94 * <tr> 95 * <td>HmacSHA384</td> 96 * <td>23+</td> 97 * </tr> 98 * <tr> 99 * <td>HmacSHA512</td> 100 * <td>23+</td> 101 * </tr> 102 * <tr> 103 * <td>PBEwithHmacSHA1</td> 104 * <td>1+</td> 105 * </tr> 106 * <tr> 107 * <td>PBEwithHmacSHA1AndAES_128</td> 108 * <td>26+</td> 109 * </tr> 110 * <tr> 111 * <td>PBEwithHmacSHA1AndAES_256</td> 112 * <td>26+</td> 113 * </tr> 114 * <tr> 115 * <td>PBEwithHmacSHA224AndAES_128</td> 116 * <td>26+</td> 117 * </tr> 118 * <tr> 119 * <td>PBEwithHmacSHA224AndAES_256</td> 120 * <td>26+</td> 121 * </tr> 122 * <tr> 123 * <td>PBEwithHmacSHA256AndAES_128</td> 124 * <td>26+</td> 125 * </tr> 126 * <tr> 127 * <td>PBEwithHmacSHA256AndAES_256</td> 128 * <td>26+</td> 129 * </tr> 130 * <tr> 131 * <td>PBEwithHmacSHA384AndAES_128</td> 132 * <td>26+</td> 133 * </tr> 134 * <tr> 135 * <td>PBEwithHmacSHA384AndAES_256</td> 136 * <td>26+</td> 137 * </tr> 138 * <tr> 139 * <td>PBEwithHmacSHA512AndAES_128</td> 140 * <td>26+</td> 141 * </tr> 142 * <tr> 143 * <td>PBEwithHmacSHA512AndAES_256</td> 144 * <td>26+</td> 145 * </tr> 146 * <tr> 147 * <td>PBEwithMD5AND128BITAES-CBC-OPENSSL</td> 148 * <td>1+</td> 149 * </tr> 150 * <tr> 151 * <td>PBEwithMD5AND192BITAES-CBC-OPENSSL</td> 152 * <td>1+</td> 153 * </tr> 154 * <tr> 155 * <td>PBEwithMD5AND256BITAES-CBC-OPENSSL</td> 156 * <td>1+</td> 157 * </tr> 158 * <tr> 159 * <td>PBEwithMD5ANDDES</td> 160 * <td>1+</td> 161 * </tr> 162 * <tr> 163 * <td>PBEwithMD5ANDRC2</td> 164 * <td>1+</td> 165 * </tr> 166 * <tr> 167 * <td>PBEwithSHA1ANDDES</td> 168 * <td>1+</td> 169 * </tr> 170 * <tr> 171 * <td>PBEwithSHA1ANDRC2</td> 172 * <td>1+</td> 173 * </tr> 174 * <tr> 175 * <td>PBEwithSHA256AND128BITAES-CBC-BC</td> 176 * <td>1+</td> 177 * </tr> 178 * <tr> 179 * <td>PBEwithSHA256AND192BITAES-CBC-BC</td> 180 * <td>1+</td> 181 * </tr> 182 * <tr> 183 * <td>PBEwithSHA256AND256BITAES-CBC-BC</td> 184 * <td>1+</td> 185 * </tr> 186 * <tr> 187 * <td>PBEwithSHAAND128BITAES-CBC-BC</td> 188 * <td>1+</td> 189 * </tr> 190 * <tr> 191 * <td>PBEwithSHAAND128BITRC2-CBC</td> 192 * <td>10+</td> 193 * </tr> 194 * <tr> 195 * <td>PBEwithSHAAND128BITRC4</td> 196 * <td>10+</td> 197 * </tr> 198 * <tr> 199 * <td>PBEwithSHAAND192BITAES-CBC-BC</td> 200 * <td>1+</td> 201 * </tr> 202 * <tr> 203 * <td>PBEwithSHAAND2-KEYTRIPLEDES-CBC</td> 204 * <td>1+</td> 205 * </tr> 206 * <tr> 207 * <td>PBEwithSHAAND256BITAES-CBC-BC</td> 208 * <td>1+</td> 209 * </tr> 210 * <tr> 211 * <td>PBEwithSHAAND3-KEYTRIPLEDES-CBC</td> 212 * <td>1+</td> 213 * </tr> 214 * <tr> 215 * <td>PBEwithSHAAND40BITRC2-CBC</td> 216 * <td>1+</td> 217 * </tr> 218 * <tr> 219 * <td>PBEwithSHAAND40BITRC4</td> 220 * <td>10+</td> 221 * </tr> 222 * <tr> 223 * <td>PBEwithSHAANDTWOFISH-CBC</td> 224 * <td>10+</td> 225 * </tr> 226 * <tr> 227 * <td>PBKDF2withHmacSHA1</td> 228 * <td>10+</td> 229 * </tr> 230 * <tr> 231 * <td>PBKDF2withHmacSHA1And8BIT</td> 232 * <td>19+</td> 233 * </tr> 234 * <tr> 235 * <td>PBKDF2withHmacSHA224</td> 236 * <td>26+</td> 237 * </tr> 238 * <tr> 239 * <td>PBKDF2withHmacSHA256</td> 240 * <td>26+</td> 241 * </tr> 242 * <tr> 243 * <td>PBKDF2withHmacSHA384</td> 244 * <td>26+</td> 245 * </tr> 246 * <tr> 247 * <td>PBKDF2withHmacSHA512</td> 248 * <td>26+</td> 249 * </tr> 250 * </tbody> 251 * </table> 252 * 253 * These algorithms are described in the <a href= 254 * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#SecretKeyFactory"> 255 * SecretKeyFactory section</a> of the 256 * Java Cryptography Architecture Standard Algorithm Name Documentation. 257 * 258 * @author Jan Luehe 259 * 260 * @see SecretKey 261 * @see javax.crypto.spec.DESKeySpec 262 * @see javax.crypto.spec.DESedeKeySpec 263 * @see javax.crypto.spec.PBEKeySpec 264 * @since 1.4 265 */ 266 267 public class SecretKeyFactory { 268 269 // The provider 270 private Provider provider; 271 272 // The algorithm associated with this factory 273 private final String algorithm; 274 275 // The provider implementation (delegate) 276 private volatile SecretKeyFactorySpi spi; 277 278 // lock for mutex during provider selection 279 private final Object lock = new Object(); 280 281 // remaining services to try in provider selection 282 // null once provider is selected 283 private Iterator<Service> serviceIterator; 284 285 /** 286 * Creates a SecretKeyFactory object. 287 * 288 * @param keyFacSpi the delegate 289 * @param provider the provider 290 * @param algorithm the secret-key algorithm 291 */ 292 protected SecretKeyFactory(SecretKeyFactorySpi keyFacSpi, 293 Provider provider, String algorithm) { 294 this.spi = keyFacSpi; 295 this.provider = provider; 296 this.algorithm = algorithm; 297 } 298 299 private SecretKeyFactory(String algorithm) throws NoSuchAlgorithmException { 300 this.algorithm = algorithm; 301 List<Service> list = 302 GetInstance.getServices("SecretKeyFactory", algorithm); 303 serviceIterator = list.iterator(); 304 // fetch and instantiate initial spi 305 if (nextSpi(null) == null) { 306 throw new NoSuchAlgorithmException 307 (algorithm + " SecretKeyFactory not available"); 308 } 309 } 310 311 /** 312 * Returns a <code>SecretKeyFactory</code> object that converts 313 * secret keys of the specified algorithm. 314 * 315 * <p> This method traverses the list of registered security Providers, 316 * starting with the most preferred Provider. 317 * A new SecretKeyFactory object encapsulating the 318 * SecretKeyFactorySpi implementation from the first 319 * Provider that supports the specified algorithm is returned. 320 * 321 * <p> Note that the list of registered providers may be retrieved via 322 * the {@link Security#getProviders() Security.getProviders()} method. 323 * 324 * @param algorithm the standard name of the requested secret-key 325 * algorithm. 326 * See the SecretKeyFactory section in the <a href= 327 * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#SecretKeyFactory"> 328 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 329 * for information about standard algorithm names. 330 * 331 * @return the new <code>SecretKeyFactory</code> object. 332 * 333 * @exception NullPointerException if the specified algorithm 334 * is null. 335 * 336 * @exception NoSuchAlgorithmException if no Provider supports a 337 * SecretKeyFactorySpi implementation for the 338 * specified algorithm. 339 * 340 * @see java.security.Provider 341 */ 342 public static final SecretKeyFactory getInstance(String algorithm) 343 throws NoSuchAlgorithmException { 344 return new SecretKeyFactory(algorithm); 345 } 346 347 /** 348 * Returns a <code>SecretKeyFactory</code> object that converts 349 * secret keys of the specified algorithm. 350 * 351 * <p> A new SecretKeyFactory object encapsulating the 352 * SecretKeyFactorySpi implementation from the specified provider 353 * is returned. The specified provider must be registered 354 * in the security provider list. 355 * 356 * <p> Note that the list of registered providers may be retrieved via 357 * the {@link Security#getProviders() Security.getProviders()} method. 358 * 359 * @param algorithm the standard name of the requested secret-key 360 * algorithm. 361 * See the SecretKeyFactory section in the <a href= 362 * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#SecretKeyFactory"> 363 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 364 * for information about standard algorithm names. 365 * 366 * @param provider the name of the provider. 367 * 368 * @return the new <code>SecretKeyFactory</code> object. 369 * 370 * @exception NoSuchAlgorithmException if a SecretKeyFactorySpi 371 * implementation for the specified algorithm is not 372 * available from the specified provider. 373 * 374 * @exception NullPointerException if the specified algorithm 375 * is null. 376 * 377 * @throws NoSuchProviderException if the specified provider is not 378 * registered in the security provider list. 379 * 380 * @exception IllegalArgumentException if the <code>provider</code> 381 * is null or empty. 382 * 383 * @see java.security.Provider 384 */ 385 public static final SecretKeyFactory getInstance(String algorithm, 386 String provider) throws NoSuchAlgorithmException, 387 NoSuchProviderException { 388 Instance instance = JceSecurity.getInstance("SecretKeyFactory", 389 SecretKeyFactorySpi.class, algorithm, provider); 390 return new SecretKeyFactory((SecretKeyFactorySpi)instance.impl, 391 instance.provider, algorithm); 392 } 393 394 /** 395 * Returns a <code>SecretKeyFactory</code> object that converts 396 * secret keys of the specified algorithm. 397 * 398 * <p> A new SecretKeyFactory object encapsulating the 399 * SecretKeyFactorySpi implementation from the specified Provider 400 * object is returned. Note that the specified Provider object 401 * does not have to be registered in the provider list. 402 * 403 * @param algorithm the standard name of the requested secret-key 404 * algorithm. 405 * See the SecretKeyFactory section in the <a href= 406 * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#SecretKeyFactory"> 407 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 408 * for information about standard algorithm names. 409 * 410 * @param provider the provider. 411 * 412 * @return the new <code>SecretKeyFactory</code> object. 413 * 414 * @exception NullPointerException if the specified algorithm 415 * is null. 416 * 417 * @exception NoSuchAlgorithmException if a SecretKeyFactorySpi 418 * implementation for the specified algorithm is not available 419 * from the specified Provider object. 420 * 421 * @exception IllegalArgumentException if the <code>provider</code> 422 * is null. 423 * 424 * @see java.security.Provider 425 */ 426 public static final SecretKeyFactory getInstance(String algorithm, 427 Provider provider) throws NoSuchAlgorithmException { 428 Instance instance = JceSecurity.getInstance("SecretKeyFactory", 429 SecretKeyFactorySpi.class, algorithm, provider); 430 return new SecretKeyFactory((SecretKeyFactorySpi)instance.impl, 431 instance.provider, algorithm); 432 } 433 434 /** 435 * Returns the provider of this <code>SecretKeyFactory</code> object. 436 * 437 * @return the provider of this <code>SecretKeyFactory</code> object 438 */ 439 public final Provider getProvider() { 440 synchronized (lock) { 441 // disable further failover after this call 442 serviceIterator = null; 443 return provider; 444 } 445 } 446 447 /** 448 * Returns the algorithm name of this <code>SecretKeyFactory</code> object. 449 * 450 * <p>This is the same name that was specified in one of the 451 * <code>getInstance</code> calls that created this 452 * <code>SecretKeyFactory</code> object. 453 * 454 * @return the algorithm name of this <code>SecretKeyFactory</code> 455 * object. 456 */ 457 public final String getAlgorithm() { 458 return this.algorithm; 459 } 460 461 /** 462 * Update the active spi of this class and return the next 463 * implementation for failover. If no more implemenations are 464 * available, this method returns null. However, the active spi of 465 * this class is never set to null. 466 */ 467 private SecretKeyFactorySpi nextSpi(SecretKeyFactorySpi oldSpi) { 468 synchronized (lock) { 469 // somebody else did a failover concurrently 470 // try that spi now 471 if ((oldSpi != null) && (oldSpi != spi)) { 472 return spi; 473 } 474 if (serviceIterator == null) { 475 return null; 476 } 477 while (serviceIterator.hasNext()) { 478 Service s = serviceIterator.next(); 479 if (JceSecurity.canUseProvider(s.getProvider()) == false) { 480 continue; 481 } 482 try { 483 Object obj = s.newInstance(null); 484 if (obj instanceof SecretKeyFactorySpi == false) { 485 continue; 486 } 487 SecretKeyFactorySpi spi = (SecretKeyFactorySpi)obj; 488 provider = s.getProvider(); 489 this.spi = spi; 490 return spi; 491 } catch (NoSuchAlgorithmException e) { 492 // ignore 493 } 494 } 495 serviceIterator = null; 496 return null; 497 } 498 } 499 500 /** 501 * Generates a <code>SecretKey</code> object from the provided key 502 * specification (key material). 503 * 504 * @param keySpec the specification (key material) of the secret key 505 * 506 * @return the secret key 507 * 508 * @exception InvalidKeySpecException if the given key specification 509 * is inappropriate for this secret-key factory to produce a secret key. 510 */ 511 public final SecretKey generateSecret(KeySpec keySpec) 512 throws InvalidKeySpecException { 513 if (serviceIterator == null) { 514 return spi.engineGenerateSecret(keySpec); 515 } 516 Exception failure = null; 517 SecretKeyFactorySpi mySpi = spi; 518 do { 519 try { 520 return mySpi.engineGenerateSecret(keySpec); 521 } catch (Exception e) { 522 if (failure == null) { 523 failure = e; 524 } 525 mySpi = nextSpi(mySpi); 526 } 527 } while (mySpi != null); 528 if (failure instanceof InvalidKeySpecException) { 529 throw (InvalidKeySpecException)failure; 530 } 531 throw new InvalidKeySpecException 532 ("Could not generate secret key", failure); 533 } 534 535 /** 536 * Returns a specification (key material) of the given key object 537 * in the requested format. 538 * 539 * @param key the key 540 * @param keySpec the requested format in which the key material shall be 541 * returned 542 * 543 * @return the underlying key specification (key material) in the 544 * requested format 545 * 546 * @exception InvalidKeySpecException if the requested key specification is 547 * inappropriate for the given key (e.g., the algorithms associated with 548 * <code>key</code> and <code>keySpec</code> do not match, or 549 * <code>key</code> references a key on a cryptographic hardware device 550 * whereas <code>keySpec</code> is the specification of a software-based 551 * key), or the given key cannot be dealt with 552 * (e.g., the given key has an algorithm or format not supported by this 553 * secret-key factory). 554 */ 555 public final KeySpec getKeySpec(SecretKey key, Class<?> keySpec) 556 throws InvalidKeySpecException { 557 if (serviceIterator == null) { 558 return spi.engineGetKeySpec(key, keySpec); 559 } 560 Exception failure = null; 561 SecretKeyFactorySpi mySpi = spi; 562 do { 563 try { 564 return mySpi.engineGetKeySpec(key, keySpec); 565 } catch (Exception e) { 566 if (failure == null) { 567 failure = e; 568 } 569 mySpi = nextSpi(mySpi); 570 } 571 } while (mySpi != null); 572 if (failure instanceof InvalidKeySpecException) { 573 throw (InvalidKeySpecException)failure; 574 } 575 throw new InvalidKeySpecException 576 ("Could not get key spec", failure); 577 } 578 579 /** 580 * Translates a key object, whose provider may be unknown or potentially 581 * untrusted, into a corresponding key object of this secret-key factory. 582 * 583 * @param key the key whose provider is unknown or untrusted 584 * 585 * @return the translated key 586 * 587 * @exception InvalidKeyException if the given key cannot be processed 588 * by this secret-key factory. 589 */ 590 public final SecretKey translateKey(SecretKey key) 591 throws InvalidKeyException { 592 if (serviceIterator == null) { 593 return spi.engineTranslateKey(key); 594 } 595 Exception failure = null; 596 SecretKeyFactorySpi mySpi = spi; 597 do { 598 try { 599 return mySpi.engineTranslateKey(key); 600 } catch (Exception e) { 601 if (failure == null) { 602 failure = e; 603 } 604 mySpi = nextSpi(mySpi); 605 } 606 } while (mySpi != null); 607 if (failure instanceof InvalidKeyException) { 608 throw (InvalidKeyException)failure; 609 } 610 throw new InvalidKeyException 611 ("Could not translate key", failure); 612 } 613 } 614