Source for javax.crypto.KeyAgreement

   1: /* KeyAgreement.java -- Engine for key agreement methods.
   2:    Copyright (C) 2004  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package javax.crypto;
  40: 
  41: import gnu.java.security.Engine;
  42: 
  43: import java.lang.reflect.InvocationTargetException;
  44: import java.security.InvalidAlgorithmParameterException;
  45: import java.security.InvalidKeyException;
  46: import java.security.Key;
  47: import java.security.NoSuchAlgorithmException;
  48: import java.security.NoSuchProviderException;
  49: import java.security.Provider;
  50: import java.security.SecureRandom;
  51: import java.security.Security;
  52: import java.security.spec.AlgorithmParameterSpec;
  53: 
  54: /**
  55:  * Key agreement is a method in which two or more parties may agree on a
  56:  * secret key for symmetric cryptography or message authentication
  57:  * without transmitting any secrets in the clear. Key agreement
  58:  * algorithms typically use a public/private <i>key pair</i>, and the
  59:  * public key (along with some additional information) is sent across
  60:  * untrusted networks.
  61:  *
  62:  * <p>The most common form of key agreement used today is the
  63:  * <i>Diffie-Hellman key exchange algorithm</i>, described in <a
  64:  * href="http://www.rsasecurity.com/rsalabs/pkcs/pkcs-3/">PKCS #3 -
  65:  * Diffie Hellman Key Agreement Standard</a>.
  66:  *
  67:  * @author Casey Marshall (csm@gnu.org)
  68:  * @since 1.4
  69:  * @see KeyGenerator
  70:  * @see SecretKey
  71:  */
  72: public class KeyAgreement
  73: {
  74: 
  75:   // Fields.
  76:   // ------------------------------------------------------------------------
  77: 
  78:   private static final String SERVICE = "KeyAgreement";
  79: 
  80:   /** The underlying key agreement implementation. */
  81:   private KeyAgreementSpi kaSpi;
  82: 
  83:   /** The provider of this implementation. */
  84:   private Provider provider;
  85: 
  86:   /** The name of this instance's algorithm. */
  87:   private String algorithm;
  88: 
  89:   /** Singnals whether or not this instance has been initialized. */
  90:   private boolean virgin;
  91: 
  92:   // Constructor.
  93:   // ------------------------------------------------------------------------
  94: 
  95:   protected KeyAgreement(KeyAgreementSpi kaSpi, Provider provider,
  96:                          String algorithm)
  97:   {
  98:     this.kaSpi = kaSpi;
  99:     this.provider = provider;
 100:     this.algorithm = algorithm;
 101:     virgin = true;
 102:   }
 103: 
 104:   // Class methods.
 105:   // ------------------------------------------------------------------------
 106: 
 107:   /**
 108:    * Get an implementation of an algorithm from the first provider that
 109:    * implements it.
 110:    *
 111:    * @param algorithm The name of the algorithm to get.
 112:    * @return The proper KeyAgreement instacne, if found.
 113:    * @throws java.security.NoSuchAlgorithmException If the specified
 114:    *         algorithm is not implemented by any installed provider.
 115:    */
 116:   public static final KeyAgreement getInstance(String algorithm)
 117:     throws NoSuchAlgorithmException
 118:   {
 119:     Provider[] provs = Security.getProviders();
 120:     String msg = algorithm;
 121:     for (int i = 0; i < provs.length; i++)
 122:       {
 123:         try
 124:           {
 125:             return getInstance(algorithm, provs[i]);
 126:           }
 127:         catch (NoSuchAlgorithmException nsae)
 128:           {
 129:             msg = nsae.getMessage();
 130:           }
 131:       }
 132:     throw new NoSuchAlgorithmException(msg);
 133:   }
 134: 
 135:   /**
 136:    * Get an implementation of an algorithm from a named provider.
 137:    *
 138:    * @param algorithm The name of the algorithm to get.
 139:    * @param provider  The name of the provider from which to get the
 140:    *        implementation.
 141:    * @return The proper KeyAgreement instance, if found.
 142:    * @throws java.security.NoSuchAlgorithmException If the named provider
 143:    *         does not implement the algorithm.
 144:    * @throws java.security.NoSuchProviderException If the named provider
 145:    *         does not exist.
 146:    */
 147:   public static final KeyAgreement getInstance(String algorithm,
 148:                                                String provider)
 149:     throws NoSuchAlgorithmException, NoSuchProviderException
 150:   {
 151:     Provider p = Security.getProvider(provider);
 152:     if (p == null)
 153:       {
 154:         throw new NoSuchProviderException(provider);
 155:       }
 156:     return getInstance(algorithm, p);
 157:   }
 158: 
 159:   /**
 160:    * Get an implementation of an algorithm from a specific provider.
 161:    *
 162:    * @param algorithm The name of the algorithm to get.
 163:    * @param provider  The provider from which to get the implementation.
 164:    * @return The proper KeyAgreement instance, if found.
 165:    * @throws java.security.NoSuchAlgorithmException If this provider
 166:    *         does not implement the algorithm.
 167:    */
 168:   public static final KeyAgreement getInstance(String algorithm,
 169:                                                Provider provider)
 170:     throws NoSuchAlgorithmException
 171:   {
 172:     try
 173:       {
 174:         return new KeyAgreement((KeyAgreementSpi)
 175:           Engine.getInstance(SERVICE, algorithm, provider),
 176:           provider, algorithm);
 177:       }
 178:     catch (InvocationTargetException ite)
 179:       {
 180:         if (ite.getCause() == null)
 181:           throw new NoSuchAlgorithmException(algorithm);
 182:         if (ite.getCause() instanceof NoSuchAlgorithmException)
 183:           throw (NoSuchAlgorithmException) ite.getCause();
 184:         throw new NoSuchAlgorithmException(algorithm);
 185:       }
 186:     catch (ClassCastException cce)
 187:       {
 188:         throw new NoSuchAlgorithmException(algorithm);
 189:       }
 190:   }
 191: 
 192:   // Instance methods.
 193:   // ------------------------------------------------------------------------
 194: 
 195:   /**
 196:    * Do a phase in the key agreement. The number of times this method is
 197:    * called depends upon the algorithm and the number of parties
 198:    * involved, but must be called at least once with the
 199:    * <code>lastPhase</code> flag set to <code>true</code>.
 200:    *
 201:    * @param key       The key for this phase.
 202:    * @param lastPhase Should be <code>true</code> if this will be the
 203:    *        last phase before generating the shared secret.
 204:    * @return The intermediate result, or <code>null</code> if there is
 205:    *         no intermediate result.
 206:    * @throws java.lang.IllegalStateException If this instance has not
 207:    *         been initialized.
 208:    * @throws java.security.InvalidKeyException If the key is
 209:    *         inappropriate for this algorithm.
 210:    */
 211:   public final Key doPhase(Key key, boolean lastPhase)
 212:     throws IllegalStateException, InvalidKeyException
 213:   {
 214:     if (virgin)
 215:       {
 216:         throw new IllegalStateException("not initialized");
 217:       }
 218:     return kaSpi.engineDoPhase(key, lastPhase);
 219:   }
 220: 
 221:   /**
 222:    * Generate the shared secret in a new byte array.
 223:    *
 224:    * @return The shared secret.
 225:    * @throws java.lang.IllegalStateException If this instnace has not
 226:    *         been initialized, or if not enough calls to
 227:    *         <code>doPhase</code> have been made.
 228:    */
 229:   public final byte[] generateSecret() throws IllegalStateException
 230:   {
 231:     if (virgin)
 232:       {
 233:         throw new IllegalStateException("not initialized");
 234:       }
 235:     return kaSpi.engineGenerateSecret();
 236:   }
 237: 
 238:   /**
 239:    * Generate the shared secret and store it into the supplied array.
 240:    *
 241:    * @param sharedSecret The array in which to store the secret.
 242:    * @param offset       The index in <code>sharedSecret</code> to start
 243:    *                     storing data.
 244:    * @return The length of the shared secret, in bytes.
 245:    * @throws java.lang.IllegalStateException If this instnace has not
 246:    *         been initialized, or if not enough calls to
 247:    *         <code>doPhase</code> have been made.
 248:    * @throws javax.crypto.ShortBufferException If the supplied array is
 249:    *         not large enough to store the result.
 250:    */
 251:   public final int generateSecret(byte[] sharedSecret, int offset)
 252:   throws IllegalStateException, ShortBufferException
 253:   {
 254:     if (virgin)
 255:       {
 256:         throw new IllegalStateException("not initialized");
 257:       }
 258:     return kaSpi.engineGenerateSecret(sharedSecret, offset);
 259:   }
 260: 
 261:   /**
 262:    * Generate the shared secret and return it as an appropriate {@link
 263:    * SecretKey}.
 264:    *
 265:    * @param algorithm The secret key's algorithm.
 266:    * @return The shared secret as a secret key.
 267:    * @throws java.lang.IllegalStateException If this instnace has not
 268:    *         been initialized, or if not enough calls to
 269:    *         <code>doPhase</code> have been made.
 270:    * @throws java.security.InvalidKeyException If the shared secret
 271:    *         cannot be used to make a {@link SecretKey}.
 272:    * @throws java.security.NoSuchAlgorithmException If the specified
 273:    *         algorithm does not exist.
 274:    */
 275:   public final SecretKey generateSecret(String algorithm)
 276:   throws IllegalStateException, InvalidKeyException, NoSuchAlgorithmException
 277:   {
 278:     if (virgin)
 279:       {
 280:         throw new IllegalStateException("not initialized");
 281:       }
 282:     return kaSpi.engineGenerateSecret(algorithm);
 283:   }
 284: 
 285:   /**
 286:    * Return the name of this key-agreement algorithm.
 287:    *
 288:    * @return The algorithm name.
 289:    */
 290:   public final String getAlgorithm()
 291:   {
 292:     return algorithm;
 293:   }
 294: 
 295:   /**
 296:    * Return the provider of the underlying implementation.
 297:    *
 298:    * @return The provider.
 299:    */
 300:   public final Provider getProvider()
 301:   {
 302:     return provider;
 303:   }
 304: 
 305:   /**
 306:    * Initialize this key agreement with a key. This method will use the
 307:    * highest-priority {@link java.security.SecureRandom} as its source
 308:    * of randomness.
 309:    *
 310:    * @param key The key, usually the user's private key.
 311:    * @throws java.security.InvalidKeyException If the supplied key is
 312:    *         not appropriate.
 313:    */
 314:   public final void init(Key key) throws InvalidKeyException
 315:   {
 316:     init(key, new SecureRandom());
 317:   }
 318: 
 319:   /**
 320:    * Initialize this key agreement with a key and a source of
 321:    * randomness.
 322:    *
 323:    * @param key    The key, usually the user's private key.
 324:    * @param random The source of randomness.
 325:    * @throws java.security.InvalidKeyException If the supplied key is
 326:    *         not appropriate.
 327:    */
 328:   public final void init(Key key, SecureRandom random)
 329:     throws InvalidKeyException
 330:   {
 331:     kaSpi.engineInit(key, random);
 332:     virgin = false; // w00t!
 333:   }
 334: 
 335:   /**
 336:    * Initialize this key agreement with a key and parameters. This
 337:    * method will use the highest-priority {@link
 338:    * java.security.SecureRandom} as its source of randomness.
 339:    *
 340:    * @param key    The key, usually the user's private key.
 341:    * @param params The algorithm parameters.
 342:    * @throws java.security.InvalidAlgorithmParameterException If the
 343:    *         supplied parameters are not appropriate.
 344:    * @throws java.security.InvalidKeyException If the supplied key is
 345:    *         not appropriate.
 346:    */
 347:   public final void init(Key key, AlgorithmParameterSpec params)
 348:     throws InvalidAlgorithmParameterException, InvalidKeyException
 349:   {
 350:     init(key, params, new SecureRandom());
 351:   }
 352: 
 353:   /**
 354:    * Initialize this key agreement with a key, parameters, and source of
 355:    * randomness.
 356:    *
 357:    * @param key    The key, usually the user's private key.
 358:    * @param params The algorithm parameters.
 359:    * @param random The source of randomness.
 360:    * @throws java.security.InvalidAlgorithmParameterException If the
 361:    *         supplied parameters are not appropriate.
 362:    * @throws java.security.InvalidKeyException If the supplied key is
 363:    *         not appropriate.
 364:    */
 365:   public final void init(Key key, AlgorithmParameterSpec params,
 366:                          SecureRandom random)
 367:     throws InvalidAlgorithmParameterException, InvalidKeyException
 368:   {
 369:     kaSpi.engineInit(key, params, random);
 370:     virgin = false; // w00t!
 371:   }
 372: }