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