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