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 java.security; 27 28 import java.util.*; 29 30 import java.security.Provider.Service; 31 import java.security.spec.KeySpec; 32 import java.security.spec.InvalidKeySpecException; 33 34 import sun.security.util.Debug; 35 import sun.security.jca.*; 36 import sun.security.jca.GetInstance.Instance; 37 38 /** 39 * Key factories are used to convert <I>keys</I> (opaque 40 * cryptographic keys of type {@code Key}) into <I>key specifications</I> 41 * (transparent representations of the underlying key material), and vice 42 * versa. 43 * 44 * <P> Key factories are bi-directional. That is, they allow you to build an 45 * opaque key object from a given key specification (key material), or to 46 * retrieve the underlying key material of a key object in a suitable format. 47 * 48 * <P> Multiple compatible key specifications may exist for the same key. 49 * For example, a DSA public key may be specified using 50 * {@code DSAPublicKeySpec} or 51 * {@code X509EncodedKeySpec}. A key factory can be used to translate 52 * between compatible key specifications. 53 * 54 * <P> The following is an example of how to use a key factory in order to 55 * instantiate a DSA public key from its encoding. 56 * Assume Alice has received a digital signature from Bob. 57 * Bob also sent her his public key (in encoded format) to verify 58 * his signature. Alice then performs the following actions: 59 * 60 * <pre> 61 * X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(bobEncodedPubKey); 62 * KeyFactory keyFactory = KeyFactory.getInstance("DSA"); 63 * PublicKey bobPubKey = keyFactory.generatePublic(bobPubKeySpec); 64 * Signature sig = Signature.getInstance("DSA"); 65 * sig.initVerify(bobPubKey); 66 * sig.update(data); 67 * sig.verify(signature); 68 * </pre> 69 * 70 * <p> Every implementation of the Java platform is required to support the 71 * following standard {@code KeyFactory} algorithms: 72 * <ul> 73 * <li>{@code DiffieHellman}</li> 74 * <li>{@code DSA}</li> 75 * <li>{@code RSA}</li> 76 * </ul> 77 * These algorithms are described in the <a href= 78 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyFactory"> 79 * KeyFactory section</a> of the 80 * Java Cryptography Architecture Standard Algorithm Name Documentation. 81 * Consult the release documentation for your implementation to see if any 82 * other algorithms are supported. 83 * 84 * @author Jan Luehe 85 * 86 * @see Key 87 * @see PublicKey 88 * @see PrivateKey 89 * @see java.security.spec.KeySpec 90 * @see java.security.spec.DSAPublicKeySpec 91 * @see java.security.spec.X509EncodedKeySpec 92 * 93 * @since 1.2 94 */ 95 96 public class KeyFactory { 97 98 private static final Debug debug = 99 Debug.getInstance("jca", "KeyFactory"); 100 101 // The algorithm associated with this key factory 102 private final String algorithm; 103 104 // The provider 105 private Provider provider; 106 107 // The provider implementation (delegate) 108 private volatile KeyFactorySpi spi; 109 110 // lock for mutex during provider selection 111 private final Object lock = new Object(); 112 113 // remaining services to try in provider selection 114 // null once provider is selected 115 private Iterator<Service> serviceIterator; 116 117 /** 118 * Creates a KeyFactory object. 119 * 120 * @param keyFacSpi the delegate 121 * @param provider the provider 122 * @param algorithm the name of the algorithm 123 * to associate with this {@code KeyFactory} 124 */ 125 protected KeyFactory(KeyFactorySpi keyFacSpi, Provider provider, 126 String algorithm) { 127 this.spi = keyFacSpi; 128 this.provider = provider; 129 this.algorithm = algorithm; 130 } 131 132 private KeyFactory(String algorithm) throws NoSuchAlgorithmException { 133 this.algorithm = algorithm; 134 List<Service> list = GetInstance.getServices("KeyFactory", algorithm); 135 serviceIterator = list.iterator(); 136 // fetch and instantiate initial spi 137 if (nextSpi(null) == null) { 138 throw new NoSuchAlgorithmException 139 (algorithm + " KeyFactory not available"); 140 } 141 } 142 143 /** 144 * Returns a KeyFactory object that converts 145 * public/private keys of the specified algorithm. 146 * 147 * <p> This method traverses the list of registered security Providers, 148 * starting with the most preferred Provider. 149 * A new KeyFactory object encapsulating the 150 * KeyFactorySpi implementation from the first 151 * Provider that supports the specified algorithm is returned. 152 * 153 * <p> Note that the list of registered providers may be retrieved via 154 * the {@link Security#getProviders() Security.getProviders()} method. 155 * 156 * @implNote 157 * The JDK Reference Implementation additionally uses the 158 * {@code jdk.security.provider.preferred} 159 * {@link Security#getProperty(String) Security} property to determine 160 * the preferred provider order for the specified algorithm. This 161 * may be different than the order of providers returned by 162 * {@link Security#getProviders() Security.getProviders()}. 163 * 164 * @param algorithm the name of the requested key algorithm. 165 * See the KeyFactory section in the <a href= 166 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyFactory"> 167 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 168 * for information about standard algorithm names. 169 * 170 * @return the new {@code KeyFactory} object 171 * 172 * @throws NoSuchAlgorithmException if no {@code Provider} supports a 173 * {@code KeyFactorySpi} implementation for the 174 * specified algorithm 175 * 176 * @throws NullPointerException if {@code algorithm} is {@code null} 177 * 178 * @see Provider 179 */ 180 public static KeyFactory getInstance(String algorithm) 181 throws NoSuchAlgorithmException { 182 Objects.requireNonNull(algorithm, "null algorithm name"); 183 return new KeyFactory(algorithm); 184 } 185 186 /** 187 * Returns a KeyFactory object that converts 188 * public/private keys of the specified algorithm. 189 * 190 * <p> A new KeyFactory object encapsulating the 191 * KeyFactorySpi implementation from the specified provider 192 * is returned. The specified provider must be registered 193 * in the security provider list. 194 * 195 * <p> Note that the list of registered providers may be retrieved via 196 * the {@link Security#getProviders() Security.getProviders()} method. 197 * 198 * @param algorithm the name of the requested key algorithm. 199 * See the KeyFactory section in the <a href= 200 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyFactory"> 201 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 202 * for information about standard algorithm names. 203 * 204 * @param provider the name of the provider. 205 * 206 * @return the new {@code KeyFactory} object 207 * 208 * @throws IllegalArgumentException if the provider name is {@code null} 209 * or empty 210 * 211 * @throws NoSuchAlgorithmException if a {@code KeyFactorySpi} 212 * implementation for the specified algorithm is not 213 * available from the specified provider 214 * 215 * @throws NoSuchProviderException if the specified provider is not 216 * registered in the security provider list 217 * 218 * @throws NullPointerException if {@code algorithm} is {@code null} 219 * 220 * @see Provider 221 */ 222 public static KeyFactory getInstance(String algorithm, String provider) 223 throws NoSuchAlgorithmException, NoSuchProviderException { 224 Objects.requireNonNull(algorithm, "null algorithm name"); 225 Instance instance = GetInstance.getInstance("KeyFactory", 226 KeyFactorySpi.class, algorithm, provider); 227 return new KeyFactory((KeyFactorySpi)instance.impl, 228 instance.provider, algorithm); 229 } 230 231 /** 232 * Returns a KeyFactory object that converts 233 * public/private keys of the specified algorithm. 234 * 235 * <p> A new KeyFactory object encapsulating the 236 * KeyFactorySpi implementation from the specified Provider 237 * object is returned. Note that the specified Provider object 238 * does not have to be registered in the provider list. 239 * 240 * @param algorithm the name of the requested key algorithm. 241 * See the KeyFactory section in the <a href= 242 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyFactory"> 243 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 244 * for information about standard algorithm names. 245 * 246 * @param provider the provider. 247 * 248 * @return the new {@code KeyFactory} object 249 * 250 * @throws IllegalArgumentException if the specified provider is 251 * {@code null} 252 * 253 * @throws NoSuchAlgorithmException if a {@code KeyFactorySpi} 254 * implementation for the specified algorithm is not available 255 * from the specified {@code Provider} object 256 * 257 * @throws NullPointerException if {@code algorithm} is {@code null} 258 * 259 * @see Provider 260 * 261 * @since 1.4 262 */ 263 public static KeyFactory getInstance(String algorithm, Provider provider) 264 throws NoSuchAlgorithmException { 265 Objects.requireNonNull(algorithm, "null algorithm name"); 266 Instance instance = GetInstance.getInstance("KeyFactory", 267 KeyFactorySpi.class, algorithm, provider); 268 return new KeyFactory((KeyFactorySpi)instance.impl, 269 instance.provider, algorithm); 270 } 271 272 /** 273 * Returns the provider of this key factory object. 274 * 275 * @return the provider of this key factory object 276 */ 277 public final Provider getProvider() { 278 synchronized (lock) { 279 // disable further failover after this call 280 serviceIterator = null; 281 return provider; 282 } 283 } 284 285 /** 286 * Gets the name of the algorithm 287 * associated with this {@code KeyFactory}. 288 * 289 * @return the name of the algorithm associated with this 290 * {@code KeyFactory} 291 */ 292 public final String getAlgorithm() { 293 return this.algorithm; 294 } 295 296 /** 297 * Update the active KeyFactorySpi of this class and return the next 298 * implementation for failover. If no more implemenations are 299 * available, this method returns null. However, the active spi of 300 * this class is never set to null. 301 */ 302 private KeyFactorySpi nextSpi(KeyFactorySpi oldSpi) { 303 synchronized (lock) { 304 // somebody else did a failover concurrently 305 // try that spi now 306 if ((oldSpi != null) && (oldSpi != spi)) { 307 return spi; 308 } 309 if (serviceIterator == null) { 310 return null; 311 } 312 while (serviceIterator.hasNext()) { 313 Service s = serviceIterator.next(); 314 try { 315 Object obj = s.newInstance(null); 316 if (obj instanceof KeyFactorySpi == false) { 317 continue; 318 } 319 KeyFactorySpi spi = (KeyFactorySpi)obj; 320 provider = s.getProvider(); 321 this.spi = spi; 322 return spi; 323 } catch (NoSuchAlgorithmException e) { 324 // ignore 325 } 326 } 327 serviceIterator = null; 328 return null; 329 } 330 } 331 332 /** 333 * Generates a public key object from the provided key specification 334 * (key material). 335 * 336 * @param keySpec the specification (key material) of the public key. 337 * 338 * @return the public key. 339 * 340 * @exception InvalidKeySpecException if the given key specification 341 * is inappropriate for this key factory to produce a public key. 342 */ 343 public final PublicKey generatePublic(KeySpec keySpec) 344 throws InvalidKeySpecException { 345 if (serviceIterator == null) { 346 return spi.engineGeneratePublic(keySpec); 347 } 348 Exception failure = null; 349 KeyFactorySpi mySpi = spi; 350 do { 351 try { 352 return mySpi.engineGeneratePublic(keySpec); 353 } catch (Exception e) { 354 if (failure == null) { 355 failure = e; 356 } 357 mySpi = nextSpi(mySpi); 358 } 359 } while (mySpi != null); 360 if (failure instanceof RuntimeException) { 361 throw (RuntimeException)failure; 362 } 363 if (failure instanceof InvalidKeySpecException) { 364 throw (InvalidKeySpecException)failure; 365 } 366 throw new InvalidKeySpecException 367 ("Could not generate public key", failure); 368 } 369 370 /** 371 * Generates a private key object from the provided key specification 372 * (key material). 373 * 374 * @param keySpec the specification (key material) of the private key. 375 * 376 * @return the private key. 377 * 378 * @exception InvalidKeySpecException if the given key specification 379 * is inappropriate for this key factory to produce a private key. 380 */ 381 public final PrivateKey generatePrivate(KeySpec keySpec) 382 throws InvalidKeySpecException { 383 if (serviceIterator == null) { 384 return spi.engineGeneratePrivate(keySpec); 385 } 386 Exception failure = null; 387 KeyFactorySpi mySpi = spi; 388 do { 389 try { 390 return mySpi.engineGeneratePrivate(keySpec); 391 } catch (Exception e) { 392 if (failure == null) { 393 failure = e; 394 } 395 mySpi = nextSpi(mySpi); 396 } 397 } while (mySpi != null); 398 if (failure instanceof RuntimeException) { 399 throw (RuntimeException)failure; 400 } 401 if (failure instanceof InvalidKeySpecException) { 402 throw (InvalidKeySpecException)failure; 403 } 404 throw new InvalidKeySpecException 405 ("Could not generate private key", failure); 406 } 407 408 /** 409 * Returns a specification (key material) of the given key object. 410 * {@code keySpec} identifies the specification class in which 411 * the key material should be returned. It could, for example, be 412 * {@code DSAPublicKeySpec.class}, to indicate that the 413 * key material should be returned in an instance of the 414 * {@code DSAPublicKeySpec} class. 415 * 416 * @param <T> the type of the key specification to be returned 417 * 418 * @param key the key. 419 * 420 * @param keySpec the specification class in which 421 * the key material should be returned. 422 * 423 * @return the underlying key specification (key material) in an instance 424 * of the requested specification class. 425 * 426 * @exception InvalidKeySpecException if the requested key specification is 427 * inappropriate for the given key, or the given key cannot be processed 428 * (e.g., the given key has an unrecognized algorithm or format). 429 */ 430 public final <T extends KeySpec> T getKeySpec(Key key, Class<T> keySpec) 431 throws InvalidKeySpecException { 432 if (serviceIterator == null) { 433 return spi.engineGetKeySpec(key, keySpec); 434 } 435 Exception failure = null; 436 KeyFactorySpi mySpi = spi; 437 do { 438 try { 439 return mySpi.engineGetKeySpec(key, keySpec); 440 } catch (Exception e) { 441 if (failure == null) { 442 failure = e; 443 } 444 mySpi = nextSpi(mySpi); 445 } 446 } while (mySpi != null); 447 if (failure instanceof RuntimeException) { 448 throw (RuntimeException)failure; 449 } 450 if (failure instanceof InvalidKeySpecException) { 451 throw (InvalidKeySpecException)failure; 452 } 453 throw new InvalidKeySpecException 454 ("Could not get key spec", failure); 455 } 456 457 /** 458 * Translates a key object, whose provider may be unknown or potentially 459 * untrusted, into a corresponding key object of this key factory. 460 * 461 * @param key the key whose provider is unknown or untrusted. 462 * 463 * @return the translated key. 464 * 465 * @exception InvalidKeyException if the given key cannot be processed 466 * by this key factory. 467 */ 468 public final Key translateKey(Key key) throws InvalidKeyException { 469 if (serviceIterator == null) { 470 return spi.engineTranslateKey(key); 471 } 472 Exception failure = null; 473 KeyFactorySpi mySpi = spi; 474 do { 475 try { 476 return mySpi.engineTranslateKey(key); 477 } catch (Exception e) { 478 if (failure == null) { 479 failure = e; 480 } 481 mySpi = nextSpi(mySpi); 482 } 483 } while (mySpi != null); 484 if (failure instanceof RuntimeException) { 485 throw (RuntimeException)failure; 486 } 487 if (failure instanceof InvalidKeyException) { 488 throw (InvalidKeyException)failure; 489 } 490 throw new InvalidKeyException 491 ("Could not translate key", failure); 492 } 493 494 }