mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			1149 lines
		
	
	
		
			41 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			1149 lines
		
	
	
		
			41 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* Cipher.java -- Interface to a cryptographic cipher.
 | |
|    Copyright (C) 2004, 2006  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.nio.ByteBuffer;
 | |
| import java.nio.ReadOnlyBufferException;
 | |
| 
 | |
| import java.security.AlgorithmParameters;
 | |
| 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.cert.Certificate;
 | |
| import java.security.cert.X509Certificate;
 | |
| import java.security.spec.AlgorithmParameterSpec;
 | |
| import java.util.StringTokenizer;
 | |
| 
 | |
| /**
 | |
|  * <p>This class implements a cryptographic cipher for transforming
 | |
|  * data.</p>
 | |
|  *
 | |
|  * <p>Ciphers cannot be instantiated directly; rather one of the
 | |
|  * <code>getInstance</code> must be used to instantiate a given
 | |
|  * <i>transformation</i>, optionally with a specific provider.</p>
 | |
|  *
 | |
|  * <p>A transformation is of the form:</p>
 | |
|  *
 | |
|  * <ul>
 | |
|  * <li><i>algorithm</i>/<i>mode</i>/<i>padding</i>, or</li>
 | |
|  * <li><i>algorithm</i>
 | |
|  * </ul>
 | |
|  *
 | |
|  * <p>where <i>algorithm</i> is the base name of a cryptographic cipher
 | |
|  * (such as "AES"), <i>mode</i> is the abbreviated name of a block
 | |
|  * cipher mode (such as "CBC" for cipher block chaining mode), and
 | |
|  * <i>padding</i> is the name of a padding scheme (such as
 | |
|  * "PKCS5Padding"). If only the algorithm name is supplied, then the
 | |
|  * provider-specific default mode and padding will be used.</p>
 | |
|  *
 | |
|  * <p>An example transformation is:</p>
 | |
|  *
 | |
|  * <blockquote><code>Cipher c =
 | |
|  * Cipher.getInstance("AES/CBC/PKCS5Padding");</code></blockquote>
 | |
|  *
 | |
|  * <p>Finally, when requesting a block cipher in stream cipher mode
 | |
|  * (such as <acronym title="Advanced Encryption Standard">AES</acronym>
 | |
|  * in OFB or CFB mode) the number of bits to be processed
 | |
|  * at a time may be specified by appending it to the name of the mode;
 | |
|  * e.g. <code>"AES/OFB8/NoPadding"</code>. If no such number is
 | |
|  * specified a provider-specific default value is used.</p>
 | |
|  *
 | |
|  * @author Casey Marshall (csm@gnu.org)
 | |
|  * @see java.security.KeyGenerator
 | |
|  * @see javax.crypto.SecretKey
 | |
|  */
 | |
| public class Cipher
 | |
| {
 | |
| 
 | |
|   // Constants and variables.
 | |
|   // ------------------------------------------------------------------------
 | |
| 
 | |
|   private static final String SERVICE = "Cipher";
 | |
| 
 | |
|   /**
 | |
|    * The decryption operation mode.
 | |
|    */
 | |
|   public static final int DECRYPT_MODE = 2;
 | |
| 
 | |
|   /**
 | |
|    * The encryption operation mode.
 | |
|    */
 | |
|   public static final int ENCRYPT_MODE = 1;
 | |
| 
 | |
|   /**
 | |
|    * Constant for when the key to be unwrapped is a private key.
 | |
|    */
 | |
|   public static final int PRIVATE_KEY = 2;
 | |
| 
 | |
|   /**
 | |
|    * Constant for when the key to be unwrapped is a public key.
 | |
|    */
 | |
|   public static final int PUBLIC_KEY = 1;
 | |
| 
 | |
|   /**
 | |
|    * Constant for when the key to be unwrapped is a secret key.
 | |
|    */
 | |
|   public static final int SECRET_KEY = 3;
 | |
| 
 | |
|   /**
 | |
|    * The key unwrapping operation mode.
 | |
|    */
 | |
|   public static final int UNWRAP_MODE = 4;
 | |
| 
 | |
|   /**
 | |
|    * The key wrapping operation mode.
 | |
|    */
 | |
|   public static final int WRAP_MODE = 3;
 | |
| 
 | |
|   /**
 | |
|    * The uninitialized state. This state signals that any of the
 | |
|    * <code>init</code> methods have not been called, and therefore no
 | |
|    * transformations can be done.
 | |
|    */
 | |
|   private static final int INITIAL_STATE = 0;
 | |
| 
 | |
|   /** The underlying cipher service provider interface. */
 | |
|   private CipherSpi cipherSpi;
 | |
| 
 | |
|   /** The provider from which this instance came. */
 | |
|   private Provider provider;
 | |
| 
 | |
|   /** The transformation requested. */
 | |
|   private String transformation;
 | |
| 
 | |
|   /** Our current state (encrypting, wrapping, etc.) */
 | |
|   private int state;
 | |
| 
 | |
|   /**
 | |
|    * Creates a new cipher instance for the given transformation.
 | |
|    * <p>
 | |
|    * The installed providers are tried in order for an implementation, and the
 | |
|    * first appropriate instance is returned. If no installed provider can
 | |
|    * provide the implementation, an appropriate exception is thrown.
 | |
|    *
 | |
|    * @param transformation The transformation to create.
 | |
|    * @return An appropriate cipher for this transformation.
 | |
|    * @throws NoSuchAlgorithmException If no installed provider can supply the
 | |
|    *           appropriate cipher or mode.
 | |
|    * @throws NoSuchPaddingException If no installed provider can supply the
 | |
|    *           appropriate padding.
 | |
|    */
 | |
|   public static final Cipher getInstance(String transformation)
 | |
|       throws NoSuchAlgorithmException, NoSuchPaddingException
 | |
|   {
 | |
|     Provider[] p = Security.getProviders();
 | |
|     NoSuchAlgorithmException lastException = null;
 | |
|     NoSuchPaddingException lastPaddingException = null;
 | |
|     for (int i = 0; i < p.length; i++)
 | |
|       try
 | |
|         {
 | |
|           return getInstance(transformation, p[i]);
 | |
|         }
 | |
|       catch (NoSuchAlgorithmException x)
 | |
|         {
 | |
|           lastException = x;
 | |
|           lastPaddingException = null;
 | |
|         }
 | |
|       catch (NoSuchPaddingException x)
 | |
|         {
 | |
|           lastPaddingException = x;
 | |
|         }
 | |
|     if (lastPaddingException != null)
 | |
|       throw lastPaddingException;
 | |
|     if (lastException != null)
 | |
|       throw lastException;
 | |
|     throw new NoSuchAlgorithmException(transformation);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Creates a new cipher instance for the given transformation and the named
 | |
|    * provider.
 | |
|    *
 | |
|    * @param transformation The transformation to create.
 | |
|    * @param provider The name of the provider to use.
 | |
|    * @return An appropriate cipher for this transformation.
 | |
|    * @throws NoSuchAlgorithmException If the provider cannot supply the
 | |
|    *           appropriate cipher or mode.
 | |
|    * @throws NoSuchProviderException If the named provider is not installed.
 | |
|    * @throws NoSuchPaddingException If the provider cannot supply the
 | |
|    *           appropriate padding.
 | |
|    * @throws IllegalArgumentException if either <code>transformation</code> or
 | |
|    *           <code>provider</code> is <code>null</code>.
 | |
|    */
 | |
|   public static final Cipher getInstance(String transformation, String provider)
 | |
|       throws NoSuchAlgorithmException, NoSuchProviderException,
 | |
|       NoSuchPaddingException
 | |
|   {
 | |
|     if (provider == null)
 | |
|       throw new IllegalArgumentException("provider MUST NOT be null");
 | |
|     Provider p = Security.getProvider(provider);
 | |
|     if (p == null)
 | |
|       throw new NoSuchProviderException(provider);
 | |
|     return getInstance(transformation, p);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Creates a new cipher instance for a given transformation from a given
 | |
|    * provider.
 | |
|    *
 | |
|    * @param transformation The transformation to create.
 | |
|    * @param provider The provider to use.
 | |
|    * @return An appropriate cipher for this transformation.
 | |
|    * @throws NoSuchAlgorithmException If the given provider cannot supply the
 | |
|    *           appropriate cipher or mode.
 | |
|    * @throws NoSuchPaddingException If the given provider cannot supply the
 | |
|    *           appropriate padding scheme.
 | |
|    */
 | |
|   public static final Cipher getInstance(String transformation,
 | |
|                                          Provider provider)
 | |
|       throws NoSuchAlgorithmException, NoSuchPaddingException
 | |
|   {
 | |
|     StringBuilder sb = new StringBuilder().append("Cipher transformation [")
 | |
|         .append(transformation).append("] from provider [")
 | |
|         .append(provider).append("] ");
 | |
|     Throwable cause;
 | |
|     Object spi;
 | |
|     CipherSpi result;
 | |
|     if (transformation.indexOf('/') < 0)
 | |
|       {
 | |
|         try
 | |
|           {
 | |
|             spi = Engine.getInstance(SERVICE, transformation, provider);
 | |
|             return new Cipher((CipherSpi) spi, provider, transformation);
 | |
|           }
 | |
|         catch (Exception e)
 | |
|           {
 | |
|             if (e instanceof NoSuchAlgorithmException)
 | |
|               throw (NoSuchAlgorithmException) e;
 | |
|             cause = e;
 | |
|           }
 | |
|       }
 | |
|     else
 | |
|       {
 | |
|         StringTokenizer tok = new StringTokenizer(transformation, "/");
 | |
|         if (tok.countTokens() != 3)
 | |
|           throw new NoSuchAlgorithmException(sb.append("is malformed").toString());
 | |
| 
 | |
|         String alg = tok.nextToken();
 | |
|         String mode = tok.nextToken();
 | |
|         String pad = tok.nextToken();
 | |
|         try
 | |
|           {
 | |
|             spi = Engine.getInstance(SERVICE, transformation, provider);
 | |
|             return new Cipher((CipherSpi) spi, provider, transformation);
 | |
|           }
 | |
|         catch (Exception e)
 | |
|           {
 | |
|             cause = e;
 | |
|           }
 | |
| 
 | |
|         try
 | |
|           {
 | |
|             spi = Engine.getInstance(SERVICE, alg + '/' + mode, provider);
 | |
|             result = (CipherSpi) spi;
 | |
|             result.engineSetPadding(pad);
 | |
|             return new Cipher(result, provider, transformation);
 | |
|           }
 | |
|         catch (Exception e)
 | |
|           {
 | |
|             if (e instanceof NoSuchPaddingException)
 | |
|               throw (NoSuchPaddingException) e;
 | |
|             cause = e;
 | |
|           }
 | |
| 
 | |
|         try
 | |
|           {
 | |
|             spi = Engine.getInstance(SERVICE, alg + "//" + pad, provider);
 | |
|             result = (CipherSpi) spi;
 | |
|             result.engineSetMode(mode);
 | |
|             return new Cipher(result, provider, transformation);
 | |
|           }
 | |
|         catch (Exception e)
 | |
|           {
 | |
|             cause = e;
 | |
|           }
 | |
| 
 | |
|         try
 | |
|           {
 | |
|             spi = Engine.getInstance(SERVICE, alg, provider);
 | |
|             result = (CipherSpi) spi;
 | |
|             result.engineSetMode(mode);
 | |
|             result.engineSetPadding(pad);
 | |
|             return new Cipher(result, provider, transformation);
 | |
|           }
 | |
|         catch (Exception e)
 | |
|           {
 | |
|             if (e instanceof NoSuchPaddingException)
 | |
|               throw (NoSuchPaddingException) e;
 | |
|             cause = e;
 | |
|           }
 | |
|       }
 | |
|     sb.append("could not be created");
 | |
|     NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
 | |
|     x.initCause(cause);
 | |
|     throw x;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Create a cipher.
 | |
|    *
 | |
|    * @param cipherSpi The underlying implementation of the cipher.
 | |
|    * @param provider  The provider of this cipher implementation.
 | |
|    * @param transformation The transformation this cipher performs.
 | |
|    */
 | |
|   protected
 | |
|   Cipher(CipherSpi cipherSpi, Provider provider, String transformation)
 | |
|   {
 | |
|     this.cipherSpi = cipherSpi;
 | |
|     this.provider = provider;
 | |
|     this.transformation = transformation;
 | |
|     state = INITIAL_STATE;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Get the name that this cipher instance was created with; this is
 | |
|    * equivalent to the "transformation" argument given to any of the
 | |
|    * {@link #getInstance()} methods.
 | |
|    *
 | |
|    * @return The cipher name.
 | |
|    */
 | |
|   public final String getAlgorithm()
 | |
|   {
 | |
|     return transformation;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Return the size of blocks, in bytes, that this cipher processes.
 | |
|    *
 | |
|    * @return The block size.
 | |
|    */
 | |
|   public final int getBlockSize()
 | |
|   {
 | |
|     if (cipherSpi != null)
 | |
|       {
 | |
|         return cipherSpi.engineGetBlockSize();
 | |
|       }
 | |
|     return 1;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Return the currently-operating {@link ExemptionMechanism}.
 | |
|    *
 | |
|    * @return null, currently.
 | |
|    */
 | |
|   public final ExemptionMechanism getExemptionMechanism()
 | |
|   {
 | |
|     return null;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Return the <i>initialization vector</i> that this instance was
 | |
|    * initialized with.
 | |
|    *
 | |
|    * @return The IV.
 | |
|    */
 | |
|   public final byte[] getIV()
 | |
|   {
 | |
|     if (cipherSpi != null)
 | |
|       {
 | |
|         return cipherSpi.engineGetIV();
 | |
|       }
 | |
|     return null;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Return the {@link java.security.AlgorithmParameters} that this
 | |
|    * instance was initialized with.
 | |
|    *
 | |
|    * @return The parameters.
 | |
|    */
 | |
|   public final AlgorithmParameters getParameters()
 | |
|   {
 | |
|     if (cipherSpi != null) {
 | |
|       return cipherSpi.engineGetParameters();
 | |
|     }
 | |
|     return null;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Return this cipher's provider.
 | |
|    *
 | |
|    * @return The provider.
 | |
|    */
 | |
|   public final Provider getProvider()
 | |
|   {
 | |
|     return provider;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Finishes a multi-part transformation, and returns the final
 | |
|    * transformed bytes.
 | |
|    *
 | |
|    * @return The final transformed bytes.
 | |
|    * @throws java.lang.IllegalStateException If this instance has not
 | |
|    *         been initialized, or if a <tt>doFinal</tt> call has already
 | |
|    *         been made.
 | |
|    * @throws javax.crypto.IllegalBlockSizeException If this instance has
 | |
|    *         no padding and the input is not a multiple of this cipher's
 | |
|    *         block size.
 | |
|    * @throws javax.crypto.BadPaddingException If this instance is
 | |
|    *         decrypting and the padding bytes do not match this
 | |
|    *         instance's padding scheme.
 | |
|    */
 | |
|   public final byte[] doFinal()
 | |
|     throws IllegalStateException, IllegalBlockSizeException, BadPaddingException
 | |
|   {
 | |
|     return doFinal(new byte[0], 0, 0);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Finishes a multi-part transformation or does an entire
 | |
|    * transformation on the input, and returns the transformed bytes.
 | |
|    *
 | |
|    * @param input The final input bytes.
 | |
|    * @return The final transformed bytes.
 | |
|    * @throws java.lang.IllegalStateException If this instance has not
 | |
|    *         been initialized, or if a <tt>doFinal</tt> call has already
 | |
|    *         been made.
 | |
|    * @throws javax.crypto.IllegalBlockSizeException If this instance has
 | |
|    *         no padding and the input is not a multiple of this cipher's
 | |
|    *         block size.
 | |
|    * @throws javax.crypto.BadPaddingException If this instance is
 | |
|    *         decrypting and the padding bytes do not match this
 | |
|    *         instance's padding scheme.
 | |
|    */
 | |
|   public final byte[] doFinal(byte[] input)
 | |
|     throws IllegalStateException, IllegalBlockSizeException, BadPaddingException
 | |
|   {
 | |
|     return doFinal(input, 0, input.length);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Finishes a multi-part transformation or does an entire
 | |
|    * transformation on the input, and returns the transformed bytes.
 | |
|    *
 | |
|    * @param input       The final input bytes.
 | |
|    * @param inputOffset The index in the input bytes to start.
 | |
|    * @param inputLength The number of bytes to read from the input.
 | |
|    * @return The final transformed bytes.
 | |
|    * @throws java.lang.IllegalStateException If this instance has not
 | |
|    *         been initialized, or if a <tt>doFinal</tt> call has already
 | |
|    *         been made.
 | |
|    * @throws javax.crypto.IllegalBlockSizeException If this instance has
 | |
|    *         no padding and the input is not a multiple of this cipher's
 | |
|    *         block size.
 | |
|    * @throws javax.crypto.BadPaddingException If this instance is
 | |
|    *         decrypting and the padding bytes do not match this
 | |
|    *         instance's padding scheme.
 | |
|    */
 | |
|   public final byte[] doFinal(byte[] input, int inputOffset, int inputLength)
 | |
|     throws IllegalStateException, IllegalBlockSizeException, BadPaddingException
 | |
|   {
 | |
|     if (cipherSpi == null)
 | |
|       {
 | |
|         byte[] b = new byte[inputLength];
 | |
|         System.arraycopy(input, inputOffset, b, 0, inputLength);
 | |
|         return b;
 | |
|       }
 | |
|     if (state != ENCRYPT_MODE && state != DECRYPT_MODE)
 | |
|       {
 | |
|         throw new IllegalStateException("neither encrypting nor decrypting");
 | |
|       }
 | |
|     return cipherSpi.engineDoFinal(input, inputOffset, inputLength);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Finishes a multi-part transformation and stores the transformed
 | |
|    * bytes into the given array.
 | |
|    *
 | |
|    * @param output       The destination for the transformed bytes.
 | |
|    * @param outputOffset The offset in <tt>output</tt> to start storing
 | |
|    *        bytes.
 | |
|    * @return The number of bytes placed into the output array.
 | |
|    * @throws java.lang.IllegalStateException If this instance has not
 | |
|    *         been initialized, or if a <tt>doFinal</tt> call has already
 | |
|    *         been made.
 | |
|    * @throws javax.crypto.IllegalBlockSizeException If this instance has
 | |
|    *         no padding and the input is not a multiple of this cipher's
 | |
|    *         block size.
 | |
|    * @throws javax.crypto.BadPaddingException If this instance is
 | |
|    *         decrypting and the padding bytes do not match this
 | |
|    *         instance's padding scheme.
 | |
|    * @throws javax.crypto.ShortBufferException If the output array is
 | |
|    *         not large enough to hold the transformed bytes.
 | |
|    */
 | |
|   public final int doFinal(byte[] output, int outputOffset)
 | |
|     throws IllegalStateException, IllegalBlockSizeException, BadPaddingException,
 | |
|            ShortBufferException
 | |
|   {
 | |
|     if (cipherSpi == null)
 | |
|       {
 | |
|         return 0;
 | |
|       }
 | |
|     if (state != ENCRYPT_MODE && state != DECRYPT_MODE)
 | |
|       {
 | |
|         throw new IllegalStateException("neither encrypting nor decrypting");
 | |
|       }
 | |
|     return cipherSpi.engineDoFinal(new byte[0], 0, 0, output, outputOffset);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Finishes a multi-part transformation or transforms a portion of a
 | |
|    * byte array, and stores the result in the given byte array.
 | |
|    *
 | |
|    * @param input        The input bytes.
 | |
|    * @param inputOffset  The index in <tt>input</tt> to start.
 | |
|    * @param inputLength  The number of bytes to transform.
 | |
|    * @param output       The output buffer.
 | |
|    * @param outputOffset The index in <tt>output</tt> to start.
 | |
|    * @return The number of bytes placed into the output array.
 | |
|    * @throws java.lang.IllegalStateException If this instance has not
 | |
|    *         been initialized, or if a <tt>doFinal</tt> call has already
 | |
|    *         been made.
 | |
|    * @throws javax.crypto.IllegalBlockSizeException If this instance has
 | |
|    *         no padding and the input is not a multiple of this cipher's
 | |
|    *         block size.
 | |
|    * @throws javax.crypto.BadPaddingException If this instance is
 | |
|    *         decrypting and the padding bytes do not match this
 | |
|    *         instance's padding scheme.
 | |
|    * @throws javax.crypto.ShortBufferException If the output array is
 | |
|    *         not large enough to hold the transformed bytes.
 | |
|    */
 | |
|   public final int doFinal(byte[] input, int inputOffset, int inputLength,
 | |
|                            byte[] output, int outputOffset)
 | |
|     throws IllegalStateException, IllegalBlockSizeException, BadPaddingException,
 | |
|            ShortBufferException
 | |
|   {
 | |
|     if (cipherSpi == null)
 | |
|       {
 | |
|         if (inputLength > output.length - outputOffset)
 | |
|           {
 | |
|             throw new ShortBufferException();
 | |
|           }
 | |
|         System.arraycopy(input, inputOffset, output, outputOffset, inputLength);
 | |
|         return inputLength;
 | |
|       }
 | |
|     if (state != ENCRYPT_MODE && state != DECRYPT_MODE)
 | |
|       {
 | |
|         throw new IllegalStateException("neither encrypting nor decrypting");
 | |
|       }
 | |
|     return cipherSpi.engineDoFinal(input, inputOffset, inputLength,
 | |
|                                    output, outputOffset);
 | |
|   }
 | |
| 
 | |
|   public final int doFinal(byte[] input, int inputOffset, int inputLength,
 | |
|                            byte[] output)
 | |
|     throws IllegalStateException, IllegalBlockSizeException, BadPaddingException,
 | |
|            ShortBufferException
 | |
|   {
 | |
|     return doFinal(input, inputOffset, inputLength, output, 0);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Finishes a multi-part transformation with, or completely
 | |
|    * transforms, a byte buffer, and stores the result into the output
 | |
|    * buffer.
 | |
|    *
 | |
|    * @param input  The input buffer.
 | |
|    * @param output The output buffer.
 | |
|    * @return The number of bytes stored into the output buffer.
 | |
|    * @throws IllegalArgumentException If the input and output buffers
 | |
|    *  are the same object.
 | |
|    * @throws IllegalStateException If this cipher was not initialized
 | |
|    *  for encryption or decryption.
 | |
|    * @throws ReadOnlyBufferException If the output buffer is not
 | |
|    *  writable.
 | |
|    * @throws IllegalBlockSizeException If this cipher requires a total
 | |
|    *  input that is a multiple of its block size to complete this
 | |
|    *  transformation.
 | |
|    * @throws ShortBufferException If the output buffer is not large
 | |
|    *  enough to hold the transformed bytes.
 | |
|    * @throws BadPaddingException If the cipher is a block cipher with
 | |
|    *  a padding scheme, and the decrypted bytes do not end with a
 | |
|    *  valid padding.
 | |
|    * @since 1.5
 | |
|    */
 | |
|   public final int doFinal (ByteBuffer input, ByteBuffer output)
 | |
|     throws ReadOnlyBufferException, ShortBufferException,
 | |
|            BadPaddingException, IllegalBlockSizeException
 | |
|   {
 | |
|     if (input == output)
 | |
|       throw new IllegalArgumentException
 | |
|         ("input and output buffers cannot be the same");
 | |
|     if (state != ENCRYPT_MODE && state != DECRYPT_MODE)
 | |
|       throw new IllegalStateException
 | |
|         ("not initialized for encrypting or decrypting");
 | |
|     return cipherSpi.engineDoFinal (input, output);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the size an output buffer needs to be if this cipher is
 | |
|    * updated with a number of bytes.
 | |
|    *
 | |
|    * @param inputLength The input length.
 | |
|    * @return The output length given this input length.
 | |
|    * @throws java.lang.IllegalStateException If this instance has not
 | |
|    *         been initialized, or if a <tt>doFinal</tt> call has already
 | |
|    *         been made.
 | |
|    */
 | |
|   public final int getOutputSize(int inputLength) throws IllegalStateException
 | |
|   {
 | |
|     if (cipherSpi == null)
 | |
|       return inputLength;
 | |
|     return cipherSpi.engineGetOutputSize(inputLength);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <p>Initialize this cipher with the public key from the given
 | |
|    * certificate.</p>
 | |
|    *
 | |
|    * <p>The cipher will be initialized for encryption, decryption, key
 | |
|    * wrapping, or key unwrapping, depending upon whether the
 | |
|    * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link
 | |
|    * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE},
 | |
|    * respectively.</p>
 | |
|    *
 | |
|    * <p>As per the Java 1.4 specification, if <code>cert</code> is an
 | |
|    * instance of an {@link java.security.cert.X509Certificate} and its
 | |
|    * <i>key usage</i> extension field is incompatible with
 | |
|    * <code>opmode</code> then an {@link
 | |
|    * java.security.InvalidKeyException} is thrown.</p>
 | |
|    *
 | |
|    * <p>If this cipher requires any random bytes (for example for an
 | |
|    * initilization vector) than the {@link java.security.SecureRandom}
 | |
|    * with the highest priority is used as the source of these bytes.</p>
 | |
|    *
 | |
|    * <p>A call to any of the <code>init</code> methods overrides the
 | |
|    * state of the instance, and is equivalent to creating a new instance
 | |
|    * and calling its <code>init</code> method.</p>
 | |
|    *
 | |
|    * @param opmode      The operation mode to use.
 | |
|    * @param certificate The certificate.
 | |
|    * @throws java.security.InvalidKeyException If the underlying cipher
 | |
|    *         instance rejects the certificate's public key, or if the
 | |
|    *         public key cannot be used as described above.
 | |
|    */
 | |
|   public final void init(int opmode, Certificate certificate)
 | |
|     throws InvalidKeyException
 | |
|   {
 | |
|     init(opmode, certificate, new SecureRandom());
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <p>Initialize this cipher with the supplied key.</p>
 | |
|    *
 | |
|    * <p>The cipher will be initialized for encryption, decryption, key
 | |
|    * wrapping, or key unwrapping, depending upon whether the
 | |
|    * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link
 | |
|    * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE},
 | |
|    * respectively.</p>
 | |
|    *
 | |
|    * <p>If this cipher requires any random bytes (for example for an
 | |
|    * initilization vector) than the {@link java.security.SecureRandom}
 | |
|    * with the highest priority is used as the source of these bytes.</p>
 | |
|    *
 | |
|    * <p>A call to any of the <code>init</code> methods overrides the
 | |
|    * state of the instance, and is equivalent to creating a new instance
 | |
|    * and calling its <code>init</code> method.</p>
 | |
|    *
 | |
|    * @param opmode The operation mode to use.
 | |
|    * @param key    The key.
 | |
|    * @throws java.security.InvalidKeyException If the underlying cipher
 | |
|    *         instance rejects the given key.
 | |
|    */
 | |
|   public final void init(int opmode, Key key) throws InvalidKeyException
 | |
|   {
 | |
|     if (cipherSpi != null)
 | |
|       {
 | |
|         cipherSpi.engineInit(opmode, key, new SecureRandom());
 | |
|       }
 | |
|     state = opmode;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <p>Initialize this cipher with the public key from the given
 | |
|    * certificate and the specified source of randomness.</p>
 | |
|    *
 | |
|    * <p>The cipher will be initialized for encryption, decryption, key
 | |
|    * wrapping, or key unwrapping, depending upon whether the
 | |
|    * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link
 | |
|    * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE},
 | |
|    * respectively.</p>
 | |
|    *
 | |
|    * <p>As per the Java 1.4 specification, if <code>cert</code> is an
 | |
|    * instance of an {@link java.security.cert.X509Certificate} and its
 | |
|    * <i>key usage</i> extension field is incompatible with
 | |
|    * <code>opmode</code> then an {@link
 | |
|    * java.security.InvalidKeyException} is thrown.</p>
 | |
|    *
 | |
|    * <p>If this cipher requires any random bytes (for example for an
 | |
|    * initilization vector) than the {@link java.security.SecureRandom}
 | |
|    * with the highest priority is used as the source of these bytes.</p>
 | |
|    *
 | |
|    * <p>A call to any of the <code>init</code> methods overrides the
 | |
|    * state of the instance, and is equivalent to creating a new instance
 | |
|    * and calling its <code>init</code> method.</p>
 | |
|    *
 | |
|    * @param opmode      The operation mode to use.
 | |
|    * @param certificate The certificate.
 | |
|    * @param random      The source of randomness.
 | |
|    * @throws java.security.InvalidKeyException If the underlying cipher
 | |
|    *         instance rejects the certificate's public key, or if the
 | |
|    *         public key cannot be used as described above.
 | |
|    */
 | |
|   public final void
 | |
|   init(int opmode, Certificate certificate, SecureRandom random)
 | |
|   throws InvalidKeyException
 | |
|   {
 | |
|     if (certificate instanceof X509Certificate)
 | |
|       {
 | |
|         boolean[] keyInfo = ((X509Certificate) certificate).getKeyUsage();
 | |
|         if (keyInfo != null)
 | |
|           {
 | |
|             switch (opmode)
 | |
|               {
 | |
|               case DECRYPT_MODE:
 | |
|                 if (!keyInfo[3])
 | |
|                   {
 | |
|                     throw new InvalidKeyException(
 | |
|                       "the certificate's key cannot be used for transforming data");
 | |
|                   }
 | |
|                 if (keyInfo[7])
 | |
|                   {
 | |
|                     throw new InvalidKeyException(
 | |
|                       "the certificate's key can only be used for encryption");
 | |
|                   }
 | |
|                 break;
 | |
| 
 | |
|               case ENCRYPT_MODE:
 | |
|                 if (!keyInfo[3])
 | |
|                   {
 | |
|                     throw new InvalidKeyException(
 | |
|                       "the certificate's key cannot be used for transforming data");
 | |
|                   }
 | |
|                 if (keyInfo[8])
 | |
|                   {
 | |
|                     throw new InvalidKeyException(
 | |
|                       "the certificate's key can only be used for decryption");
 | |
|                   }
 | |
|                 break;
 | |
| 
 | |
|               case UNWRAP_MODE:
 | |
|                 if (!keyInfo[2] || keyInfo[7])
 | |
|                   {
 | |
|                     throw new InvalidKeyException(
 | |
|                       "the certificate's key cannot be used for key unwrapping");
 | |
|                   }
 | |
|                 break;
 | |
| 
 | |
|               case WRAP_MODE:
 | |
|                 if (!keyInfo[2] || keyInfo[8])
 | |
|                   {
 | |
|                     throw new InvalidKeyException(
 | |
|                       "the certificate's key cannot be used for key wrapping");
 | |
|                   }
 | |
|                 break;
 | |
|               }
 | |
|           }
 | |
|       }
 | |
|     init(opmode, certificate.getPublicKey(), random);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <p>Initialize this cipher with the supplied key and source of
 | |
|    * randomness.</p>
 | |
|    *
 | |
|    * <p>The cipher will be initialized for encryption, decryption, key
 | |
|    * wrapping, or key unwrapping, depending upon whether the
 | |
|    * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link
 | |
|    * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE},
 | |
|    * respectively.</p>
 | |
|    *
 | |
|    * <p>A call to any of the <code>init</code> methods overrides the
 | |
|    * state of the instance, and is equivalent to creating a new instance
 | |
|    * and calling its <code>init</code> method.</p>
 | |
|    *
 | |
|    * @param opmode The operation mode to use.
 | |
|    * @param key    The key.
 | |
|    * @param random The source of randomness to use.
 | |
|    * @throws java.security.InvalidKeyException If the underlying cipher
 | |
|    *         instance rejects the given key.
 | |
|    */
 | |
|   public final void init(int opmode, Key key, SecureRandom random)
 | |
|     throws InvalidKeyException
 | |
|   {
 | |
|     if (cipherSpi != null)
 | |
|       {
 | |
|         cipherSpi.engineInit(opmode, key, random);
 | |
|       }
 | |
|     state = opmode;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <p>Initialize this cipher with the supplied key and parameters.</p>
 | |
|    *
 | |
|    * <p>The cipher will be initialized for encryption, decryption, key
 | |
|    * wrapping, or key unwrapping, depending upon whether the
 | |
|    * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link
 | |
|    * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE},
 | |
|    * respectively.</p>
 | |
|    *
 | |
|    * <p>If this cipher requires any random bytes (for example for an
 | |
|    * initilization vector) then the {@link java.security.SecureRandom}
 | |
|    * with the highest priority is used as the source of these bytes.</p>
 | |
|    *
 | |
|    * <p>A call to any of the <code>init</code> methods overrides the
 | |
|    * state of the instance, and is equivalent to creating a new instance
 | |
|    * and calling its <code>init</code> method.</p>
 | |
|    *
 | |
|    * @param opmode The operation mode to use.
 | |
|    * @param key    The key.
 | |
|    * @param params The algorithm parameters to initialize this instance
 | |
|    *               with.
 | |
|    * @throws java.security.InvalidKeyException If the underlying cipher
 | |
|    *         instance rejects the given key.
 | |
|    * @throws java.security.InvalidAlgorithmParameterException If the
 | |
|    *         supplied parameters are inappropriate for this cipher.
 | |
|    */
 | |
|   public final void init(int opmode, Key key, AlgorithmParameters params)
 | |
|     throws InvalidKeyException, InvalidAlgorithmParameterException
 | |
|   {
 | |
|     init(opmode, key, params, new SecureRandom());
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <p>Initialize this cipher with the supplied key and parameters.</p>
 | |
|    *
 | |
|    * <p>The cipher will be initialized for encryption, decryption, key
 | |
|    * wrapping, or key unwrapping, depending upon whether the
 | |
|    * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link
 | |
|    * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE},
 | |
|    * respectively.</p>
 | |
|    *
 | |
|    * <p>If this cipher requires any random bytes (for example for an
 | |
|    * initilization vector) then the {@link java.security.SecureRandom}
 | |
|    * with the highest priority is used as the source of these bytes.</p>
 | |
|    *
 | |
|    * <p>A call to any of the <code>init</code> methods overrides the
 | |
|    * state of the instance, and is equivalent to creating a new instance
 | |
|    * and calling its <code>init</code> method.</p>
 | |
|    *
 | |
|    * @param opmode The operation mode to use.
 | |
|    * @param key    The key.
 | |
|    * @param params The algorithm parameters to initialize this instance
 | |
|    *               with.
 | |
|    * @throws java.security.InvalidKeyException If the underlying cipher
 | |
|    *         instance rejects the given key.
 | |
|    * @throws java.security.InvalidAlgorithmParameterException If the
 | |
|    *         supplied parameters are inappropriate for this cipher.
 | |
|    */
 | |
|   public final void init(int opmode, Key key, AlgorithmParameterSpec params)
 | |
|     throws InvalidKeyException, InvalidAlgorithmParameterException
 | |
|   {
 | |
|     init(opmode, key, params, new SecureRandom());
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <p>Initialize this cipher with the supplied key, parameters, and
 | |
|    * source of randomness.</p>
 | |
|    *
 | |
|    * <p>The cipher will be initialized for encryption, decryption, key
 | |
|    * wrapping, or key unwrapping, depending upon whether the
 | |
|    * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link
 | |
|    * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE},
 | |
|    * respectively.</p>
 | |
|    *
 | |
|    * <p>A call to any of the <code>init</code> methods overrides the
 | |
|    * state of the instance, and is equivalent to creating a new instance
 | |
|    * and calling its <code>init</code> method.</p>
 | |
|    *
 | |
|    * @param opmode The operation mode to use.
 | |
|    * @param key    The key.
 | |
|    * @param params The algorithm parameters to initialize this instance
 | |
|    *               with.
 | |
|    * @param random The source of randomness to use.
 | |
|    * @throws java.security.InvalidKeyException If the underlying cipher
 | |
|    *         instance rejects the given key.
 | |
|    * @throws java.security.InvalidAlgorithmParameterException If the
 | |
|    *         supplied parameters are inappropriate for this cipher.
 | |
|    */
 | |
|   public final void init(int opmode, Key key, AlgorithmParameters params,
 | |
|                          SecureRandom random)
 | |
|     throws InvalidKeyException, InvalidAlgorithmParameterException
 | |
|   {
 | |
|     if (cipherSpi != null)
 | |
|       {
 | |
|         cipherSpi.engineInit(opmode, key, params, random);
 | |
|       }
 | |
|     state = opmode;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <p>Initialize this cipher with the supplied key, parameters, and
 | |
|    * source of randomness.</p>
 | |
|    *
 | |
|    * <p>The cipher will be initialized for encryption, decryption, key
 | |
|    * wrapping, or key unwrapping, depending upon whether the
 | |
|    * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link
 | |
|    * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE},
 | |
|    * respectively.</p>
 | |
|    *
 | |
|    * <p>A call to any of the <code>init</code> methods overrides the
 | |
|    * state of the instance, and is equivalent to creating a new instance
 | |
|    * and calling its <code>init</code> method.</p>
 | |
|    *
 | |
|    * @param opmode The operation mode to use.
 | |
|    * @param key    The key.
 | |
|    * @param params The algorithm parameters to initialize this instance
 | |
|    *               with.
 | |
|    * @param random The source of randomness to use.
 | |
|    * @throws java.security.InvalidKeyException If the underlying cipher
 | |
|    *         instance rejects the given key.
 | |
|    * @throws java.security.InvalidAlgorithmParameterException If the
 | |
|    *         supplied parameters are inappropriate for this cipher.
 | |
|    */
 | |
|   public final void init(int opmode, Key key, AlgorithmParameterSpec params,
 | |
|                          SecureRandom random)
 | |
|     throws InvalidKeyException, InvalidAlgorithmParameterException
 | |
|   {
 | |
|     if (cipherSpi != null)
 | |
|       {
 | |
|         cipherSpi.engineInit(opmode, key, params, random);
 | |
|       }
 | |
|     state = opmode;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Unwrap a previously-wrapped key.
 | |
|    *
 | |
|    * @param wrappedKey          The wrapped key.
 | |
|    * @param wrappedKeyAlgorithm The algorithm with which the key was
 | |
|    *        wrapped.
 | |
|    * @param wrappedKeyType      The type of key (public, private, or
 | |
|    *        secret) that this wrapped key respresents.
 | |
|    * @return The unwrapped key.
 | |
|    * @throws java.lang.IllegalStateException If this instance has not be
 | |
|    *         initialized for unwrapping.
 | |
|    * @throws java.security.InvalidKeyException If <code>wrappedKey</code>
 | |
|    *         is not a wrapped key, if the algorithm cannot unwrap this
 | |
|    *         key, or if the unwrapped key's type differs from the
 | |
|    *         specified type.
 | |
|    * @throws java.security.NoSuchAlgorithmException If
 | |
|    *         <code>wrappedKeyAlgorithm</code> is not a valid algorithm
 | |
|    *         name.
 | |
|    */
 | |
|   public final Key unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
 | |
|                           int wrappedKeyType)
 | |
|     throws IllegalStateException, InvalidKeyException, NoSuchAlgorithmException
 | |
|   {
 | |
|     if (cipherSpi == null)
 | |
|       {
 | |
|         return null;
 | |
|       }
 | |
|     if (state != UNWRAP_MODE)
 | |
|       {
 | |
|         throw new IllegalStateException("instance is not for unwrapping");
 | |
|       }
 | |
|     return cipherSpi.engineUnwrap(wrappedKey, wrappedKeyAlgorithm,
 | |
|                                   wrappedKeyType);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Continue a multi-part transformation on an entire byte array,
 | |
|    * returning the transformed bytes.
 | |
|    *
 | |
|    * @param input The input bytes.
 | |
|    * @return The transformed bytes.
 | |
|    * @throws java.lang.IllegalStateException If this cipher was not
 | |
|    *         initialized for encryption or decryption.
 | |
|    */
 | |
|   public final byte[] update(byte[] input) throws IllegalStateException
 | |
|   {
 | |
|     return update(input, 0, input.length);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Continue a multi-part transformation on part of a byte array,
 | |
|    * returning the transformed bytes.
 | |
|    *
 | |
|    * @param input       The input bytes.
 | |
|    * @param inputOffset The index in the input to start.
 | |
|    * @param inputLength The number of bytes to transform.
 | |
|    * @return The transformed bytes.
 | |
|    * @throws java.lang.IllegalStateException If this cipher was not
 | |
|    *         initialized for encryption or decryption.
 | |
|    */
 | |
|   public final byte[] update(byte[] input, int inputOffset, int inputLength)
 | |
|     throws IllegalStateException
 | |
|   {
 | |
|     if (cipherSpi == null)
 | |
|       {
 | |
|         byte[] b = new byte[inputLength];
 | |
|         System.arraycopy(input, inputOffset, b, 0, inputLength);
 | |
|         return b;
 | |
|       }
 | |
|     if (state != ENCRYPT_MODE && state != DECRYPT_MODE)
 | |
|       {
 | |
|         throw new IllegalStateException(
 | |
|           "cipher is not for encrypting or decrypting");
 | |
|       }
 | |
|     return cipherSpi.engineUpdate(input, inputOffset, inputLength);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Continue a multi-part transformation on part of a byte array,
 | |
|    * placing the transformed bytes into the given array.
 | |
|    *
 | |
|    * @param input       The input bytes.
 | |
|    * @param inputOffset The index in the input to start.
 | |
|    * @param inputLength The number of bytes to transform.
 | |
|    * @param output      The output byte array.
 | |
|    * @return The number of transformed bytes.
 | |
|    * @throws java.lang.IllegalStateException If this cipher was not
 | |
|    *         initialized for encryption or decryption.
 | |
|    * @throws javax.security.ShortBufferException If there is not enough
 | |
|    *         room in the output array to hold the transformed bytes.
 | |
|    */
 | |
|   public final int update(byte[] input, int inputOffset, int inputLength,
 | |
|                           byte[] output)
 | |
|     throws IllegalStateException, ShortBufferException
 | |
|   {
 | |
|     return update(input, inputOffset, inputLength, output, 0);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Continue a multi-part transformation on part of a byte array,
 | |
|    * placing the transformed bytes into the given array.
 | |
|    *
 | |
|    * @param input        The input bytes.
 | |
|    * @param inputOffset  The index in the input to start.
 | |
|    * @param inputLength  The number of bytes to transform.
 | |
|    * @param output       The output byte array.
 | |
|    * @param outputOffset The index in the output array to start.
 | |
|    * @return The number of transformed bytes.
 | |
|    * @throws java.lang.IllegalStateException If this cipher was not
 | |
|    *         initialized for encryption or decryption.
 | |
|    * @throws javax.security.ShortBufferException If there is not enough
 | |
|    *         room in the output array to hold the transformed bytes.
 | |
|    */
 | |
|   public final int update(byte[] input, int inputOffset, int inputLength,
 | |
|                           byte[] output, int outputOffset)
 | |
|     throws IllegalStateException, ShortBufferException
 | |
|   {
 | |
|     if (cipherSpi == null)
 | |
|       {
 | |
|         if (inputLength > output.length - outputOffset)
 | |
|           {
 | |
|             throw new ShortBufferException();
 | |
|           }
 | |
|         System.arraycopy(input, inputOffset, output, outputOffset, inputLength);
 | |
|         return inputLength;
 | |
|       }
 | |
|     if (state != ENCRYPT_MODE && state != DECRYPT_MODE)
 | |
|       {
 | |
|         throw new IllegalStateException(
 | |
|           "cipher is not for encrypting or decrypting");
 | |
|       }
 | |
|     return cipherSpi.engineUpdate(input, inputOffset, inputLength,
 | |
|                                   output, outputOffset);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Continue a multi-part transformation on a byte buffer, storing
 | |
|    * the transformed bytes into another buffer.
 | |
|    *
 | |
|    * @param input  The input buffer.
 | |
|    * @param output The output buffer.
 | |
|    * @return The number of bytes stored in <i>output</i>.
 | |
|    * @throws IllegalArgumentException If the two buffers are the same
 | |
|    *  object.
 | |
|    * @throws IllegalStateException If this cipher was not initialized
 | |
|    *  for encrypting or decrypting.
 | |
|    * @throws ReadOnlyBufferException If the output buffer is not
 | |
|    *  writable.
 | |
|    * @throws ShortBufferException If the output buffer does not have
 | |
|    *  enough available space for the transformed bytes.
 | |
|    * @since 1.5
 | |
|    */
 | |
|   public final int update (ByteBuffer input, ByteBuffer output)
 | |
|     throws ReadOnlyBufferException, ShortBufferException
 | |
|   {
 | |
|     if (input == output)
 | |
|       throw new IllegalArgumentException
 | |
|         ("input and output buffers must be different");
 | |
|     if (state != ENCRYPT_MODE && state != DECRYPT_MODE)
 | |
|       throw new IllegalStateException
 | |
|         ("not initialized for encryption or decryption");
 | |
|     return cipherSpi.engineUpdate (input, output);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Wrap a key.
 | |
|    *
 | |
|    * @param key The key to wrap.
 | |
|    * @return The wrapped key.
 | |
|    * @throws java.lang.IllegalStateException If this instance was not
 | |
|    *         initialized for key wrapping.
 | |
|    * @throws javax.crypto.IllegalBlockSizeException If this instance has
 | |
|    *         no padding and the key is not a multiple of the block size.
 | |
|    * @throws java.security.InvalidKeyException If this instance cannot
 | |
|    *         wrap this key.
 | |
|    */
 | |
|   public final byte[] wrap(Key key)
 | |
|     throws IllegalStateException, IllegalBlockSizeException, InvalidKeyException
 | |
|   {
 | |
|     if (cipherSpi == null)
 | |
|       {
 | |
|         return null;
 | |
|       }
 | |
|     if (state != WRAP_MODE)
 | |
|       {
 | |
|         throw new IllegalStateException("instance is not for key wrapping");
 | |
|       }
 | |
|     return cipherSpi.engineWrap(key);
 | |
|   }
 | |
| }
 |