1 /* 2 * Copyright (c) 1997, 2015, 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} property to determine 159 * the preferred provider order for the specified algorithm. This 160 * may be different than the order of providers returned by 161 * {@link Security#getProviders() Security.getProviders()}. 162 * 163 * @param algorithm the name of the requested key algorithm. 164 * See the KeyFactory section in the <a href= 165 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyFactory"> 166 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 167 * for information about standard algorithm names. 168 * 169 * @return the new KeyFactory object. 170 * 171 * @exception NoSuchAlgorithmException if no Provider supports a 172 * KeyFactorySpi implementation for the 173 * specified algorithm. 174 * 175 * @see Provider 176 */ 177 public static KeyFactory getInstance(String algorithm) 178 throws NoSuchAlgorithmException { 179 return new KeyFactory(algorithm); 180 } 181 182 /** 183 * Returns a KeyFactory object that converts 184 * public/private keys of the specified algorithm. 185 * 186 * <p> A new KeyFactory object encapsulating the 187 * KeyFactorySpi implementation from the specified provider 188 * is returned. The specified provider must be registered 189 * in the security provider list. 190 * 191 * <p> Note that the list of registered providers may be retrieved via 192 * the {@link Security#getProviders() Security.getProviders()} method. 193 * 194 * @param algorithm the name of the requested key algorithm. 195 * See the KeyFactory section in the <a href= 196 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyFactory"> 197 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 198 * for information about standard algorithm names. 199 * 200 * @param provider the name of the provider. 201 * 202 * @return the new KeyFactory object. 203 * 204 * @exception NoSuchAlgorithmException if a KeyFactorySpi 205 * implementation for the specified algorithm is not 206 * available from the specified provider. 207 * 208 * @exception NoSuchProviderException if the specified provider is not 209 * registered in the security provider list. 210 * 211 * @exception IllegalArgumentException if the provider name is null 212 * or empty. 213 * 214 * @see Provider 215 */ 216 public static KeyFactory getInstance(String algorithm, String provider) 217 throws NoSuchAlgorithmException, NoSuchProviderException { 218 Instance instance = GetInstance.getInstance("KeyFactory", 219 KeyFactorySpi.class, algorithm, provider); 220 return new KeyFactory((KeyFactorySpi)instance.impl, 221 instance.provider, algorithm); 222 } 223 224 /** 225 * Returns a KeyFactory object that converts 226 * public/private keys of the specified algorithm. 227 * 228 * <p> A new KeyFactory object encapsulating the 229 * KeyFactorySpi implementation from the specified Provider 230 * object is returned. Note that the specified Provider object 231 * does not have to be registered in the provider list. 232 * 233 * @param algorithm the name of the requested key algorithm. 234 * See the KeyFactory section in the <a href= 235 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyFactory"> 236 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 237 * for information about standard algorithm names. 238 * 239 * @param provider the provider. 240 * 241 * @return the new KeyFactory object. 242 * 243 * @exception NoSuchAlgorithmException if a KeyFactorySpi 244 * implementation for the specified algorithm is not available 245 * from the specified Provider object. 246 * 247 * @exception IllegalArgumentException if the specified provider is null. 248 * 249 * @see Provider 250 * 251 * @since 1.4 252 */ 253 public static KeyFactory getInstance(String algorithm, Provider provider) 254 throws NoSuchAlgorithmException { 255 Instance instance = GetInstance.getInstance("KeyFactory", 256 KeyFactorySpi.class, algorithm, provider); 257 return new KeyFactory((KeyFactorySpi)instance.impl, 258 instance.provider, algorithm); 259 } 260 261 /** 262 * Returns the provider of this key factory object. 263 * 264 * @return the provider of this key factory object 265 */ 266 public final Provider getProvider() { 267 synchronized (lock) { 268 // disable further failover after this call 269 serviceIterator = null; 270 return provider; 271 } 272 } 273 274 /** 275 * Gets the name of the algorithm 276 * associated with this {@code KeyFactory}. 277 * 278 * @return the name of the algorithm associated with this 279 * {@code KeyFactory} 280 */ 281 public final String getAlgorithm() { 282 return this.algorithm; 283 } 284 285 /** 286 * Update the active KeyFactorySpi of this class and return the next 287 * implementation for failover. If no more implemenations are 288 * available, this method returns null. However, the active spi of 289 * this class is never set to null. 290 */ 291 private KeyFactorySpi nextSpi(KeyFactorySpi oldSpi) { 292 synchronized (lock) { 293 // somebody else did a failover concurrently 294 // try that spi now 295 if ((oldSpi != null) && (oldSpi != spi)) { 296 return spi; 297 } 298 if (serviceIterator == null) { 299 return null; 300 } 301 while (serviceIterator.hasNext()) { 302 Service s = serviceIterator.next(); 303 try { 304 Object obj = s.newInstance(null); 305 if (obj instanceof KeyFactorySpi == false) { 306 continue; 307 } 308 KeyFactorySpi spi = (KeyFactorySpi)obj; 309 provider = s.getProvider(); 310 this.spi = spi; 311 return spi; 312 } catch (NoSuchAlgorithmException e) { 313 // ignore 314 } 315 } 316 serviceIterator = null; 317 return null; 318 } 319 } 320 321 /** 322 * Generates a public key object from the provided key specification 323 * (key material). 324 * 325 * @param keySpec the specification (key material) of the public key. 326 * 327 * @return the public key. 328 * 329 * @exception InvalidKeySpecException if the given key specification 330 * is inappropriate for this key factory to produce a public key. 331 */ 332 public final PublicKey generatePublic(KeySpec keySpec) 333 throws InvalidKeySpecException { 334 if (serviceIterator == null) { 335 return spi.engineGeneratePublic(keySpec); 336 } 337 Exception failure = null; 338 KeyFactorySpi mySpi = spi; 339 do { 340 try { 341 return mySpi.engineGeneratePublic(keySpec); 342 } catch (Exception e) { 343 if (failure == null) { 344 failure = e; 345 } 346 mySpi = nextSpi(mySpi); 347 } 348 } while (mySpi != null); 349 if (failure instanceof RuntimeException) { 350 throw (RuntimeException)failure; 351 } 352 if (failure instanceof InvalidKeySpecException) { 353 throw (InvalidKeySpecException)failure; 354 } 355 throw new InvalidKeySpecException 356 ("Could not generate public key", failure); 357 } 358 359 /** 360 * Generates a private key object from the provided key specification 361 * (key material). 362 * 363 * @param keySpec the specification (key material) of the private key. 364 * 365 * @return the private key. 366 * 367 * @exception InvalidKeySpecException if the given key specification 368 * is inappropriate for this key factory to produce a private key. 369 */ 370 public final PrivateKey generatePrivate(KeySpec keySpec) 371 throws InvalidKeySpecException { 372 if (serviceIterator == null) { 373 return spi.engineGeneratePrivate(keySpec); 374 } 375 Exception failure = null; 376 KeyFactorySpi mySpi = spi; 377 do { 378 try { 379 return mySpi.engineGeneratePrivate(keySpec); 380 } catch (Exception e) { 381 if (failure == null) { 382 failure = e; 383 } 384 mySpi = nextSpi(mySpi); 385 } 386 } while (mySpi != null); 387 if (failure instanceof RuntimeException) { 388 throw (RuntimeException)failure; 389 } 390 if (failure instanceof InvalidKeySpecException) { 391 throw (InvalidKeySpecException)failure; 392 } 393 throw new InvalidKeySpecException 394 ("Could not generate private key", failure); 395 } 396 397 /** 398 * Returns a specification (key material) of the given key object. 399 * {@code keySpec} identifies the specification class in which 400 * the key material should be returned. It could, for example, be 401 * {@code DSAPublicKeySpec.class}, to indicate that the 402 * key material should be returned in an instance of the 403 * {@code DSAPublicKeySpec} class. 404 * 405 * @param <T> the type of the key specification to be returned 406 * 407 * @param key the key. 408 * 409 * @param keySpec the specification class in which 410 * the key material should be returned. 411 * 412 * @return the underlying key specification (key material) in an instance 413 * of the requested specification class. 414 * 415 * @exception InvalidKeySpecException if the requested key specification is 416 * inappropriate for the given key, or the given key cannot be processed 417 * (e.g., the given key has an unrecognized algorithm or format). 418 */ 419 public final <T extends KeySpec> T getKeySpec(Key key, Class<T> keySpec) 420 throws InvalidKeySpecException { 421 if (serviceIterator == null) { 422 return spi.engineGetKeySpec(key, keySpec); 423 } 424 Exception failure = null; 425 KeyFactorySpi mySpi = spi; 426 do { 427 try { 428 return mySpi.engineGetKeySpec(key, keySpec); 429 } catch (Exception e) { 430 if (failure == null) { 431 failure = e; 432 } 433 mySpi = nextSpi(mySpi); 434 } 435 } while (mySpi != null); 436 if (failure instanceof RuntimeException) { 437 throw (RuntimeException)failure; 438 } 439 if (failure instanceof InvalidKeySpecException) { 440 throw (InvalidKeySpecException)failure; 441 } 442 throw new InvalidKeySpecException 443 ("Could not get key spec", failure); 444 } 445 446 /** 447 * Translates a key object, whose provider may be unknown or potentially 448 * untrusted, into a corresponding key object of this key factory. 449 * 450 * @param key the key whose provider is unknown or untrusted. 451 * 452 * @return the translated key. 453 * 454 * @exception InvalidKeyException if the given key cannot be processed 455 * by this key factory. 456 */ 457 public final Key translateKey(Key key) throws InvalidKeyException { 458 if (serviceIterator == null) { 459 return spi.engineTranslateKey(key); 460 } 461 Exception failure = null; 462 KeyFactorySpi mySpi = spi; 463 do { 464 try { 465 return mySpi.engineTranslateKey(key); 466 } catch (Exception e) { 467 if (failure == null) { 468 failure = e; 469 } 470 mySpi = nextSpi(mySpi); 471 } 472 } while (mySpi != null); 473 if (failure instanceof RuntimeException) { 474 throw (RuntimeException)failure; 475 } 476 if (failure instanceof InvalidKeyException) { 477 throw (InvalidKeyException)failure; 478 } 479 throw new InvalidKeyException 480 ("Could not translate key", failure); 481 } 482 483 }