| /* KeyAgreement.java -- Engine for key agreement methods. |
| Copyright (C) 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 javax.crypto; |
| |
| import gnu.java.security.Engine; |
| |
| import java.lang.reflect.InvocationTargetException; |
| import java.security.InvalidAlgorithmParameterException; |
| import java.security.InvalidKeyException; |
| import java.security.Key; |
| import java.security.NoSuchAlgorithmException; |
| import java.security.NoSuchProviderException; |
| import java.security.Provider; |
| import java.security.SecureRandom; |
| import java.security.Security; |
| import java.security.spec.AlgorithmParameterSpec; |
| |
| /** |
| * Key agreement is a method in which two or more parties may agree on a |
| * secret key for symmetric cryptography or message authentication |
| * without transmitting any secrets in the clear. Key agreement |
| * algorithms typically use a public/private <i>key pair</i>, and the |
| * public key (along with some additional information) is sent across |
| * untrusted networks. |
| * |
| * <p>The most common form of key agreement used today is the |
| * <i>Diffie-Hellman key exchange algorithm</i>, described in <a |
| * href="http://www.rsasecurity.com/rsalabs/pkcs/pkcs-3/">PKCS #3 - |
| * Diffie Hellman Key Agreement Standard</a>. |
| * |
| * @author Casey Marshall (csm@gnu.org) |
| * @since 1.4 |
| * @see KeyGenerator |
| * @see SecretKey |
| */ |
| public class KeyAgreement |
| { |
| |
| // Fields. |
| // ------------------------------------------------------------------------ |
| |
| private static final String SERVICE = "KeyAgreement"; |
| |
| /** The underlying key agreement implementation. */ |
| private KeyAgreementSpi kaSpi; |
| |
| /** The provider of this implementation. */ |
| private Provider provider; |
| |
| /** The name of this instance's algorithm. */ |
| private String algorithm; |
| |
| /** Singnals whether or not this instance has been initialized. */ |
| private boolean virgin; |
| |
| // Constructor. |
| // ------------------------------------------------------------------------ |
| |
| protected KeyAgreement(KeyAgreementSpi kaSpi, Provider provider, |
| String algorithm) |
| { |
| this.kaSpi = kaSpi; |
| this.provider = provider; |
| this.algorithm = algorithm; |
| virgin = true; |
| } |
| |
| // Class methods. |
| // ------------------------------------------------------------------------ |
| |
| /** |
| * Get an implementation of an algorithm from the first provider that |
| * implements it. |
| * |
| * @param algorithm The name of the algorithm to get. |
| * @return The proper KeyAgreement instacne, if found. |
| * @throws java.security.NoSuchAlgorithmException If the specified |
| * algorithm is not implemented by any installed provider. |
| */ |
| public static final KeyAgreement getInstance(String algorithm) |
| throws NoSuchAlgorithmException |
| { |
| Provider[] provs = Security.getProviders(); |
| String msg = algorithm; |
| for (int i = 0; i < provs.length; i++) |
| { |
| try |
| { |
| return getInstance(algorithm, provs[i]); |
| } |
| catch (NoSuchAlgorithmException nsae) |
| { |
| msg = nsae.getMessage(); |
| } |
| } |
| throw new NoSuchAlgorithmException(msg); |
| } |
| |
| /** |
| * Get an implementation of an algorithm from a named provider. |
| * |
| * @param algorithm The name of the algorithm to get. |
| * @param provider The name of the provider from which to get the |
| * implementation. |
| * @return The proper KeyAgreement instance, if found. |
| * @throws java.security.NoSuchAlgorithmException If the named provider |
| * does not implement the algorithm. |
| * @throws java.security.NoSuchProviderException If the named provider |
| * does not exist. |
| */ |
| public static final KeyAgreement getInstance(String algorithm, |
| String provider) |
| throws NoSuchAlgorithmException, NoSuchProviderException |
| { |
| Provider p = Security.getProvider(provider); |
| if (p == null) |
| { |
| throw new NoSuchProviderException(provider); |
| } |
| return getInstance(algorithm, p); |
| } |
| |
| /** |
| * Get an implementation of an algorithm from a specific provider. |
| * |
| * @param algorithm The name of the algorithm to get. |
| * @param provider The provider from which to get the implementation. |
| * @return The proper KeyAgreement instance, if found. |
| * @throws java.security.NoSuchAlgorithmException If this provider |
| * does not implement the algorithm. |
| */ |
| public static final KeyAgreement getInstance(String algorithm, |
| Provider provider) |
| throws NoSuchAlgorithmException |
| { |
| try |
| { |
| return new KeyAgreement((KeyAgreementSpi) |
| Engine.getInstance(SERVICE, algorithm, provider), |
| provider, algorithm); |
| } |
| catch (InvocationTargetException ite) |
| { |
| if (ite.getCause() == null) |
| throw new NoSuchAlgorithmException(algorithm); |
| if (ite.getCause() instanceof NoSuchAlgorithmException) |
| throw (NoSuchAlgorithmException) ite.getCause(); |
| throw new NoSuchAlgorithmException(algorithm); |
| } |
| catch (ClassCastException cce) |
| { |
| throw new NoSuchAlgorithmException(algorithm); |
| } |
| } |
| |
| // Instance methods. |
| // ------------------------------------------------------------------------ |
| |
| /** |
| * Do a phase in the key agreement. The number of times this method is |
| * called depends upon the algorithm and the number of parties |
| * involved, but must be called at least once with the |
| * <code>lastPhase</code> flag set to <code>true</code>. |
| * |
| * @param key The key for this phase. |
| * @param lastPhase Should be <code>true</code> if this will be the |
| * last phase before generating the shared secret. |
| * @return The intermediate result, or <code>null</code> if there is |
| * no intermediate result. |
| * @throws java.lang.IllegalStateException If this instance has not |
| * been initialized. |
| * @throws java.security.InvalidKeyException If the key is |
| * inappropriate for this algorithm. |
| */ |
| public final Key doPhase(Key key, boolean lastPhase) |
| throws IllegalStateException, InvalidKeyException |
| { |
| if (virgin) |
| { |
| throw new IllegalStateException("not initialized"); |
| } |
| return kaSpi.engineDoPhase(key, lastPhase); |
| } |
| |
| /** |
| * Generate the shared secret in a new byte array. |
| * |
| * @return The shared secret. |
| * @throws java.lang.IllegalStateException If this instnace has not |
| * been initialized, or if not enough calls to |
| * <code>doPhase</code> have been made. |
| */ |
| public final byte[] generateSecret() throws IllegalStateException |
| { |
| if (virgin) |
| { |
| throw new IllegalStateException("not initialized"); |
| } |
| return kaSpi.engineGenerateSecret(); |
| } |
| |
| /** |
| * Generate the shared secret and store it into the supplied array. |
| * |
| * @param sharedSecret The array in which to store the secret. |
| * @param offset The index in <code>sharedSecret</code> to start |
| * storing data. |
| * @return The length of the shared secret, in bytes. |
| * @throws java.lang.IllegalStateException If this instnace has not |
| * been initialized, or if not enough calls to |
| * <code>doPhase</code> have been made. |
| * @throws javax.crypto.ShortBufferException If the supplied array is |
| * not large enough to store the result. |
| */ |
| public final int generateSecret(byte[] sharedSecret, int offset) |
| throws IllegalStateException, ShortBufferException |
| { |
| if (virgin) |
| { |
| throw new IllegalStateException("not initialized"); |
| } |
| return kaSpi.engineGenerateSecret(sharedSecret, offset); |
| } |
| |
| /** |
| * Generate the shared secret and return it as an appropriate {@link |
| * SecretKey}. |
| * |
| * @param algorithm The secret key's algorithm. |
| * @return The shared secret as a secret key. |
| * @throws java.lang.IllegalStateException If this instnace has not |
| * been initialized, or if not enough calls to |
| * <code>doPhase</code> have been made. |
| * @throws java.security.InvalidKeyException If the shared secret |
| * cannot be used to make a {@link SecretKey}. |
| * @throws java.security.NoSuchAlgorithmException If the specified |
| * algorithm does not exist. |
| */ |
| public final SecretKey generateSecret(String algorithm) |
| throws IllegalStateException, InvalidKeyException, NoSuchAlgorithmException |
| { |
| if (virgin) |
| { |
| throw new IllegalStateException("not initialized"); |
| } |
| return kaSpi.engineGenerateSecret(algorithm); |
| } |
| |
| /** |
| * Return the name of this key-agreement algorithm. |
| * |
| * @return The algorithm name. |
| */ |
| public final String getAlgorithm() |
| { |
| return algorithm; |
| } |
| |
| /** |
| * Return the provider of the underlying implementation. |
| * |
| * @return The provider. |
| */ |
| public final Provider getProvider() |
| { |
| return provider; |
| } |
| |
| /** |
| * Initialize this key agreement with a key. This method will use the |
| * highest-priority {@link java.security.SecureRandom} as its source |
| * of randomness. |
| * |
| * @param key The key, usually the user's private key. |
| * @throws java.security.InvalidKeyException If the supplied key is |
| * not appropriate. |
| */ |
| public final void init(Key key) throws InvalidKeyException |
| { |
| init(key, new SecureRandom()); |
| } |
| |
| /** |
| * Initialize this key agreement with a key and a source of |
| * randomness. |
| * |
| * @param key The key, usually the user's private key. |
| * @param random The source of randomness. |
| * @throws java.security.InvalidKeyException If the supplied key is |
| * not appropriate. |
| */ |
| public final void init(Key key, SecureRandom random) |
| throws InvalidKeyException |
| { |
| kaSpi.engineInit(key, random); |
| virgin = false; // w00t! |
| } |
| |
| /** |
| * Initialize this key agreement with a key and parameters. This |
| * method will use the highest-priority {@link |
| * java.security.SecureRandom} as its source of randomness. |
| * |
| * @param key The key, usually the user's private key. |
| * @param params The algorithm parameters. |
| * @throws java.security.InvalidAlgorithmParameterException If the |
| * supplied parameters are not appropriate. |
| * @throws java.security.InvalidKeyException If the supplied key is |
| * not appropriate. |
| */ |
| public final void init(Key key, AlgorithmParameterSpec params) |
| throws InvalidAlgorithmParameterException, InvalidKeyException |
| { |
| init(key, params, new SecureRandom()); |
| } |
| |
| /** |
| * Initialize this key agreement with a key, parameters, and source of |
| * randomness. |
| * |
| * @param key The key, usually the user's private key. |
| * @param params The algorithm parameters. |
| * @param random The source of randomness. |
| * @throws java.security.InvalidAlgorithmParameterException If the |
| * supplied parameters are not appropriate. |
| * @throws java.security.InvalidKeyException If the supplied key is |
| * not appropriate. |
| */ |
| public final void init(Key key, AlgorithmParameterSpec params, |
| SecureRandom random) |
| throws InvalidAlgorithmParameterException, InvalidKeyException |
| { |
| kaSpi.engineInit(key, params, random); |
| virgin = false; // w00t! |
| } |
| } |