aboutsummaryrefslogtreecommitdiffstats
path: root/libraries/spongycastle/jce/src/main/java/javax/crypto/Cipher.java
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/spongycastle/jce/src/main/java/javax/crypto/Cipher.java')
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/Cipher.java1509
1 files changed, 1509 insertions, 0 deletions
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/Cipher.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/Cipher.java
new file mode 100644
index 000000000..bf9fd3743
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/Cipher.java
@@ -0,0 +1,1509 @@
+package javax.crypto;
+
+import java.util.StringTokenizer;
+import java.security.Key;
+import java.security.Provider;
+import java.security.SecureRandom;
+import java.security.AlgorithmParameters;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.cert.Certificate;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * This class provides the functionality of a cryptographic cipher for
+ * encryption and decryption. It forms the core of the Java Cryptographic
+ * Extension (JCE) framework.
+ * <p>
+ * In order to create a Cipher object, the application calls the
+ * Cipher's <code>getInstance</code> method, and passes the name of the
+ * requested <i>transformation</i> to it. Optionally, the name of a provider
+ * may be specified.
+ * <p>
+ * A <i>transformation</i> is a string that describes the operation (or
+ * set of operations) to be performed on the given input, to produce some
+ * output. A transformation always includes the name of a cryptographic
+ * algorithm (e.g., <i>DES</i>), and may be followed by a feedback mode and
+ * padding scheme.
+ *
+ * <p> A transformation is of the form:<p>
+ *
+ * <ul>
+ * <li>"<i>algorithm/mode/padding</i>" or
+ * <p>
+ * <li>"<i>algorithm</i>"
+ * </ul>
+ *
+ * <P> (in the latter case,
+ * provider-specific default values for the mode and padding scheme are used).
+ * For example, the following is a valid transformation:<p>
+ *
+ * <pre>
+ * Cipher c = Cipher.getInstance("<i>DES/CBC/PKCS5Padding</i>");
+ * </pre>
+ * <p>
+ * When requesting a block cipher in stream cipher mode (e.g.,
+ * <code>DES</code> in <code>CFB</code> or <code>OFB</code> mode), the user may
+ * optionally specify the number of bits to be
+ * processed at a time, by appending this number to the mode name as shown in
+ * the "<i>DES/CFB8/NoPadding</i>" and "<i>DES/OFB32/PKCS5Padding</i>"
+ * transformations. If no such number is specified, a provider-specific default
+ * is used. (For example, the "SunJCE" provider uses a default of 64 bits.)
+ */
+public class Cipher
+{
+ static private final int UNINITIALIZED = 0;
+
+ static public final int ENCRYPT_MODE = 1;
+ static public final int DECRYPT_MODE = 2;
+ static public final int WRAP_MODE = 3;
+ static public final int UNWRAP_MODE = 4;
+
+ static public final int PUBLIC_KEY = 1;
+ static public final int PRIVATE_KEY = 2;
+ static public final int SECRET_KEY = 3;
+
+ private CipherSpi cipherSpi;
+ private Provider provider;
+ private String transformation;
+
+ private int mode = UNINITIALIZED;
+
+ /**
+ * Creates a Cipher object.
+ *
+ * @param cipherSpi the delegate
+ * @param provider the provider
+ * @param transformation the transformation
+ */
+ protected Cipher(
+ CipherSpi cipherSpi,
+ Provider provider,
+ String transformation)
+ {
+ this.cipherSpi = cipherSpi;
+ this.provider = provider;
+ this.transformation = transformation;
+ }
+
+ /**
+ * Generates a <code>Cipher</code> object that implements the specified
+ * transformation.
+ * <p>
+ * If the default provider package supplies an implementation of the
+ * requested transformation, an instance of <code>Cipher</code> containing
+ * that implementation is returned.
+ * If the transformation is not available in the default provider package,
+ * other provider packages are searched.
+ *
+ * @param transformation the name of the transformation, e.g., <i>DES/CBC/PKCS5Padding</i>.
+ * See Appendix A in the Java Cryptography Extension API Specification &amp; Reference
+ * for information about standard transformation names.
+ *
+ * @return a cipher that implements the requested transformation
+ * @exception NoSuchAlgorithmException if the specified transformation is not available in the default
+ * provider package or any of the other provider packages that were searched.
+ * @exception NoSuchPaddingException if <code>transformation</code> contains a padding scheme that is
+ * not available.
+ */
+ public static final Cipher getInstance(
+ String transformation)
+ throws NoSuchAlgorithmException, NoSuchPaddingException
+ {
+ try
+ {
+ JCEUtil.Implementation imp = JCEUtil.getImplementation("Cipher", transformation, (String) null);
+
+ if (imp != null)
+ {
+ return new Cipher((CipherSpi)imp.getEngine(), imp.getProvider(), transformation);
+ }
+
+ //
+ // try the long way
+ //
+ StringTokenizer tok = new StringTokenizer(transformation, "/");
+ String algorithm = tok.nextToken();
+
+ imp = JCEUtil.getImplementation("Cipher", algorithm, (String) null);
+
+ if (imp == null)
+ {
+ throw new NoSuchAlgorithmException(transformation + " not found");
+ }
+
+ CipherSpi cipherSpi = (CipherSpi)imp.getEngine();
+
+ //
+ // make sure we don't get fooled by a "//" in the string
+ //
+ if (tok.hasMoreTokens() && !transformation.regionMatches(algorithm.length(), "//", 0, 2))
+ {
+ cipherSpi.engineSetMode(tok.nextToken());
+ }
+
+ if (tok.hasMoreTokens())
+ {
+ cipherSpi.engineSetPadding(tok.nextToken());
+ }
+
+ return new Cipher(cipherSpi, imp.getProvider(), transformation);
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new NoSuchAlgorithmException(transformation + " not found");
+ }
+ }
+
+ /**
+ * Creates a <code>Cipher</code> object that implements the specified
+ * transformation, as supplied by the specified provider.
+ *
+ * @param transformation the name of the transformation, e.g., <i>DES/CBC/PKCS5Padding</i>.
+ * See Appendix A in the Java Cryptography Extension API Specification &amp; Reference
+ * for information about standard transformation names.
+ *
+ * @param provider the provider
+ * @return a cipher that implements the requested transformation
+ * @exception NoSuchAlgorithmException if no transformation was specified, or if the specified
+ * transformation is not available from the specified provider.
+ * @exception NoSuchPaddingException if <code>transformation</code> contains a padding scheme
+ * that is not available.
+ */
+ public static final Cipher getInstance(
+ String transformation,
+ Provider provider)
+ throws NoSuchAlgorithmException, NoSuchPaddingException
+ {
+ if (transformation == null)
+ {
+ throw new IllegalArgumentException("No transformation specified for Cipher.getInstance()");
+ }
+
+ JCEUtil.Implementation imp = JCEUtil.getImplementation("Cipher", transformation, provider);
+
+ if (imp != null)
+ {
+ return new Cipher((CipherSpi)imp.getEngine(), imp.getProvider(), transformation);
+ }
+
+ //
+ // try the long way
+ //
+ StringTokenizer tok = new StringTokenizer(transformation, "/");
+ String algorithm = tok.nextToken();
+
+ imp = JCEUtil.getImplementation("Cipher", algorithm, provider);
+
+ if (imp == null)
+ {
+ throw new NoSuchAlgorithmException(transformation + " not found");
+ }
+
+ CipherSpi cipherSpi = (CipherSpi)imp.getEngine();
+
+ //
+ // make sure we don't get fooled by a "//" in the string
+ //
+ if (tok.hasMoreTokens() && !transformation.regionMatches(algorithm.length(), "//", 0, 2))
+ {
+ cipherSpi.engineSetMode(tok.nextToken());
+ }
+
+ if (tok.hasMoreTokens())
+ {
+ cipherSpi.engineSetPadding(tok.nextToken());
+ }
+
+ return new Cipher(cipherSpi, imp.getProvider(), transformation);
+ }
+
+ /**
+ * Creates a <code>Cipher</code> object that implements the specified
+ * transformation, as supplied by the specified provider.
+ *
+ * @param transformation the name of the transformation, e.g., <i>DES/CBC/PKCS5Padding</i>.
+ * See Appendix A in the Java Cryptography Extension API Specification &amp; Reference
+ * for information about standard transformation names.
+ *
+ * @param provider the name of the provider
+ * @return a cipher that implements the requested transformation
+ * @exception NoSuchAlgorithmException if no transformation was specified, or if the specified
+ * transformation is not available from the specified provider.
+ * @exception NoSuchProviderException if the specified provider has not been configured.
+ * @exception NoSuchPaddingException if <code>transformation</code> contains a padding scheme
+ * that is not available.
+ */
+ public static final Cipher getInstance(
+ String transformation,
+ String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException
+ {
+ if (transformation == null)
+ {
+ throw new IllegalArgumentException("No transformation specified for Cipher.getInstance()");
+ }
+
+ JCEUtil.Implementation imp = JCEUtil.getImplementation("Cipher", transformation, provider);
+
+ if (imp != null)
+ {
+ return new Cipher((CipherSpi)imp.getEngine(), imp.getProvider(), transformation);
+ }
+
+ //
+ // try the long way
+ //
+ StringTokenizer tok = new StringTokenizer(transformation, "/");
+ String algorithm = tok.nextToken();
+
+ imp = JCEUtil.getImplementation("Cipher", algorithm, provider);
+
+ if (imp == null)
+ {
+ throw new NoSuchAlgorithmException(transformation + " not found");
+ }
+
+ CipherSpi cipherSpi = (CipherSpi)imp.getEngine();
+
+ //
+ // make sure we don't get fooled by a "//" in the string
+ //
+ if (tok.hasMoreTokens() && !transformation.regionMatches(algorithm.length(), "//", 0, 2))
+ {
+ cipherSpi.engineSetMode(tok.nextToken());
+ }
+
+ if (tok.hasMoreTokens())
+ {
+ cipherSpi.engineSetPadding(tok.nextToken());
+ }
+
+ return new Cipher(cipherSpi, imp.getProvider(), transformation);
+ }
+
+ /**
+ * Returns the provider of this <code>Cipher</code> object.
+ *
+ * @return the provider of this <code>Cipher</code> object
+ */
+ public final Provider getProvider()
+ {
+ return provider;
+ }
+
+ /**
+ * Returns the algorithm name of this <code>Cipher</code> object.
+ * <p>
+ * This is the same name that was specified in one of the
+ * <code>getInstance</code> calls that created this <code>Cipher</code>
+ * object..
+ *
+ * @return the algorithm name of this <code>Cipher</code> object.
+ */
+ public final String getAlgorithm()
+ {
+ return transformation;
+ }
+
+ /**
+ * Returns the block size (in bytes).
+ *
+ * @return the block size (in bytes), or 0 if the underlying algorithm is not a block cipher
+ */
+ public final int getBlockSize()
+ {
+ return cipherSpi.engineGetBlockSize();
+ }
+
+ /**
+ * Returns the length in bytes that an output buffer would need to be in
+ * order to hold the result of the next <code>update</code> or
+ * <code>doFinal</code> operation, given the input length <code>inputLen</code> (in bytes).
+ * <p>
+ * This call takes into account any unprocessed (buffered) data from a
+ * previous <code>update</code> call, and padding.
+ * <p>
+ * The actual output length of the next <code>update</code> or
+ * <code>doFinal</code> call may be smaller than the length returned by
+ * this method.
+ *
+ * @param inputLen the input length (in bytes)
+ * @return the required output buffer size (in bytes)
+ * @exception java.lang.IllegalStateException if this cipher is in a wrong state (e.g., has not
+ * yet been initialized)
+ */
+ public final int getOutputSize(
+ int inputLen)
+ throws IllegalStateException
+ {
+ if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE)
+ {
+ throw new IllegalStateException("Cipher is uninitialised");
+ }
+
+ return cipherSpi.engineGetOutputSize(inputLen);
+ }
+
+ /**
+ * Returns the initialization vector (IV) in a new buffer.
+ * <p>
+ * This is useful in the case where a random IV was created,
+ * or in the context of password-based encryption or decryption, where the IV
+ * is derived from a user-supplied password.
+ *
+ * @return the initialization vector in a new buffer, or null if the
+ * underlying algorithm does not use an IV, or if the IV has not yet been set.
+ */
+ public final byte[] getIV()
+ {
+ return cipherSpi.engineGetIV();
+ }
+
+ /**
+ * Returns the parameters used with this cipher.
+ * <p>
+ * The returned parameters may be the same that were used to initialize
+ * this cipher, or may contain a combination of default and random
+ * parameter values used by the underlying cipher implementation if this
+ * cipher requires algorithm parameters but was not initialized with any.
+ *
+ * @return the parameters used with this cipher, or null if this cipher
+ * does not use any parameters.
+ */
+ public final AlgorithmParameters getParameters()
+ {
+ return cipherSpi.engineGetParameters();
+ }
+
+ /**
+ * Returns the exemption mechanism object used with this cipher.
+ *
+ * @return the exemption mechanism object used with this cipher, or
+ * null if this cipher does not use any exemption mechanism.
+ */
+ public final ExemptionMechanism getExemptionMechanism()
+ {
+ return null;
+ }
+
+ /**
+ * Initializes this cipher with a key.
+ * <p>
+ * The cipher is initialized for one of the following four operations:
+ * encryption, decryption, key wrapping or key unwrapping, depending
+ * on the value of <code>opmode</code>.
+ * <p>
+ * If this cipher requires any algorithm parameters that cannot be
+ * derived from the given <code>key</code>, the underlying cipher
+ * implementation is supposed to generate the required parameters itself
+ * (using provider-specific default or random values) if it is being
+ * initialized for encryption or key wrapping, and raise an
+ * <code>InvalidKeyException</code> if it is being
+ * initialized for decryption or key unwrapping.
+ * The generated parameters can be retrieved using
+ * <a href = "#getParameters()">getParameters</a> or
+ * <a href = "#getIV()">getIV</a> (if the parameter is an IV).
+ * <p>
+ * If this cipher (including its underlying feedback or padding scheme)
+ * requires any random bytes (e.g., for parameter generation), it will get
+ * them using the <a href="http://java.sun.com/products/jdk/1.2/docs/api/java.security.SecureRandom.html">
+ * <code>SecureRandom</code></a> implementation of the highest-priority
+ * installed provider as the source of randomness.
+ * (If none of the installed providers supply an implementation of
+ * SecureRandom, a system-provided source of randomness will be used.)
+ * <p>
+ * Note that when a Cipher object is initialized, it loses all
+ * previously-acquired state. In other words, initializing a Cipher is
+ * equivalent to creating a new instance of that Cipher and initializing
+ * it.
+ *
+ * @param opmode the operation mode of this cipher (this is one of the following:
+ * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
+ * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
+ * @param key the key
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * initializing this cipher, or if this cipher is being initialized for
+ * decryption and requires algorithm parameters that cannot be
+ * determined from the given key, or if the given key has a keysize that
+ * exceeds the maximum allowable keysize (as determined from the
+ * configured jurisdiction policy files). Note: Jurisdiction files are ignored
+ * in this implementation.
+ */
+ public final void init(
+ int opmode,
+ Key key)
+ throws InvalidKeyException
+ {
+ cipherSpi.engineInit(opmode, key, new SecureRandom());
+ mode = opmode;
+ }
+
+ /**
+ * Initializes this cipher with a key and a source of randomness.
+ * <p>
+ * The cipher is initialized for one of the following four operations:
+ * encryption, decryption, key wrapping or key unwrapping, depending
+ * on the value of <code>opmode</code>.
+ * <p>
+ * If this cipher requires any algorithm parameters that cannot be
+ * derived from the given <code>key</code>, the underlying cipher
+ * implementation is supposed to generate the required parameters itself
+ * (using provider-specific default or random values) if it is being
+ * initialized for encryption or key wrapping, and raise an
+ * <code>InvalidKeyException</code> if it is being
+ * initialized for decryption or key unwrapping.
+ * The generated parameters can be retrieved using
+ * <a href = "#engineGetParameters()">engineGetParameters</a> or
+ * <a href = "#engineGetIV()">engineGetIV</a> (if the parameter is an IV).
+ * <p>
+ * If this cipher (including its underlying feedback or padding scheme)
+ * requires any random bytes (e.g., for parameter generation), it will get
+ * them from <code>random</code>.
+ * <p>
+ * Note that when a Cipher object is initialized, it loses all
+ * previously-acquired state. In other words, initializing a Cipher is
+ * equivalent to creating a new instance of that Cipher and initializing
+ * it.
+ * @param opmode the operation mode of this cipher (this is one of the
+ * following: <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
+ * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
+ * @param key the encryption key
+ * @param random the source of randomness
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * initializing this cipher, or if this cipher is being initialized for
+ * decryption and requires algorithm parameters that cannot be
+ * determined from the given key, or if the given key has a keysize that
+ * exceeds the maximum allowable keysize (as determined from the
+ * configured jurisdiction policy files). Note: Jurisdiction files are ignored
+ * in this implementation.
+ */
+ public final void init(
+ int opmode,
+ Key key,
+ SecureRandom random)
+ throws InvalidKeyException
+ {
+ cipherSpi.engineInit(opmode, key, random);
+ mode = opmode;
+ }
+
+ /**
+ * Initializes this cipher with a key and a set of algorithm parameters.
+ * <p>
+ * The cipher is initialized for one of the following four operations:
+ * encryption, decryption, key wrapping or key unwrapping, depending
+ * on the value of <code>opmode</code>.
+ * <p>
+ * If this cipher requires any algorithm parameters and
+ * <code>params</code> is null, the underlying cipher implementation is
+ * supposed to generate the required parameters itself (using
+ * provider-specific default or random values) if it is being
+ * initialized for encryption or key wrapping, and raise an
+ * <code>InvalidAlgorithmParameterException</code> if it is being
+ * initialized for decryption or key unwrapping.
+ * The generated parameters can be retrieved using
+ * <a href = "#getParameters()">getParameters</a> or
+ * <a href = "#getIV()">getIV</a> (if the parameter is an IV).
+ * <p>
+ * If this cipher (including its underlying feedback or padding scheme)
+ * requires any random bytes (e.g., for parameter generation), it will get
+ * them using the
+ * <a href="http://java.sun.com/products/jdk/1.2/docs/api/java.security.SecureRandom.html">
+ * <code>SecureRandom</code></a> implementation of the highest-priority
+ * installed provider as the source of randomness.
+ * (If none of the installed providers supply an implementation of
+ * SecureRandom, a system-provided source of randomness will be used.)
+ * <p>
+ * Note that when a Cipher object is initialized, it loses all
+ * previously-acquired state. In other words, initializing a Cipher is
+ * equivalent to creating a new instance of that Cipher and initializing
+ * it.
+ *
+ * @param opmode the operation mode of this cipher (this is one of the
+ * following: <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>, <code>WRAP_MODE</code>
+ * or <code>UNWRAP_MODE</code>)
+ * @param key the encryption key
+ * @param params the algorithm parameters
+ * @exception InvalidKeyException if the given key is inappropriate for initializing this
+ * cipher, or its keysize exceeds the maximum allowable keysize (as determined from the
+ * configured jurisdiction policy files).
+ * @exception InvalidAlgorithmParameterException if the given algorithm parameters are
+ * inappropriate for this cipher, or this cipher is being initialized for decryption and
+ * requires algorithm parameters and <code>params</code> is null, or the given algorithm
+ * parameters imply a cryptographic strength that would exceed the legal limits (as determined
+ * from the configured jurisdiction policy files). Note: Jurisdiction files are ignored
+ * in this implementation.
+ */
+ public final void init(
+ int opmode,
+ Key key,
+ AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ cipherSpi.engineInit(opmode, key, params, new SecureRandom());
+ mode = opmode;
+ }
+
+ /**
+ * Initializes this cipher with a key, a set of algorithm
+ * parameters, and a source of randomness.
+ * <p>
+ * The cipher is initialized for one of the following four operations:
+ * encryption, decryption, key wrapping or key unwrapping, depending
+ * on the value of <code>opmode</code>.
+ * <p>
+ * If this cipher requires any algorithm parameters and
+ * <code>params</code> is null, the underlying cipher implementation is
+ * supposed to generate the required parameters itself (using
+ * provider-specific default or random values) if it is being
+ * initialized for encryption or key wrapping, and raise an
+ * <code>InvalidAlgorithmParameterException</code> if it is being
+ * initialized for decryption or key unwrapping.
+ * The generated parameters can be retrieved using
+ * <a href = "#getParameters()">getParameters</a> or
+ * <a href = "#getIV()">getIV</a> (if the parameter is an IV).
+ * <p>
+ * If this cipher (including its underlying feedback or padding scheme)
+ * requires any random bytes (e.g., for parameter generation), it will get
+ * them from <code>random</code>.
+ * <p>
+ * Note that when a Cipher object is initialized, it loses all
+ * previously-acquired state. In other words, initializing a Cipher is
+ * equivalent to creating a new instance of that Cipher and initializing
+ * it.
+ *
+ * @param opmode the operation mode of this cipher (this is one of the
+ * following: <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
+ * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
+ * @param key the encryption key
+ * @param params the algorithm parameters
+ * @param random the source of randomness
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * initializing this cipher, or its keysize exceeds the maximum allowable
+ * keysize (as determined from the configured jurisdiction policy files).
+ * @exception InvalidAlgorithmParameterException if the given algorithm
+ * parameters are inappropriate for this cipher,
+ * or this cipher is being initialized for decryption and requires
+ * algorithm parameters and <code>params</code> is null, or the given
+ * algorithm parameters imply a cryptographic strength that would exceed
+ * the legal limits (as determined from the configured jurisdiction
+ * policy files).
+ * Note: Jurisdiction files are ignored in this implementation.
+ */
+ public final void init(
+ int opmode,
+ Key key,
+ AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ cipherSpi.engineInit(opmode, key, params, random);
+ mode = opmode;
+ }
+
+ /**
+ * Initializes this cipher with a key and a set of algorithm
+ * parameters.
+ * <p>
+ * The cipher is initialized for one of the following four operations:
+ * encryption, decryption, key wrapping or key unwrapping, depending
+ * on the value of <code>opmode</code>.
+ * <p>
+ * If this cipher requires any algorithm parameters and
+ * <code>params</code> is null, the underlying cipher implementation is
+ * supposed to generate the required parameters itself (using
+ * provider-specific default or random values) if it is being
+ * initialized for encryption or key wrapping, and raise an
+ * <code>InvalidAlgorithmParameterException</code> if it is being
+ * initialized for decryption or key unwrapping.
+ * The generated parameters can be retrieved using
+ * <a href = "#getParameters()">getParameters</a> or
+ * <a href = "#getIV()">getIV</a> (if the parameter is an IV).
+ * <p>
+ * If this cipher (including its underlying feedback or padding scheme)
+ * requires any random bytes (e.g., for parameter generation), it will get
+ * them using the
+ * <a href="http://java.sun.com/products/jdk/1.2/docs/api/java.security.SecureRandom.html">
+ * <code>SecureRandom</code></a> implementation of the highest-priority
+ * installed provider as the source of randomness.
+ * (If none of the installed providers supply an implementation of
+ * SecureRandom, a system-provided source of randomness will be used.)
+ * <p>
+ * Note that when a Cipher object is initialized, it loses all
+ * previously-acquired state. In other words, initializing a Cipher is
+ * equivalent to creating a new instance of that Cipher and initializing
+ * it.
+ *
+ * @param opmode the operation mode of this cipher (this is one of the
+ * following: <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>, <code>WRAP_MODE</code>
+ * or <code>UNWRAP_MODE</code>)
+ * @param key the encryption key
+ * @param params the algorithm parameters
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * initializing this cipher, or its keysize exceeds the maximum allowable
+ * keysize (as determined from the configured jurisdiction policy files).
+ * @exception InvalidAlgorithmParameterException if the given algorithm
+ * parameters are inappropriate for this cipher,
+ * or this cipher is being initialized for decryption and requires
+ * algorithm parameters and <code>params</code> is null, or the given
+ * algorithm parameters imply a cryptographic strength that would exceed
+ * the legal limits (as determined from the configured jurisdiction
+ * policy files).
+ * Note: Jurisdiction files are ignored in this implementation.
+ */
+ public final void init(
+ int opmode,
+ Key key,
+ AlgorithmParameters params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ cipherSpi.engineInit(opmode, key, params, new SecureRandom());
+ mode = opmode;
+ }
+
+ /**
+ * Initializes this cipher with a key, a set of algorithm
+ * parameters, and a source of randomness.
+ * <p>
+ * The cipher is initialized for one of the following four operations:
+ * encryption, decryption, key wrapping or key unwrapping, depending
+ * on the value of <code>opmode</code>.
+ * <p>
+ * If this cipher requires any algorithm parameters and
+ * <code>params</code> is null, the underlying cipher implementation is
+ * supposed to generate the required parameters itself (using
+ * provider-specific default or random values) if it is being
+ * initialized for encryption or key wrapping, and raise an
+ * <code>InvalidAlgorithmParameterException</code> if it is being
+ * initialized for decryption or key unwrapping.
+ * The generated parameters can be retrieved using
+ * <a href = "#getParameters()">getParameters</a> or
+ * <a href = "#getIV()">getIV</a> (if the parameter is an IV).
+ * <p>
+ * If this cipher (including its underlying feedback or padding scheme)
+ * requires any random bytes (e.g., for parameter generation), it will get
+ * them from <code>random</code>.
+ * <p>
+ * Note that when a Cipher object is initialized, it loses all
+ * previously-acquired state. In other words, initializing a Cipher is
+ * equivalent to creating a new instance of that Cipher and initializing
+ * it.
+ *
+ * @param opmode the operation mode of this cipher (this is one of the
+ * following: <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>, <code>WRAP_MODE</code>
+ * or <code>UNWRAP_MODE</code>)
+ * @param key the encryption key
+ * @param params the algorithm parameters
+ * @param random the source of randomness
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * initializing this cipher, or its keysize exceeds the maximum allowable
+ * keysize (as determined from the configured jurisdiction policy files).
+ * @exception InvalidAlgorithmParameterException if the given algorithm
+ * parameters are inappropriate for this cipher,
+ * or this cipher is being initialized for decryption and requires
+ * algorithm parameters and <code>params</code> is null, or the given
+ * algorithm parameters imply a cryptographic strength that would exceed
+ * the legal limits (as determined from the configured jurisdiction
+ * policy files).
+ * Note: Jurisdiction files are ignored in this implementation.
+ */
+ public final void init(
+ int opmode,
+ Key key,
+ AlgorithmParameters params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ cipherSpi.engineInit(opmode, key, params, random);
+ mode = opmode;
+ }
+
+ /**
+ * Initializes this cipher with the public key from the given certificate.
+ * <p>
+ * The cipher is initialized for one of the following four operations:
+ * encryption, decryption, key wrapping or key unwrapping, depending
+ * on the value of <code>opmode</code>.
+ * <p>
+ * If the certificate is of type X.509 and has a <i>key usage</i>
+ * extension field marked as critical, and the value of the <i>key usage</i>
+ * extension field implies that the public key in
+ * the certificate and its corresponding private key are not
+ * supposed to be used for the operation represented by the value
+ * of <code>opmode</code>,
+ * an <code>InvalidKeyException</code>
+ * is thrown.
+ * <p>
+ * If this cipher requires any algorithm parameters that cannot be
+ * derived from the public key in the given certificate, the underlying
+ * cipher
+ * implementation is supposed to generate the required parameters itself
+ * (using provider-specific default or ramdom values) if it is being
+ * initialized for encryption or key wrapping, and raise an <code>
+ * InvalidKeyException</code> if it is being initialized for decryption or
+ * key unwrapping.
+ * The generated parameters can be retrieved using
+ * <a href = "#getParameters()">getParameters</a> or
+ * <a href = "#getIV()">getIV</a> (if the parameter is an IV).
+ * <p>
+ * If this cipher (including its underlying feedback or padding scheme)
+ * requires any random bytes (e.g., for parameter generation), it will get
+ * them using the
+ * <a href="http://java.sun.com/products/jdk/1.2/docs/api/java.security.SecureRandom.html">
+ * <code>SecureRandom</code></a>
+ * implementation of the highest-priority installed provider as the source of randomness.
+ * (If none of the installed providers supply an implementation of
+ * SecureRandom, a system-provided source of randomness will be used.)
+ * <p>
+ * Note that when a Cipher object is initialized, it loses all
+ * previously-acquired state. In other words, initializing a Cipher is
+ * equivalent to creating a new instance of that Cipher and initializing
+ * it.
+ * @param opmode the operation mode of this cipher (this is one of the
+ * following:
+ * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
+ * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
+ * @param certificate the certificate
+ * @exception InvalidKeyException if the public key in the given
+ * certificate is inappropriate for initializing this cipher, or this
+ * cipher is being initialized for decryption or unwrapping keys and
+ * requires algorithm parameters that cannot be determined from the
+ * public key in the given certificate, or the keysize of the public key
+ * in the given certificate has a keysize that exceeds the maximum
+ * allowable keysize (as determined by the configured jurisdiction policy
+ * files).
+ * Note: Jurisdiction files are ignored in this implementation.
+ */
+ public final void init(
+ int opmode,
+ Certificate certificate)
+ throws InvalidKeyException
+ {
+ cipherSpi.engineInit(opmode, certificate.getPublicKey(), new SecureRandom());
+ mode = opmode;
+ }
+
+ /**
+ * Initializes this cipher with the public key from the given certificate
+ * and a source of randomness.
+ * <p>The cipher is initialized for one of the following four operations:
+ * encryption, decryption, key wrapping
+ * or key unwrapping, depending on
+ * the value of <code>opmode</code>.
+ * <p>
+ * If the certificate is of type X.509 and has a <i>key usage</i>
+ * extension field marked as critical, and the value of the <i>key usage</i>
+ * extension field implies that the public key in
+ * the certificate and its corresponding private key are not
+ * supposed to be used for the operation represented by the value of
+ * <code>opmode</code>,
+ * an <code>InvalidKeyException</code>
+ * is thrown.
+ * <p>
+ * If this cipher requires any algorithm parameters that cannot be
+ * derived from the public key in the given <code>certificate</code>,
+ * the underlying cipher
+ * implementation is supposed to generate the required parameters itself
+ * (using provider-specific default or random values) if it is being
+ * initialized for encryption or key wrapping, and raise an
+ * <code>InvalidKeyException</code> if it is being
+ * initialized for decryption or key unwrapping.
+ * The generated parameters can be retrieved using
+ * <a href = "#engineGetParameters()">engineGetParameters</a> or
+ * <a href = "#engineGetIV()">engineGetIV</a> (if the parameter is an IV).
+ * <p>
+ * If this cipher (including its underlying feedback or padding scheme)
+ * requires any random bytes (e.g., for parameter generation), it will get
+ * them from <code>random</code>.
+ * <p>
+ * Note that when a Cipher object is initialized, it loses all
+ * previously-acquired state. In other words, initializing a Cipher is
+ * equivalent to creating a new instance of that Cipher and initializing
+ * it.
+ *
+ * @param opmode the operation mode of this cipher (this is one of the
+ * following: <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
+ * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
+ * @param certificate the certificate
+ * @param random the source of randomness
+ * @exception InvalidKeyException if the public key in the given
+ * certificate is inappropriate for initializing this cipher, or this
+ * cipher is being initialized for decryption or unwrapping keys and
+ * requires algorithm parameters that cannot be determined from the
+ * public key in the given certificate, or the keysize of the public key
+ * in the given certificate has a keysize that exceeds the maximum
+ * allowable keysize (as determined by the configured jurisdiction policy
+ * files).
+ */
+ public final void init(
+ int opmode,
+ Certificate certificate,
+ SecureRandom random)
+ throws InvalidKeyException
+ {
+ cipherSpi.engineInit(opmode, certificate.getPublicKey(), random);
+ mode = opmode;
+ }
+
+ /**
+ * Continues a multiple-part encryption or decryption operation
+ * (depending on how this cipher was initialized), processing another data
+ * part.
+ * <p>
+ * The bytes in the <code>input</code> buffer are processed, and the
+ * result is stored in a new buffer.
+ * <p>
+ * If <code>input</code> has a length of zero, this method returns
+ * <code>null</code>.
+ *
+ * @param input the input buffer
+ * @return the new buffer with the result, or null if the underlying
+ * cipher is a block cipher and the input data is too short to result in a
+ * new block.
+ * @exception IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not been initialized)
+ */
+ public final byte[] update(
+ byte[] input)
+ throws IllegalStateException
+ {
+ if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE)
+ {
+ throw new IllegalStateException("Cipher is uninitialised");
+ }
+
+ if (input == null)
+ {
+ throw new IllegalArgumentException("Null input buffer");
+ }
+
+ if (input.length == 0)
+ {
+ return null;
+ }
+
+ return cipherSpi.engineUpdate(input, 0, input.length);
+ }
+
+ /**
+ * Continues a multiple-part encryption or decryption operation
+ * (depending on how this cipher was initialized), processing another data
+ * part.
+ * <p>
+ * The first <code>inputLen</code> bytes in the <code>input</code>
+ * buffer, starting at <code>inputOffset</code> inclusive, are processed,
+ * and the result is stored in a new buffer.
+ * <p>
+ * If <code>inputLen</code> is zero, this method returns
+ * <code>null</code>.
+ *
+ * @param input the input buffer
+ * @param inputOffset the offset in <code>input</code> where the input
+ * starts
+ * @param inputLen the input length
+ * @return the new buffer with the result, or null if the underlying
+ * cipher is a block cipher and the input data is too short to result in a
+ * new block.
+ * @exception IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not been initialized)
+ */
+ public final byte[] update(
+ byte[] input,
+ int inputOffset,
+ int inputLen)
+ throws IllegalStateException
+ {
+ if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE)
+ {
+ throw new IllegalStateException("Cipher is uninitialised");
+ }
+
+ if (input == null)
+ {
+ throw new IllegalArgumentException("Null input passed");
+ }
+
+ if (inputLen < 0 || inputOffset < 0
+ || inputLen > (input.length - inputOffset))
+ {
+ throw new IllegalArgumentException("Bad inputOffset/inputLen");
+ }
+
+ if (inputLen == 0)
+ {
+ return null;
+ }
+
+ return cipherSpi.engineUpdate(input, inputOffset, inputLen);
+ }
+
+ /**
+ * Continues a multiple-part encryption or decryption operation
+ * (depending on how this cipher was initialized), processing another data
+ * part.
+ * <p>
+ * The first <code>inputLen</code> bytes in the <code>input</code>
+ * buffer, starting at <code>inputOffset</code> inclusive, are processed,
+ * and the result is stored in the <code>output</code> buffer.
+ * <p>
+ * If the <code>output</code> buffer is too small to hold the result,
+ * a <code>ShortBufferException</code> is thrown. In this case, repeat this
+ * call with a larger output buffer. Use
+ * <a href = "#getOutputSize(int)">getOutputSize</a> to determine how big
+ * the output buffer should be.
+ * <p>
+ * If <code>inputLen</code> is zero, this method returns
+ * a length of zero.
+ *
+ * @param input the input buffer
+ * @param inputOffset the offset in <code>input</code> where the input starts
+ * @param inputLen the input length
+ * @param output the buffer for the result
+ * @return the number of bytes stored in <code>output</code>
+ * @exception IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not been initialized)
+ * @exception ShortBufferException if the given output buffer is too small
+ * to hold the result
+ */
+ public final int update(
+ byte[] input,
+ int inputOffset,
+ int inputLen,
+ byte[] output)
+ throws IllegalStateException, ShortBufferException
+ {
+ if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE)
+ {
+ throw new IllegalStateException("Cipher is uninitialised");
+ }
+
+ if (input == null)
+ {
+ throw new IllegalArgumentException("Null input passed");
+ }
+
+ if (inputLen < 0 || inputOffset < 0
+ || inputLen > (input.length - inputOffset))
+ {
+ throw new IllegalArgumentException("Bad inputOffset/inputLen");
+ }
+
+ if (output == null)
+ {
+ throw new IllegalArgumentException("Null output passed");
+ }
+
+ if (inputLen == 0)
+ {
+ return 0;
+ }
+
+ return cipherSpi.engineUpdate(input, inputOffset, inputLen, output, 0);
+ }
+
+ /**
+ * Continues a multiple-part encryption or decryption operation
+ * (depending on how this cipher was initialized), processing another data
+ * part.
+ * <p>
+ * The first <code>inputLen</code> bytes in the <code>input</code>
+ * buffer, starting at <code>inputOffset</code> inclusive, are processed,
+ * and the result is stored in the <code>output</code> buffer, starting at
+ * <code>outputOffset</code> inclusive.
+ * <p>
+ * If the <code>output</code> buffer is too small to hold the result,
+ * a <code>ShortBufferException</code> is thrown. In this case, repeat this
+ * call with a larger output buffer. Use
+ * <a href = "#getOutputSize(int)">getOutputSize</a> to determine how big
+ * the output buffer should be.
+ * <p>
+ * If <code>inputLen</code> is zero, this method returns
+ * a length of zero.
+ *
+ * @param input the input buffer
+ * @param inputOffset the offset in <code>input</code> where the input starts
+ * @param inputLen the input length
+ * @param output the buffer for the result
+ * @param outputOffset the offset in <code>output</code> where the result
+ * is stored
+ * @return the number of bytes stored in <code>output</code>
+ * @exception IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not been initialized)
+ * @exception ShortBufferException if the given output buffer is too small
+ * to hold the result
+ */
+ public final int update(
+ byte[] input,
+ int inputOffset,
+ int inputLen,
+ byte[] output,
+ int outputOffset)
+ throws IllegalStateException, ShortBufferException
+ {
+ if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE)
+ {
+ throw new IllegalStateException("Cipher is uninitialised");
+ }
+
+ if (input == null)
+ {
+ throw new IllegalArgumentException("Null input passed");
+ }
+
+ if (inputLen < 0 || inputOffset < 0
+ || inputLen > (input.length - inputOffset))
+ {
+ throw new IllegalArgumentException("Bad inputOffset/inputLen");
+ }
+
+ if (output == null)
+ {
+ throw new IllegalArgumentException("Null output passed");
+ }
+
+ if (outputOffset < 0 || outputOffset >= output.length)
+ {
+ throw new IllegalArgumentException("Bad outputOffset");
+ }
+
+ if (inputLen == 0)
+ {
+ return 0;
+ }
+
+ return cipherSpi.engineUpdate(input, inputOffset, inputLen, output, outputOffset);
+ }
+
+ /**
+ * Finishes a multiple-part encryption or decryption operation, depending
+ * on how this cipher was initialized.
+ * <p>
+ * Input data that may have been buffered during a previous
+ * <code>update</code> operation is processed, with padding (if requested)
+ * being applied.
+ * The result is stored in a new buffer.
+ * <p>
+ * A call to this method resets this cipher object to the state
+ * it was in when previously initialized via a call to <code>init</code>.
+ * That is, the object is reset and available to encrypt or decrypt
+ * (depending on the operation mode that was specified in the call to
+ * <code>init</code>) more data.
+ * @return the new buffer with the result
+ * @exception IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not been initialized)
+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
+ * no padding has been requested (only in encryption mode), and the total
+ * input length of the data processed by this cipher is not a multiple of
+ * block size
+ * @exception BadPaddingException if this cipher is in decryption mode,
+ * and (un)padding has been requested, but the decrypted data is not
+ * bounded by the appropriate padding bytes
+ */
+ public final byte[] doFinal()
+ throws java.lang.IllegalStateException, IllegalBlockSizeException,
+ BadPaddingException
+ {
+ if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE)
+ {
+ throw new IllegalStateException("Cipher is uninitialised");
+ }
+
+ return cipherSpi.engineDoFinal(null, 0, 0);
+ }
+
+ /**
+ * Finishes a multiple-part encryption or decryption operation, depending
+ * on how this cipher was initialized.
+ * <p>
+ * Input data that may have been buffered during a previous
+ * <code>update</code> operation is processed, with padding (if requested)
+ * being applied.
+ * The result is stored in the <code>output</code> buffer, starting at
+ * <code>outputOffset</code> inclusive.
+ * <p>
+ * If the <code>output</code> buffer is too small to hold the result,
+ * a <code>ShortBufferException</code> is thrown. In this case, repeat this
+ * call with a larger output buffer. Use
+ * <a href = "#getOutputSize(int)">getOutputSize</a> to determine how big
+ * the output buffer should be.
+ * <p>
+ * A call to this method resets this cipher object to the state
+ * it was in when previously initialized via a call to <code>init</code>.
+ * That is, the object is reset and available to encrypt or decrypt
+ * (depending on the operation mode that was specified in the call to
+ * <code>init</code>) more data.
+ *
+ * @param output the buffer for the result
+ * @param outputOffset the offset in <code>output</code> where the result
+ * is stored
+ * @return the number of bytes stored in <code>output</code>
+ * @exception IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not been initialized)
+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
+ * no padding has been requested (only in encryption mode), and the total
+ * input length of the data processed by this cipher is not a multiple of
+ * block size
+ * @exception ShortBufferException if the given output buffer is too small
+ * to hold the result
+ * @exception BadPaddingException if this cipher is in decryption mode,
+ * and (un)padding has been requested, but the decrypted data is not
+ * bounded by the appropriate padding bytes
+ */
+ public final int doFinal(
+ byte[] output,
+ int outputOffset)
+ throws IllegalStateException, IllegalBlockSizeException,
+ ShortBufferException, BadPaddingException
+ {
+ if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE)
+ {
+ throw new IllegalStateException("Cipher is uninitialised");
+ }
+
+ if (output == null)
+ {
+ throw new IllegalArgumentException("Null output passed");
+ }
+
+ if (outputOffset < 0 || outputOffset >= output.length)
+ {
+ throw new IllegalArgumentException("Bad outputOffset");
+ }
+
+ return cipherSpi.engineDoFinal(null, 0, 0, output, outputOffset);
+ }
+
+ /**
+ * Encrypts or decrypts data in a single-part operation, or finishes a
+ * multiple-part operation. The data is encrypted or decrypted,
+ * depending on how this cipher was initialized.
+ * <p>
+ * The bytes in the <code>input</code> buffer, and any input bytes that
+ * may have been buffered during a previous <code>update</code> operation,
+ * are processed, with padding (if requested) being applied.
+ * The result is stored in a new buffer.
+ * <p>
+ * A call to this method resets this cipher object to the state
+ * it was in when previously initialized via a call to <code>init</code>.
+ * That is, the object is reset and available to encrypt or decrypt
+ * (depending on the operation mode that was specified in the call to
+ * <code>init</code>) more data.
+ *
+ * @param input the input buffer
+ * @return the new buffer with the result
+ * @exception IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not been initialized)
+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
+ * no padding has been requested (only in encryption mode), and the total
+ * input length of the data processed by this cipher is not a multiple of
+ * block size
+ * @exception BadPaddingException if this cipher is in decryption mode,
+ * and (un)padding has been requested, but the decrypted data is not
+ * bounded by the appropriate padding bytes
+ */
+ public final byte[] doFinal(
+ byte[] input)
+ throws java.lang.IllegalStateException, IllegalBlockSizeException, BadPaddingException
+ {
+ if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE)
+ {
+ throw new IllegalStateException("Cipher is uninitialised");
+ }
+
+ if (input == null)
+ {
+ throw new IllegalArgumentException("Null input passed");
+ }
+
+ return cipherSpi.engineDoFinal(input, 0, input.length);
+ }
+
+ /**
+ * Encrypts or decrypts data in a single-part operation, or finishes a
+ * multiple-part operation. The data is encrypted or decrypted,
+ * depending on how this cipher was initialized.
+ * <p>
+ * The first <code>inputLen</code> bytes in the <code>input</code>
+ * buffer, starting at <code>inputOffset</code> inclusive, and any input
+ * bytes that may have been buffered during a previous <code>update</code>
+ * operation, are processed, with padding (if requested) being applied.
+ * The result is stored in a new buffer.
+ * <p>A call to this method resets this cipher object to the state
+ * it was in when previously initialized via a call to <code>init</code>.
+ * That is, the object is reset and available to encrypt or decrypt
+ * (depending on the operation mode that was specified in the call to
+ * <code>init</code>) more data.
+ *
+ * @param input the input buffer
+ * @param inputOffset the offset in <code>input</code> where the input starts
+ * @param inputLen the input length
+ * @return the new buffer with the result
+ * @exception IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not been initialized)
+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
+ * no padding has been requested (only in encryption mode), and the total
+ * input length of the data processed by this cipher is not a multiple of
+ * block size
+ * @exception BadPaddingException if this cipher is in decryption mode,
+ * and (un)padding has been requested, but the decrypted data is not
+ * bounded by the appropriate padding bytes
+ */
+ public final byte[] doFinal(
+ byte[] input,
+ int inputOffset,
+ int inputLen)
+ throws IllegalStateException, IllegalBlockSizeException, BadPaddingException
+ {
+ if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE)
+ {
+ throw new IllegalStateException("Cipher is uninitialised");
+ }
+
+ if (input == null)
+ {
+ throw new IllegalArgumentException("Null input passed");
+ }
+
+ if (inputLen < 0 || inputOffset < 0
+ || inputLen > (input.length - inputOffset))
+ {
+ throw new IllegalArgumentException("Bad inputOffset/inputLen");
+ }
+
+ return cipherSpi.engineDoFinal(input, inputOffset, inputLen);
+ }
+
+ /**
+ * Encrypts or decrypts data in a single-part operation, or finishes a
+ * multiple-part operation. The data is encrypted or decrypted,
+ * depending on how this cipher was initialized.
+ * <p>
+ * The first <code>inputLen</code> bytes in the <code>input</code>
+ * buffer, starting at <code>inputOffset</code> inclusive, and any input
+ * bytes that may have been buffered during a previous <code>update</code>
+ * operation, are processed, with padding (if requested) being applied.
+ * The result is stored in the <code>output</code> buffer.
+ * <p>
+ * If the <code>output</code> buffer is too small to hold the result,
+ * a <code>ShortBufferException</code> is thrown. In this case, repeat this
+ * call with a larger output buffer. Use
+ * <a href = "#getOutputSize(int)">getOutputSize</a> to determine how big
+ * the output buffer should be.
+ * <p>
+ * A call to this method resets this cipher object to the state
+ * it was in when previously initialized via a call to <code>init</code>.
+ * That is, the object is reset and available to encrypt or decrypt
+ * (depending on the operation mode that was specified in the call to
+ * <code>init</code>) more data.
+ * @param input the input buffer
+ * @param inputOffset the offset in <code>input</code> where the input starts
+ * @param inputLen the input length
+ * @param output the buffer for the result
+ * @return the number of bytes stored in <code>output</code>
+ * @exception IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not been initialized)
+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
+ * no padding has been requested (only in encryption mode), and the total
+ * input length of the data processed by this cipher is not a multiple of
+ * block size
+ * @exception ShortBufferException if the given output buffer is too small
+ * to hold the result
+ * @exception BadPaddingException if this cipher is in decryption mode,
+ * and (un)padding has been requested, but the decrypted data is not
+ * bounded by the appropriate padding bytes
+ */
+ public final int doFinal(
+ byte[] input,
+ int inputOffset,
+ int inputLen,
+ byte[] output)
+ throws IllegalStateException, ShortBufferException,
+ IllegalBlockSizeException, BadPaddingException
+ {
+ if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE)
+ {
+ throw new IllegalStateException("Cipher is uninitialised");
+ }
+
+ if (input == null)
+ {
+ throw new IllegalArgumentException("Null input passed");
+ }
+
+ if (inputLen < 0 || inputOffset < 0
+ || inputLen > (input.length - inputOffset))
+ {
+ throw new IllegalArgumentException("Bad inputOffset/inputLen");
+ }
+
+ if (output == null)
+ {
+ throw new IllegalArgumentException("Null output passed");
+ }
+
+ return cipherSpi.engineDoFinal(input, inputOffset, inputLen, output, 0);
+ }
+
+ /**
+ * Encrypts or decrypts data in a single-part operation, or finishes a
+ * multiple-part operation. The data is encrypted or decrypted,
+ * depending on how this cipher was initialized.
+ * <p>
+ * The first <code>inputLen</code> bytes in the <code>input</code>
+ * buffer, starting at <code>inputOffset</code> inclusive, and any input
+ * bytes that may have been buffered during a previous
+ * <code>update</code> operation, are processed, with padding
+ * (if requested) being applied.
+ * The result is stored in the <code>output</code> buffer, starting at
+ * <code>outputOffset</code> inclusive.
+ * <p>
+ * If the <code>output</code> buffer is too small to hold the result,
+ * a <code>ShortBufferException</code> is thrown. In this case, repeat this
+ * call with a larger output buffer. Use
+ * <a href = "#getOutputSize(int)">getOutputSize</a> to determine how big
+ * the output buffer should be.
+ * <p>
+ * A call to this method resets this cipher object to the state
+ * it was in when previously initialized via a call to <code>init</code>.
+ * That is, the object is reset and available to encrypt or decrypt
+ * (depending on the operation mode that was specified in the call to
+ * <code>init</code>) more data.
+ *
+ * @param input the input buffer
+ * @param inputOffset the offset in <code>input</code> where the input starts
+ * @param inputLen the input length
+ * @param output the buffer for the result
+ * @param outputOffset the offset in <code>output</code> where the result is
+ * stored
+ * @return the number of bytes stored in <code>output</code>
+ * @exception IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not been initialized)
+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
+ * no padding has been requested (only in encryption mode), and the total
+ * input length of the data processed by this cipher is not a multiple of
+ * block size
+ * @exception ShortBufferException if the given output buffer is too small
+ * to hold the result
+ * @exception BadPaddingException if this cipher is in decryption mode,
+ * and (un)padding has been requested, but the decrypted data is not
+ * bounded by the appropriate padding bytes
+ */
+ public final int doFinal(
+ byte[] input,
+ int inputOffset,
+ int inputLen,
+ byte[] output,
+ int outputOffset)
+ throws IllegalStateException, ShortBufferException,
+ IllegalBlockSizeException, BadPaddingException
+ {
+ if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE)
+ {
+ throw new IllegalStateException("Cipher is uninitialised");
+ }
+
+ if (input == null)
+ {
+ throw new IllegalArgumentException("Null input passed");
+ }
+
+ if (inputLen < 0 || inputOffset < 0
+ || inputLen > (input.length - inputOffset))
+ {
+ throw new IllegalArgumentException("Bad inputOffset/inputLen");
+ }
+
+ if (output == null)
+ {
+ throw new IllegalArgumentException("Null output passed");
+ }
+
+ if (outputOffset < 0 || outputOffset >= output.length)
+ {
+ throw new IllegalArgumentException("Bad outputOffset");
+ }
+
+ return cipherSpi.engineDoFinal(input, inputOffset, inputLen, output, outputOffset);
+ }
+
+ /**
+ * Wrap a key.
+ *
+ * @param key the key to be wrapped.
+ * @return the wrapped key.
+ * @exception IllegalStateException if this cipher is in a wrong state (e.g., has not
+ * been initialized).
+ * @exception IllegalBlockSizeException if this cipher is a block cipher, no padding
+ * has been requested, and the length of the encoding of the key to be wrapped is not a
+ * multiple of the block size.
+ * @exception <DD>java.security.InvalidKeyException - if it is impossible or unsafe to
+ * wrap the key with this cipher (e.g., a hardware protected key is being passed to a
+ * software-only cipher).
+ */
+ public final byte[] wrap(
+ Key key)
+ throws IllegalStateException, IllegalBlockSizeException, InvalidKeyException
+ {
+ if (mode != WRAP_MODE)
+ {
+ throw new IllegalStateException("Cipher is not initialised for wrapping");
+ }
+
+ if (key == null)
+ {
+ throw new IllegalArgumentException("Null key passed");
+ }
+
+ return cipherSpi.engineWrap(key);
+ }
+
+ /**
+ * Unwrap a previously wrapped key.
+ *
+ * @param wrappedKey the key to be unwrapped.
+ * @param wrappedKeyAlgorithm the algorithm associated with the wrapped key.
+ * @param wrappedKeyType the type of the wrapped key. This must be one of
+ * <code>SECRET_KEY</code>, <code>PRIVATE_KEY</code>, or <code>PUBLIC_KEY</code>.
+ * @return the unwrapped key.
+ * @exception IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not been initialized).
+ * @exception InvalidKeyException if <code>wrappedKey</code> does not
+ * represent a wrapped key, or if the algorithm associated with the
+ * wrapped key is different from <code>wrappedKeyAlgorithm</code>
+ * and/or its key type is different from <code>wrappedKeyType</code>.
+ * @exception NoSuchAlgorithmException - if no installed providers
+ * can create keys for the <code>wrappedKeyAlgorithm</code>.
+ */
+ public final Key unwrap(
+ byte[] wrappedKey,
+ String wrappedKeyAlgorithm,
+ int wrappedKeyType)
+ throws IllegalStateException, InvalidKeyException, NoSuchAlgorithmException
+ {
+ if (mode != UNWRAP_MODE)
+ {
+ throw new IllegalStateException("Cipher is not initialised for unwrapping");
+ }
+
+ if (wrappedKeyType != SECRET_KEY && wrappedKeyType != PUBLIC_KEY
+ && wrappedKeyType != PRIVATE_KEY)
+ {
+ throw new IllegalArgumentException("Invalid key type argument");
+ }
+
+ if (wrappedKey == null)
+ {
+ throw new IllegalArgumentException("Null wrappedKey passed");
+ }
+
+ if (wrappedKeyAlgorithm == null)
+ {
+ throw new IllegalArgumentException("Null wrappedKeyAlgorithm string passed");
+ }
+
+ return cipherSpi.engineUnwrap(wrappedKey, wrappedKeyAlgorithm, wrappedKeyType);
+ }
+}