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