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