/* KeyFactory.java --- Key Factory Class
   Copyright (C) 1999, 2003, 2004  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.security;

import gnu.java.security.Engine;

import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;

/**
 * <p>Key factories are used to convert keys (opaque cryptographic keys of type
 * {@link Key}) into key specifications (transparent representations of the
 * underlying key material), and vice versa.</p>
 *
 * <p>Key factories are bi-directional. That is, they allow you to build an
 * opaque key object from a given key specification (key material), or to
 * retrieve the underlying key material of a key object in a suitable format.</p>
 *
 * <p>Multiple compatible key specifications may exist for the same key. For
 * example, a <i>DSA</i> public key may be specified using {@link
 * java.security.spec.DSAPublicKeySpec} or {@link
 * java.security.spec.X509EncodedKeySpec}. A key factory can be used to
 * translate between compatible key specifications.</p>
 *
 * <p>The following is an example of how to use a key factory in order to
 * instantiate a <i>DSA</i> public key from its encoding. Assume Alice has
 * received a digital signature from Bob. Bob also sent her his public key (in
 * encoded format) to verify his signature. Alice then performs the following
 * actions:
 *
 * <pre>
 *  X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(bobEncodedPubKey);
 *  KeyFactory keyFactory = KeyFactory.getInstance("DSA");
 *  PublicKey bobPubKey = keyFactory.generatePublic(bobPubKeySpec);
 *  Signature sig = Signature.getInstance("DSA");
 *  sig.initVerify(bobPubKey);
 *  sig.update(data);
 *  sig.verify(signature);
 * </pre>
 *
 * @since 1.2
 * @see Key
 * @see PublicKey
 * @see PrivateKey
 * @see KeySpec
 * @see java.security.spec.DSAPublicKeySpec
 * @see java.security.spec.X509EncodedKeySpec
   @author Mark Benvenuto
 */
public class KeyFactory
{
  /** The service name for key factories. */
  private static final String KEY_FACTORY = "KeyFactory";

  private KeyFactorySpi keyFacSpi;
  private Provider provider;
  private String algorithm;

  /**
   * Creates a <code>KeyFactory</code> object.
   *
   * @param keyFacSpi the delegate.
   * @param provider the provider.
   * @param algorithm the name of the algorithm to associate with this
   * <code>KeyFactory</code>.
   */
  protected KeyFactory(KeyFactorySpi keyFacSpi, Provider provider,
		       String algorithm)
  {
    this.keyFacSpi = keyFacSpi;
    this.provider = provider;
    this.algorithm = algorithm;
  }

  /**
   * Generates a <code>KeyFactory</code> object that implements the specified
   * algorithm. If the default provider package provides an implementation of
   * the requested algorithm, an instance of <code>KeyFactory</code> containing
   * that implementation is returned. If the algorithm is not available in the
   * default package, other packages are searched.
   *
   * @param algorithm the name of the requested key algorithm. See Appendix A
   * in the Java Cryptography Architecture API Specification &amp; Reference
   * for information about standard algorithm names.
   * @return a <code>KeyFactory</code> object for the specified algorithm.
   * @throws NoSuchAlgorithmException if the requested algorithm is not
   * available in the default provider package or any of the other provider
   * packages that were searched.
   */
  public static KeyFactory getInstance(String algorithm)
    throws NoSuchAlgorithmException
  {
    Provider[] p = Security.getProviders();
    for (int i = 0; i < p.length; i++)
      try
        {
          return getInstance(algorithm, p[i]);
        }
      catch (NoSuchAlgorithmException e)
	{
	  // Ignore.
	}

    throw new NoSuchAlgorithmException(algorithm);
  }

  /**
   * Generates a <code>KeyFactory</code> object for the specified algorithm
   * from the specified provider.
   *
   * @param algorithm the name of the requested key algorithm. See Appendix A
   * in the Java Cryptography Architecture API Specification &amp; Reference
   * for information about standard algorithm names.
   * @param provider the name of the provider.
   * @return a <code>KeyFactory</code> object for the specified algorithm.
   * @throws NoSuchAlgorithmException if the algorithm is not available from
   * the specified provider.
   * @throws NoSuchProviderException if the provider has not been configured.
   * @throws IllegalArgumentException if the provider name is null or empty.
   * @see Provider
   */
  public static KeyFactory getInstance(String algorithm, String provider)
    throws NoSuchAlgorithmException, NoSuchProviderException
  {
    if (provider == null || provider.length() == 0)
      throw new IllegalArgumentException("Illegal provider");

    Provider p = Security.getProvider(provider);
    if (p == null)
      throw new NoSuchProviderException(provider);

    return getInstance(algorithm, p);
  }

  /**
   * Generates a <code>KeyFactory</code> object for the specified algorithm from
   * the specified provider. Note: the <code>provider</code> doesn't have to be
   * registered.
   *
   * @param algorithm the name of the requested key algorithm. See Appendix A
   * in the Java Cryptography Architecture API Specification &amp; Reference for
   * information about standard algorithm names.
   * @param provider the provider.
   * @return a <code>KeyFactory</code> object for the specified algorithm.
   * @throws NoSuchAlgorithmException if the algorithm is not available from
   * the specified provider.
   * @throws IllegalArgumentException if the <code>provider</code> is
   * <code>null</code>.
   * @since 1.4
   * @see Provider
   */
  public static KeyFactory getInstance(String algorithm, Provider provider)
    throws NoSuchAlgorithmException
  {
    if (provider == null)
      throw new IllegalArgumentException("Illegal provider");

    try
      {
	return new KeyFactory((KeyFactorySpi)
	  Engine.getInstance(KEY_FACTORY, algorithm, provider),
          provider, algorithm);
      }
    catch (java.lang.reflect.InvocationTargetException ite)
      {
	throw new NoSuchAlgorithmException(algorithm);
      }
    catch (ClassCastException cce)
      {
	throw new NoSuchAlgorithmException(algorithm);
      } 
  }

  /**
   * Returns the provider of this key factory object.
   *
   * @return the provider of this key factory object.
   */
  public final Provider getProvider()
  {
    return provider;
  }

  /**
   * Gets the name of the algorithm associated with this <code>KeyFactory</code>.
   *
   * @return the name of the algorithm associated with this
   * <code>KeyFactory</code>.
   */
  public final String getAlgorithm()
  {
    return algorithm;
  }

  /**
   * Generates a public key object from the provided key specification (key
   * material).
   *
   * @param keySpec the specification (key material) of the public key.
   * @return the public key.
   * @throws InvalidKeySpecException if the given key specification is
   * inappropriate for this key factory to produce a public key.
   */
  public final PublicKey generatePublic(KeySpec keySpec)
    throws InvalidKeySpecException
  {
    return keyFacSpi.engineGeneratePublic(keySpec);
  }

  /**
   * Generates a private key object from the provided key specification (key
   * material).
   *
   * @param keySpec the specification (key material) of the private key.
   * @return the private key.
   * @throws InvalidKeySpecException if the given key specification is
   * inappropriate for this key factory to produce a private key.
   */
  public final PrivateKey generatePrivate(KeySpec keySpec)
    throws InvalidKeySpecException
  {
    return keyFacSpi.engineGeneratePrivate(keySpec);
  }

  /**
   * Returns a specification (key material) of the given key object.
   * <code>keySpec</code> identifies the specification class in which the key
   * material should be returned. It could, for example, be
   * <code>DSAPublicKeySpec.class</code>, to indicate that the key material
   * should be returned in an instance of the {@link
   * java.security.spec.DSAPublicKeySpec} class.
   *
   * @param key the key.
   * @param keySpec the specification class in which the key material should be
   * returned.
   * @return the underlying key specification (key material) in an instance of
   * the requested specification class.
   * @throws InvalidKeySpecException if the requested key specification is
   * inappropriate for the given key, or the given key cannot be processed
   * (e.g., the given key has an unrecognized algorithm or format).
   */
  public final KeySpec getKeySpec(Key key, Class keySpec)
    throws InvalidKeySpecException
  {
    return keyFacSpi.engineGetKeySpec(key, keySpec);
  }

  /**
   * Translates a key object, whose provider may be unknown or potentially
   * untrusted, into a corresponding key object of this key factory.
   *
   * @param key the key whose provider is unknown or untrusted.
   * @return the translated key.
   * @throws InvalidKeyException if the given key cannot be processed by this
   * key factory.
   */
  public final Key translateKey(Key key) throws InvalidKeyException
  {
    return keyFacSpi.engineTranslateKey(key);
  }
}
