aboutsummaryrefslogtreecommitdiffstats
path: root/libraries/spongycastle/jce/src/main/java/javax
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/spongycastle/jce/src/main/java/javax')
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/BadPaddingException.java37
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/Cipher.java1509
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/CipherInputStream.java349
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/CipherOutputStream.java191
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/CipherSpi.java606
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/EncryptedPrivateKeyInfo.java234
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/ExemptionMechanism.java9
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/ExemptionMechanismException.java34
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/IllegalBlockSizeException.java36
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/JCEUtil.java202
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/KeyAgreement.java394
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/KeyAgreementSpi.java159
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/KeyGenerator.java302
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/KeyGeneratorSpi.java64
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/Mac.java443
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/MacSpi.java92
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/NoSuchPaddingException.java36
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/NullCipher.java240
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/SealedObject.java302
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/SecretKey.java28
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/SecretKeyFactory.java245
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/SecretKeyFactorySpi.java72
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/ShortBufferException.java36
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/interfaces/DHKey.java20
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/interfaces/DHPrivateKey.java21
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/interfaces/DHPublicKey.java21
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/interfaces/PBEKey.java41
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/spec/DESKeySpec.java194
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/spec/DESedeKeySpec.java100
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/spec/DHGenParameterSpec.java56
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/spec/DHParameterSpec.java95
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/spec/DHPrivateKeySpec.java61
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/spec/DHPublicKeySpec.java61
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/spec/IvParameterSpec.java75
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/spec/OAEPParameterSpec.java103
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/spec/PBEKeySpec.java222
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/spec/PBEParameterSpec.java55
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/spec/PSource.java98
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/spec/RC2ParameterSpec.java162
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/spec/RC5ParameterSpec.java224
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/spec/SecretKeySpec.java193
41 files changed, 7422 insertions, 0 deletions
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/BadPaddingException.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/BadPaddingException.java
new file mode 100644
index 000000000..d1df0d0b2
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/BadPaddingException.java
@@ -0,0 +1,37 @@
+package javax.crypto;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * This exception is thrown when a particular padding mechanism is
+ * expected for the input data but the data is not padded properly
+ *
+ */
+public class BadPaddingException
+ extends GeneralSecurityException
+{
+ private static final long serialVersionUID = -5315033893984728443L;
+
+ /**
+ * Constructs a BadPaddingException with no detail
+ * message. A detail message is a String that describes this
+ * particular exception.
+ */
+ public BadPaddingException()
+ {
+ }
+
+ /**
+ * Constructs a BadPaddingException with the specified
+ * detail message. A detail message is a String that describes
+ * this particular exception, which may, for example, specify which
+ * algorithm is not available.
+ *
+ * @param msg the detail message.
+ */
+ public BadPaddingException(
+ String msg)
+ {
+ super(msg);
+ }
+}
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);
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/CipherInputStream.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/CipherInputStream.java
new file mode 100644
index 000000000..9e41fb906
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/CipherInputStream.java
@@ -0,0 +1,349 @@
+package javax.crypto;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.FilterInputStream;
+
+/**
+ * A CipherInputStream is composed of an InputStream and a Cipher so
+ * that read() methods return data that are read in from the
+ * underlying InputStream but have been additionally processed by the
+ * Cipher. The Cipher must be fully initialized before being used by
+ * a CipherInputStream.
+ * <p>
+ * For example, if the Cipher is initialized for decryption, the
+ * CipherInputStream will attempt to read in data and decrypt them,
+ * before returning the decrypted data.
+ * <p>
+ * This class adheres strictly to the semantics, especially the
+ * failure semantics, of its ancestor classes
+ * java.io.FilterInputStream and java.io.InputStream. This class has
+ * exactly those methods specified in its ancestor classes, and
+ * overrides them all. Moreover, this class catches all exceptions
+ * that are not thrown by its ancestor classes. In particular, the
+ * <code>skip</code> method skips, and the <code>available</code>
+ * method counts only data that have been processed by the encapsulated Cipher.
+ * <p>
+ * It is crucial for a programmer using this class not to use
+ * methods that are not defined or overriden in this class (such as a
+ * new method or constructor that is later added to one of the super
+ * classes), because the design and implementation of those methods
+ * are unlikely to have considered security impact with regard to
+ * CipherInputStream.
+ *
+ * @since JCE1.2
+ * @see InputStream
+ * @see FilterInputStream
+ * @see Cipher
+ * @see CipherOutputStream
+ */
+public class CipherInputStream
+ extends FilterInputStream
+{
+ private Cipher c;
+
+ private byte[] buf;
+ private byte[] inBuf;
+
+ private int bufOff;
+ private int maxBuf;
+ private boolean finalized;
+
+ private static final int INPUT_BUF_SIZE = 2048;
+
+ /**
+ * Constructs a CipherInputStream from an InputStream and a
+ * Cipher.
+ */
+ public CipherInputStream(
+ InputStream is,
+ Cipher c)
+ {
+ super(is);
+
+ this.c = c;
+
+ buf = new byte[c.getOutputSize(INPUT_BUF_SIZE)];
+ inBuf = new byte[INPUT_BUF_SIZE];
+ }
+
+ /**
+ * Constructs a CipherInputStream from an InputStream without
+ * specifying a Cipher. This has the effect of constructing a
+ * CipherInputStream using a NullCipher.
+ */
+ protected CipherInputStream(
+ InputStream is)
+ {
+ this(is, new NullCipher());
+ }
+
+ /**
+ * grab the next chunk of input from the underlying input stream
+ */
+ private int nextChunk()
+ throws IOException
+ {
+ int available = super.available();
+
+ // must always try to read 1 byte!
+ // some buggy InputStreams return < 0!
+ if (available <= 0)
+ {
+ available = 1;
+ }
+
+ if (available > inBuf.length)
+ {
+ available = super.read(inBuf, 0, inBuf.length);
+ }
+ else
+ {
+ available = super.read(inBuf, 0, available);
+ }
+
+ if (available < 0)
+ {
+ if (finalized)
+ {
+ return -1;
+ }
+
+ try
+ {
+ buf = c.doFinal();
+ }
+ catch (Exception e)
+ {
+ throw new IOException("error processing stream: " + e.toString());
+ }
+
+ bufOff = 0;
+
+ if (buf != null)
+ {
+ maxBuf = buf.length;
+ }
+ else
+ {
+ maxBuf = 0;
+ }
+
+ finalized = true;
+
+ if (bufOff == maxBuf)
+ {
+ return -1;
+ }
+ }
+ else
+ {
+ bufOff = 0;
+
+ try
+ {
+ maxBuf = c.update(inBuf, 0, available, buf, 0);
+ }
+ catch (Exception e)
+ {
+ throw new IOException("error processing stream: " + e.toString());
+ }
+
+ if (maxBuf == 0) // not enough bytes read for first block...
+ {
+ return nextChunk();
+ }
+ }
+
+ return maxBuf;
+ }
+
+ /**
+ * Reads the next byte of data from this input stream. The value
+ * byte is returned as an <code>int</code> in the range
+ * <code>0</code> to <code>255</code>. If no byte is available
+ * because the end of the stream has been reached, the value
+ * <code>-1</code> is returned. This method blocks until input data
+ * is available, the end of the stream is detected, or an exception
+ * is thrown.
+ *
+ * @return the next byte of data, or <code>-1</code> if the end of the
+ * stream is reached.
+ * @exception IOException if an I/O error occurs.
+ * @since JCE1.2
+ */
+ public int read()
+ throws IOException
+ {
+ if (bufOff == maxBuf)
+ {
+ if (nextChunk() < 0)
+ {
+ return -1;
+ }
+ }
+
+ return buf[bufOff++] & 0xff;
+ }
+
+ /**
+ * Reads up to <code>b.length</code> bytes of data from this input
+ * stream into an array of bytes.
+ * <p>
+ * The <code>read</code> method of <code>InputStream</code> calls
+ * the <code>read</code> method of three arguments with the arguments
+ * <code>b</code>, <code>0</code>, and <code>b.length</code>.
+ *
+ * @param b the buffer into which the data is read.
+ * @return the total number of bytes read into the buffer, or
+ * <code>-1</code> is there is no more data because the end of
+ * the stream has been reached.
+ * @exception IOException if an I/O error occurs.
+ * @since JCE1.2
+ * @see #read(byte[], int, int)
+ */
+ public int read(
+ byte[] b)
+ throws IOException
+ {
+ return read(b, 0, b.length);
+ }
+
+ /**
+ * Reads up to <code>len</code> bytes of data from this input stream
+ * into an array of bytes. This method blocks until some input is
+ * available. If the first argument is <code>null,</code> up to
+ * <code>len</code> bytes are read and discarded.
+ *
+ * @param b the buffer into which the data is read.
+ * @param off the start offset of the data.
+ * @param len the maximum number of bytes read.
+ * @return the total number of bytes read into the buffer, or <code>-1</code>
+ * if there is no more data because the end of the stream has been reached.
+ * @exception IOException if an I/O error occurs.
+ * @since JCE1.2
+ * @see #read()
+ */
+ public int read(
+ byte[] b,
+ int off,
+ int len)
+ throws IOException
+ {
+ if (bufOff == maxBuf)
+ {
+ if (nextChunk() < 0)
+ {
+ return -1;
+ }
+ }
+
+ int available = maxBuf - bufOff;
+
+ if (len > available)
+ {
+ System.arraycopy(buf, bufOff, b, off, available);
+ bufOff = maxBuf;
+
+ return available;
+ }
+ else
+ {
+ System.arraycopy(buf, bufOff, b, off, len);
+ bufOff += len;
+
+ return len;
+ }
+ }
+
+ /**
+ * Skips <code>n</code> bytes of input from the bytes that can be read
+ * from this input stream without blocking.
+ * <p>
+ * Fewer bytes than requested might be skipped.
+ * The actual number of bytes skipped is equal to <code>n</code> or
+ * the result of a call to <a href = "#available()"><code>available</code></a>,
+ * whichever is smaller.
+ * If <code>n</code> is less than zero, no bytes are skipped.
+ * <p>
+ * The actual number of bytes skipped is returned.
+ *
+ * @param n the number of bytes to be skipped.
+ * @return the actual number of bytes skipped.
+ * @exception IOException if an I/O error occurs.
+ * @since JCE1.2
+ */
+ public long skip(
+ long n)
+ throws IOException
+ {
+ if (n <= 0)
+ {
+ return 0;
+ }
+
+ int available = maxBuf - bufOff;
+
+ if (n > available)
+ {
+ bufOff = maxBuf;
+
+ return available;
+ }
+ else
+ {
+ bufOff += (int)n;
+
+ return (int)n;
+ }
+ }
+
+ /**
+ * Returns the number of bytes that can be read from this input
+ * stream without blocking. The <code>available</code> method of
+ * <code>InputStream</code> returns <code>0</code>. This method
+ * <B>should</B> be overridden by subclasses.
+ *
+ * @return the number of bytes that can be read from this input stream
+ * without blocking.
+ * @exception IOException if an I/O error occurs.
+ * @since JCE1.2
+ */
+ public int available()
+ throws IOException
+ {
+ return maxBuf - bufOff;
+ }
+
+ /**
+ * Closes this input stream and releases any system resources
+ * associated with the stream.
+ * <p>
+ * The <code>close</code> method of <code>CipherInputStream</code>
+ * calls the <code>close</code> method of its underlying input
+ * stream.
+ *
+ * @exception IOException if an I/O error occurs.
+ * @since JCE1.2
+ */
+ public void close()
+ throws IOException
+ {
+ super.close();
+ }
+
+ /**
+ * Tests if this input stream supports the <code>mark</code>
+ * and <code>reset</code> methods, which it does not.
+ *
+ * @return <code>false</code>, since this class does not support the
+ * <code>mark</code> and <code>reset</code> methods.
+ * @since JCE1.2
+ * @see #mark(int)
+ * @see #reset()
+ */
+ public boolean markSupported()
+ {
+ return false;
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/CipherOutputStream.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/CipherOutputStream.java
new file mode 100644
index 000000000..ef2db07f5
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/CipherOutputStream.java
@@ -0,0 +1,191 @@
+package javax.crypto;
+
+import java.io.OutputStream;
+import java.io.IOException;
+import java.io.FilterOutputStream;
+
+/**
+ * A CipherOutputStream is composed of an OutputStream and a Cipher so
+ * that write() methods first process the data before writing them out
+ * to the underlying OutputStream. The cipher must be fully
+ * initialized before being used by a CipherOutputStream.
+ * <p>
+ * For example, if the cipher is initialized for encryption, the
+ * CipherOutputStream will attempt to encrypt data before writing out the
+ * encrypted data.
+ * <p>
+ * This class adheres strictly to the semantics, especially the
+ * failure semantics, of its ancestor classes
+ * java.io.OutputStream and java.io.FilterOutputStream. This class
+ * has exactly those methods specified in its ancestor classes, and
+ * overrides them all. Moreover, this class catches all exceptions
+ * that are not thrown by its ancestor classes.
+ * <p>
+ * It is crucial for a programmer using this class not to use
+ * methods that are not defined or overriden in this class (such as a
+ * new method or constructor that is later added to one of the super
+ * classes), because the design and implementation of those methods
+ * are unlikely to have considered security impact with regard to
+ * CipherOutputStream.
+ *
+ * @since JCE1.2
+ * @see OutputStream
+ * @see FilterOutputStream
+ * @see Cipher
+ * @see CipherInputStream
+ */
+public class CipherOutputStream
+ extends FilterOutputStream
+{
+ private Cipher c;
+
+ private byte[] oneByte = new byte[1];
+
+ /**
+ * Constructs a CipherOutputStream from an OutputStream and a
+ * Cipher.
+ */
+ public CipherOutputStream(
+ OutputStream os,
+ Cipher c)
+ {
+ super(os);
+ this.c = c;
+ }
+
+ /**
+ * Constructs a CipherOutputStream from an OutputStream without
+ * specifying a Cipher. This has the effect of constructing a
+ * CipherOutputStream using a NullCipher.
+ */
+ protected CipherOutputStream(
+ OutputStream os)
+ {
+ this(os, new NullCipher());
+ }
+
+ /**
+ * Writes the specified byte to this output stream.
+ *
+ * @param b the <code>byte</code>.
+ * @exception IOException if an I/O error occurs.
+ * @since JCE1.2
+ */
+ public void write(
+ int b)
+ throws IOException
+ {
+ oneByte[0] = (byte)b;
+
+ byte[] bytes = c.update(oneByte, 0, 1);
+
+ if (bytes != null)
+ {
+ out.write(bytes, 0, bytes.length);
+ }
+ }
+
+ /**
+ * Writes <code>b.length</code> bytes from the specified byte array
+ * to this output stream.
+ * <p>
+ * The <code>write</code> method of
+ * <code>CipherOutputStream</code> calls the <code>write</code>
+ * method of three arguments with the three arguments
+ * <code>b</code>, <code>0</code>, and <code>b.length</code>.
+ *
+ * @param b the data.
+ * @exception IOException if an I/O error occurs.
+ * @since JCE1.2
+ * @see #write(byte[], int, int)
+ */
+ public void write(
+ byte[] b)
+ throws IOException
+ {
+ write(b, 0, b.length);
+ }
+
+ /**
+ * Writes <code>len</code> bytes from the specified byte array
+ * starting at offset <code>off</code> to this output stream.
+ *
+ * @param b the data.
+ * @param off the start offset in the data.
+ * @param len the number of bytes to write.
+ * @exception IOException if an I/O error occurs.
+ * @since JCE1.2
+ */
+ public void write(
+ byte[] b,
+ int off,
+ int len)
+ throws IOException
+ {
+ byte[] bytes = c.update(b, off, len);
+
+ if (bytes != null)
+ {
+ out.write(bytes, 0, bytes.length);
+ }
+ }
+
+ /**
+ * Flushes this output stream by forcing any buffered output bytes
+ * that have already been processed by the encapsulated cipher object
+ * to be written out.
+ *
+ * <p>
+ * Any bytes buffered by the encapsulated cipher
+ * and waiting to be processed by it will not be written out. For example,
+ * if the encapsulated cipher is a block cipher, and the total number of
+ * bytes written using one of the <code>write</code> methods is less than
+ * the cipher's block size, no bytes will be written out.
+ *
+ * @exception IOException if an I/O error occurs.
+ * @since JCE1.2
+ */
+ public void flush()
+ throws IOException
+ {
+ super.flush();
+ }
+
+ /**
+ * Closes this output stream and releases any system resources
+ * associated with this stream.
+ * <p>
+ * This method invokes the <code>doFinal</code> method of the encapsulated
+ * cipher object, which causes any bytes buffered by the encapsulated
+ * cipher to be processed. The result is written out by calling the
+ * <code>flush</code> method of this output stream.
+ * <p>
+ * This method resets the encapsulated cipher object to its initial state
+ * and calls the <code>close</code> method of the underlying output
+ * stream.
+ *
+ * @exception IOException if an I/O error occurs.
+ * @since JCE1.2
+ */
+ public void close()
+ throws IOException
+ {
+ try
+ {
+ byte[] bytes = c.doFinal();
+
+ if (bytes != null)
+ {
+ out.write(bytes, 0, bytes.length);
+ }
+ }
+ catch (Exception e)
+ {
+ throw new IOException("Error closing stream: " + e.toString());
+ }
+
+ flush();
+
+ super.close();
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/CipherSpi.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/CipherSpi.java
new file mode 100644
index 000000000..09ff01e2c
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/CipherSpi.java
@@ -0,0 +1,606 @@
+package javax.crypto;
+
+import java.security.Key;
+import java.security.SecureRandom;
+import java.security.InvalidKeyException;
+import java.security.AlgorithmParameters;
+import java.security.NoSuchAlgorithmException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
+ * for the <code>Cipher</code> class.
+ * All the abstract methods in this class must be implemented by each
+ * cryptographic service provider who wishes to supply the implementation
+ * of a particular cipher algorithm.
+ * <p>
+ * In order to create an instance of <code>Cipher</code>, which
+ * encapsulates an instance of this <code>CipherSpi</code> class, an
+ * application calls one of the
+ * <a href = "Cipher.html#getInstance(java.lang.String)">getInstance</a>
+ * factory methods of the
+ * <a href = "Cipher.html">Cipher</a> engine class and specifies the requested
+ * <i>transformation</i>.
+ * Optionally, the application may also specify the name of a provider.
+ * <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>A provider may supply a separate class for each combination
+ * of <i>algorithm/mode/padding</i>, or may decide to provide more generic
+ * classes representing sub-transformations corresponding to
+ * <i>algorithm</i> or <i>algorithm/mode</i> or <i>algorithm//padding</i>
+ * (note the double slashes),
+ * in which case the requested mode and/or padding are set automatically by
+ * the <code>getInstance</code> methods of <code>Cipher</code>, which invoke
+ * the <a href = "#engineSetMode(java.lang.String)">engineSetMode</a> and
+ * <a href = "#engineSetPadding(java.lang.String)">engineSetPadding</a>
+ * methods of the provider's subclass of <code>CipherSpi</code>.
+ *
+ * <p>A <code>Cipher</code> property in a provider master class may have one of
+ * the following formats:
+ *
+ * <ul>
+ *
+ * <li>
+ * <pre>
+ * // provider's subclass of "CipherSpi" implements "algName" with
+ * // pluggable mode and padding
+ * <code>Cipher.</code><i>algName</i>
+ * </pre>
+ *
+ * <li>
+ * <pre>
+ * // provider's subclass of "CipherSpi" implements "algName" in the
+ * // specified "mode", with pluggable padding
+ * <code>Cipher.</code><i>algName/mode</i>
+ * </pre>
+ *
+ * <li>
+ * <pre>
+ * // provider's subclass of "CipherSpi" implements "algName" with the
+ * // specified "padding", with pluggable mode
+ * <code>Cipher.</code><i>algName//padding</i>
+ * </pre>
+ *
+ * <li>
+ * <pre>
+ * // provider's subclass of "CipherSpi" implements "algName" with the
+ * // specified "mode" and "padding"
+ * <code>Cipher.</code><i>algName/mode/padding</i>
+ * </pre>
+ *
+ * </ul>
+ *
+ * <p>For example, a provider may supply a subclass of <code>CipherSpi</code>
+ * that implements <i>DES/ECB/PKCS5Padding</i>, one that implements
+ * <i>DES/CBC/PKCS5Padding</i>, one that implements
+ * <i>DES/CFB/PKCS5Padding</i>, and yet another one that implements
+ * <i>DES/OFB/PKCS5Padding</i>. That provider would have the following
+ * <code>Cipher</code> properties in its master class:<p>
+ *
+ * <ul>
+ *
+ * <li>
+ * <pre>
+ * <code>Cipher.</code><i>DES/ECB/PKCS5Padding</i>
+ * </pre>
+ *
+ * <li>
+ * <pre>
+ * <code>Cipher.</code><i>DES/CBC/PKCS5Padding</i>
+ * </pre>
+ *
+ * <li>
+ * <pre>
+ * <code>Cipher.</code><i>DES/CFB/PKCS5Padding</i>
+ * </pre>
+ *
+ * <li>
+ * <pre>
+ * <code>Cipher.</code><i>DES/OFB/PKCS5Padding</i>
+ * </pre>
+ *
+ * </ul>
+ *
+ * <p>Another provider may implement a class for each of the above modes
+ * (i.e., one class for <i>ECB</i>, one for <i>CBC</i>, one for <i>CFB</i>,
+ * and one for <i>OFB</i>), one class for <i>PKCS5Padding</i>,
+ * and a generic <i>DES</i> class that subclasses from <code>CipherSpi</code>.
+ * That provider would have the following
+ * <code>Cipher</code> properties in its master class:<p>
+ *
+ * <ul>
+ *
+ * <li>
+ * <pre>
+ * <code>Cipher.</code><i>DES</i>
+ * </pre>
+ *
+ * </ul>
+ *
+ * <p>The <code>getInstance</code> factory method of the <code>Cipher</code>
+ * engine class follows these rules in order to instantiate a provider's
+ * implementation of <code>CipherSpi</code> for a
+ * transformation of the form "<i>algorithm</i>":
+ *
+ * <ol>
+ * <li>
+ * Check if the provider has registered a subclass of <code>CipherSpi</code>
+ * for the specified "<i>algorithm</i>".
+ * <p>If the answer is YES, instantiate this
+ * class, for whose mode and padding scheme default values (as supplied by
+ * the provider) are used.
+ * <p>If the answer is NO, throw a <code>NoSuchAlgorithmException</code>
+ * exception.
+ * </ol>
+ *
+ * <p>The <code>getInstance</code> factory method of the <code>Cipher</code>
+ * engine class follows these rules in order to instantiate a provider's
+ * implementation of <code>CipherSpi</code> for a
+ * transformation of the form "<i>algorithm/mode/padding</i>":
+ *
+ * <ol>
+ * <li>
+ * Check if the provider has registered a subclass of <code>CipherSpi</code>
+ * for the specified "<i>algorithm/mode/padding</i>" transformation.
+ * <p>If the answer is YES, instantiate it.
+ * <p>If the answer is NO, go to the next step.<p>
+ * <li>
+ * Check if the provider has registered a subclass of <code>CipherSpi</code>
+ * for the sub-transformation "<i>algorithm/mode</i>".
+ * <p>If the answer is YES, instantiate it, and call
+ * <code>engineSetPadding(<i>padding</i>)</code> on the new instance.
+ * <p>If the answer is NO, go to the next step.<p>
+ * <li>
+ * Check if the provider has registered a subclass of <code>CipherSpi</code>
+ * for the sub-transformation "<i>algorithm//padding</i>" (note the double
+ * slashes).
+ * <p>If the answer is YES, instantiate it, and call
+ * <code>engineSetMode(<i>mode</i>)</code> on the new instance.
+ * <p>If the answer is NO, go to the next step.<p>
+ * <li>
+ * Check if the provider has registered a subclass of <code>CipherSpi</code>
+ * for the sub-transformation "<i>algorithm</i>".
+ * <p>If the answer is YES, instantiate it, and call
+ * <code>engineSetMode(<i>mode</i>)</code> and
+ * <code>engineSetPadding(<i>padding</i>)</code> on the new instance.
+ * <p>If the answer is NO, throw a <code>NoSuchAlgorithmException</code>
+ * exception.
+ * </ol>
+ *
+ * @see KeyGenerator
+ * @see SecretKey
+ */
+public abstract class CipherSpi
+{
+ public CipherSpi()
+ {
+ }
+
+ /**
+ * Sets the mode of this cipher.
+ *
+ * @param mode the cipher mode
+ * @exception NoSuchAlgorithmException if the requested cipher mode does not exist
+ */
+ protected abstract void engineSetMode(
+ String mode)
+ throws NoSuchAlgorithmException;
+
+ /**
+ * Sets the padding mechanism of this cipher.
+ *
+ * @param padding the padding mechanism
+ * @exception NoSuchPaddingException if the requested padding mechanism does not exist
+ */
+ protected abstract void engineSetPadding(
+ String padding)
+ throws NoSuchPaddingException;
+
+ /**
+ * Returns the block size (in bytes).
+ *
+ * @return the block size (in bytes), or 0 if the underlying algorithm is not a block cipher
+ */
+ protected abstract int 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)
+ */
+ protected abstract int engineGetOutputSize(
+ int inputLen);
+
+ /**
+ * Returns the initialization vector (IV) in a new buffer.
+ * <p>
+ * This is useful in the context of password-based encryption or
+ * decryption, where the IV is derived from a user-provided passphrase.
+ *
+ * @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.
+ */
+ protected abstract byte[] 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.
+ */
+ protected abstract AlgorithmParameters engineGetParameters();
+
+ /**
+ * 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.
+ */
+ protected abstract void engineInit(
+ int opmode,
+ Key key,
+ SecureRandom random)
+ throws InvalidKeyException;
+
+ /**
+ * 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 = "#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 params the algorithm parameters
+ * @param random the source of randomness
+ * @exception InvalidKeyException if the given key is inappropriate for initializing this cipher
+ * @exception InvalidAlgorithmParameterException if the given algorithm parameters are inappropriate
+ * for this cipher, or if this cipher is being initialized for decryption and requires
+ * algorithm parameters and <code>params</code> is null.
+ */
+ protected abstract void engineInit(
+ int opmode,
+ Key key,
+ AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException;
+
+ /**
+ * 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 = "#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 params the algorithm parameters
+ * @param random the source of randomness
+ * @exception InvalidKeyException if the given key is inappropriate for initializing this cipher
+ * @exception InvalidAlgorithmParameterException if the given algorithm parameters are inappropriate
+ * for this cipher, or if this cipher is being initialized for decryption and requires
+ * algorithm parameters and <code>params</code> is null.
+ */
+ protected abstract void engineInit(
+ int opmode,
+ Key key,
+ AlgorithmParameters params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException;
+
+ /**
+ * 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.
+ *
+ * @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.
+ */
+ protected abstract byte[] engineUpdate(
+ byte[] input,
+ int inputOffset,
+ int 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, 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.
+ *
+ * @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 ShortBufferException if the given output buffer is too small to hold the result
+ */
+ protected abstract int engineUpdate(
+ byte[] input,
+ int inputOffset,
+ int inputLen,
+ byte[] output,
+ int outputOffset)
+ throws ShortBufferException;
+
+ /**
+ * 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>engineInit</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>engineInit</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 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
+ */
+ protected abstract byte[] engineDoFinal(
+ byte[] input,
+ int inputOffset,
+ int inputLen)
+ throws IllegalBlockSizeException, BadPaddingException;
+
+ /**
+ * 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.
+ * <p>
+ * A call to this method resets this cipher object to the state
+ * it was in when previously initialized via a call to
+ * <code>engineInit</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>engineInit</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 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
+ */
+ protected abstract int engineDoFinal(
+ byte[] input,
+ int inputOffset,
+ int inputLen,
+ byte[] output,
+ int outputOffset)
+ throws ShortBufferException, IllegalBlockSizeException, BadPaddingException;
+
+ /**
+ * Wrap a key.
+ * <p>
+ * This concrete method has been added to this previously-defined
+ * abstract class. (For backwards compatibility, it cannot be abstract.)
+ * It may be overridden by a provider to wrap a key.
+ * Such an override is expected to throw an IllegalBlockSizeException or
+ * InvalidKeyException (under the specified circumstances),
+ * if the given key cannot be wrapped.
+ * If this method is not overridden, it always throws an
+ * UnsupportedOperationException.
+ *
+ * @param key the key to be wrapped.
+ * @return the wrapped key.
+ * @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 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).
+ */
+ protected byte[] engineWrap(
+ Key key)
+ throws IllegalBlockSizeException, InvalidKeyException
+ {
+ throw new UnsupportedOperationException("Underlying cipher does not support key wrapping");
+ }
+
+ /**
+ * Unwrap a previously wrapped key.
+ *
+ * <p>This concrete method has been added to this previously-defined
+ * abstract class. (For backwards compatibility, it cannot be abstract.)
+ * It may be overridden by a provider to unwrap a previously wrapped key.
+ * Such an override is expected to throw an InvalidKeyException if
+ * the given wrapped key cannot be unwrapped.
+ * If this method is not overridden, it always throws an
+ * UnsupportedOperationException.
+ *
+ * @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 is one of <code>SECRET_KEY</code>,
+ * <code>PRIVATE_KEY</code>, or <code>PUBLIC_KEY</code>.
+ * @return the unwrapped key.
+ * @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>.
+ */
+ protected java.security.Key engineUnwrap(
+ byte[] wrappedKey,
+ String wrappedKeyAlgorithm,
+ int wrappedKeyType)
+ throws InvalidKeyException, NoSuchAlgorithmException
+ {
+ throw new UnsupportedOperationException("Underlying cipher does not support key unwrapping");
+ }
+
+ /**
+ * Returns the key size of the given key object.
+ * <p>
+ * This concrete method has been added to this previously-defined
+ * abstract class. It throws an <code>UnsupportedOperationException</code>
+ * if it is not overridden by the provider.
+ *
+ * @param key the key object.
+ * @return the key size of the given key object.
+ * @exception InvalidKeyException if <code>key</code> is invalid.
+ */
+ protected int engineGetKeySize(
+ Key key)
+ throws InvalidKeyException
+ {
+ throw new UnsupportedOperationException("Key size unavailable");
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/EncryptedPrivateKeyInfo.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/EncryptedPrivateKeyInfo.java
new file mode 100644
index 000000000..19f22ebe6
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/EncryptedPrivateKeyInfo.java
@@ -0,0 +1,234 @@
+package javax.crypto;
+
+import java.io.*;
+
+import java.security.*;
+import java.security.spec.*;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.DEROutputStream;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERObjectIdentifier;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * This class implements the <code>EncryptedPrivateKeyInfo</code> type
+ * as defined in PKCS #8.
+ * <p>Its ASN.1 definition is as follows:
+ *
+ * <pre>
+ * EncryptedPrivateKeyInfo ::= SEQUENCE {
+ * encryptionAlgorithm AlgorithmIdentifier,
+ * encryptedData OCTET STRING }
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL }
+ * </pre>
+ */
+public class EncryptedPrivateKeyInfo
+{
+ private org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo infoObj;
+ private AlgorithmParameters algP;
+
+ /*
+ * Constructs (i.e., parses) an <code>EncryptedPrivateKeyInfo</code> from
+ * its ASN.1 encoding.
+ *
+ * @param encoded the ASN.1 encoding of this object.
+ * @exception NullPointerException if the <code>encoded</code> is null.
+ * @exception IOException if error occurs when parsing the ASN.1 encoding.
+ */
+ public EncryptedPrivateKeyInfo(
+ byte[] encoded)
+ throws NullPointerException, IOException
+ {
+ if (encoded == null)
+ {
+ throw new NullPointerException("parameters null");
+ }
+
+ ByteArrayInputStream bIn = new ByteArrayInputStream(encoded);
+ ASN1InputStream dIn = new ASN1InputStream(bIn);
+
+ infoObj = org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo.getInstance((ASN1Sequence)dIn.readObject());
+
+ try
+ {
+ algP = this.getParameters();
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new IOException("can't create parameters: " + e.toString());
+ }
+ }
+
+ /*
+ * Constructs an <code>EncryptedPrivateKeyInfo</code> from the
+ * encryption algorithm name and the encrypted data.
+ * <p>Note: the <code>encrypedData</code> is cloned when constructing
+ * this object.
+ * <p>
+ * If encryption algorithm has associated parameters use the constructor
+ * with AlgorithmParameters as the parameter.
+ *
+ * @param algName algorithm name.
+ * @param encryptedData encrypted data.
+ * @exception NullPointerException if <code>algName</code> or <code>encryptedData</code> is null.
+ * @exception IllegalArgumentException if <code>encryptedData</code> is empty, i.e. 0-length.
+ * @exception NoSuchAlgorithmException if the specified algName is not supported.
+ */
+ public EncryptedPrivateKeyInfo(
+ String algName,
+ byte[] encryptedData)
+ throws NullPointerException, IllegalArgumentException, NoSuchAlgorithmException
+ {
+ if (algName == null || encryptedData == null)
+ {
+ throw new NullPointerException("parameters null");
+ }
+
+ org.spongycastle.asn1.x509.AlgorithmIdentifier kAlgId = new AlgorithmIdentifier(new DERObjectIdentifier(algName), null);
+
+ infoObj = new org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo(kAlgId, (byte[])encryptedData.clone());
+ algP = this.getParameters();
+ }
+
+ /**
+ * Constructs an <code>EncryptedPrivateKeyInfo</code> from the
+ * encryption algorithm parameters and the encrypted data.
+ * <p>Note: the <code>encrypedData</code> is cloned when constructing
+ * this object.
+ *
+ * @param algParams the algorithm parameters for the encryption
+ * algorithm. <code>algParams.getEncoded()</code> should return
+ * the ASN.1 encoded bytes of the <code>parameters</code> field
+ * of the <code>AlgorithmIdentifer</code> component of the
+ * <code>EncryptedPrivateKeyInfo</code> type.
+ * @param encryptedData encrypted data.
+ * @exception NullPointerException if <code>algParams</code> or <code>encryptedData</code> is null.
+ * @exception IllegalArgumentException if <code>encryptedData</code> is empty, i.e. 0-length.
+ * @exception NoSuchAlgorithmException if the specified algName of the specified <code>algParams</code> parameter is not supported.
+ */
+ public EncryptedPrivateKeyInfo(
+ AlgorithmParameters algParams,
+ byte[] encryptedData)
+ throws NullPointerException, IllegalArgumentException, NoSuchAlgorithmException
+ {
+ if (algParams == null || encryptedData == null)
+ {
+ throw new NullPointerException("parameters null");
+ }
+
+ org.spongycastle.asn1.x509.AlgorithmIdentifier kAlgId = null;
+
+ try
+ {
+ ByteArrayInputStream bIn = new ByteArrayInputStream(algParams.getEncoded());
+ ASN1InputStream dIn = new ASN1InputStream(bIn);
+
+ kAlgId = new AlgorithmIdentifier(
+ new DERObjectIdentifier(algParams.getAlgorithm()), dIn.readObject());
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("error in encoding: " + e.toString());
+ }
+
+ infoObj = new org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo(kAlgId, (byte[])encryptedData.clone());
+ algP = this.getParameters();
+ }
+
+ /**
+ * Returns the encryption algorithm.
+ *
+ * @returns the algorithm name.
+ */
+ public String getAlgName()
+ {
+ return infoObj.getEncryptionAlgorithm().getObjectId().getId();
+ }
+
+ private AlgorithmParameters getParameters()
+ throws NoSuchAlgorithmException
+ {
+ AlgorithmParameters ap = AlgorithmParameters.getInstance(this.getAlgName());
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ DEROutputStream dOut = new DEROutputStream(bOut);
+
+ try
+ {
+ dOut.writeObject(infoObj.getEncryptionAlgorithm().getParameters());
+ dOut.close();
+
+ ap.init(bOut.toByteArray());
+ }
+ catch (IOException e)
+ {
+ throw new NoSuchAlgorithmException("unable to parse parameters");
+ }
+
+ return ap;
+ }
+
+ /**
+ * Returns the algorithm parameters used by the encryption algorithm.
+ *
+ * @returns the algorithm parameters.
+ */
+ public AlgorithmParameters getAlgParameters()
+ {
+ return algP;
+ }
+
+ /**
+ * Returns a copy of the encrypted data.
+ *
+ * @returns a copy of the encrypted data.
+ */
+ public byte[] getEncryptedData()
+ {
+ return infoObj.getEncryptedData();
+ }
+
+ /**
+ * Extract the enclosed PKCS8EncodedKeySpec object from the
+ * encrypted data and return it.
+ *
+ * @return the PKCS8EncodedKeySpec object.
+ * @exception InvalidKeySpecException if the given cipher is
+ * inappropriate for the encrypted data or the encrypted
+ * data is corrupted and cannot be decrypted.
+ */
+ public PKCS8EncodedKeySpec getKeySpec(
+ Cipher c)
+ throws InvalidKeySpecException
+ {
+ try
+ {
+ return new PKCS8EncodedKeySpec(c.doFinal(this.getEncryptedData()));
+ }
+ catch (Exception e)
+ {
+ throw new InvalidKeySpecException("can't get keySpec: " + e.toString());
+ }
+ }
+
+ /**
+ * Returns the ASN.1 encoding of this object.
+ *
+ * @returns the ASN.1 encoding.
+ * @throws IOException if error occurs when constructing its ASN.1 encoding.
+ */
+ public byte[] getEncoded()
+ throws IOException
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ DEROutputStream dOut = new DEROutputStream(bOut);
+
+ dOut.writeObject(infoObj);
+ dOut.close();
+
+ return bOut.toByteArray();
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/ExemptionMechanism.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/ExemptionMechanism.java
new file mode 100644
index 000000000..49846ee92
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/ExemptionMechanism.java
@@ -0,0 +1,9 @@
+package javax.crypto;
+
+/**
+ * this is a place holder class, no exemption mechanism facility is
+ * required in this modified version of the JCE
+ */
+public class ExemptionMechanism
+{
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/ExemptionMechanismException.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/ExemptionMechanismException.java
new file mode 100644
index 000000000..e17ab0cf1
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/ExemptionMechanismException.java
@@ -0,0 +1,34 @@
+package javax.crypto;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * This is the generic ExemptionMechanism exception.
+ *
+ */
+public class ExemptionMechanismException
+ extends GeneralSecurityException
+{
+ private static final long serialVersionUID = 1572699429277957109L;
+
+ /**
+ * Constructs a ExemptionMechanismException with no detailed message.
+ * (A detailed message is a String that describes this particular exception.)
+ */
+ public ExemptionMechanismException()
+ {
+ }
+
+ /**
+ * Constructs a ExemptionMechanismException with the specified
+ * detailed message. (A detailed message is a String that describes
+ * this particular exception.)
+ *
+ * @param msg the detailed message.
+ */
+ public ExemptionMechanismException(
+ String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/IllegalBlockSizeException.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/IllegalBlockSizeException.java
new file mode 100644
index 000000000..5cd4176b2
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/IllegalBlockSizeException.java
@@ -0,0 +1,36 @@
+package javax.crypto;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * This exception is thrown when the length of data provided to a block
+ * cipher is incorrect, i.e., does not match the block size of the cipher.
+ *
+ */
+public class IllegalBlockSizeException
+ extends GeneralSecurityException
+{
+ private static final long serialVersionUID = -1965144811953540392L;
+
+ /**
+ * Constructs an IllegalBlockSizeException with no detail message.
+ * (A detail message is a String that describes this particular
+ * exception.)
+ */
+ public IllegalBlockSizeException()
+ {
+ }
+
+ /**
+ * Constructs an IllegalBlockSizeException with the specified
+ * detail message. (A detail message is a String that describes
+ * this particular exception.)
+ *
+ * @param msg the detail message.
+ */
+ public IllegalBlockSizeException(
+ String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/JCEUtil.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/JCEUtil.java
new file mode 100644
index 000000000..913c01b03
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/JCEUtil.java
@@ -0,0 +1,202 @@
+package javax.crypto;
+
+import java.security.NoSuchProviderException;
+import java.security.Provider;
+import java.security.Security;
+import java.util.Locale;
+
+class JCEUtil
+{
+ static class Implementation
+ {
+ Object engine;
+ Provider provider;
+
+ Implementation(
+ Object engine,
+ Provider provider)
+ {
+ this.engine = engine;
+ this.provider = provider;
+ }
+
+ Object getEngine()
+ {
+ return engine;
+ }
+
+ Provider getProvider()
+ {
+ return provider;
+ }
+ }
+
+ /**
+ * see if we can find an algorithm (or its alias and what it represents) in
+ * the property table for the given provider.
+ *
+ * @return null if no algorithm found, an Implementation if it is.
+ */
+ static private Implementation findImplementation(
+ String baseName,
+ String algorithm,
+ Provider prov)
+ {
+ String alias;
+
+ while ((alias = prov.getProperty("Alg.Alias." + baseName + "." + algorithm)) != null)
+ {
+ algorithm = alias;
+ }
+
+ String className = prov.getProperty(baseName + "." + algorithm);
+
+ if (className != null)
+ {
+ try
+ {
+ Class cls;
+ ClassLoader clsLoader = prov.getClass().getClassLoader();
+
+ if (clsLoader != null)
+ {
+ cls = clsLoader.loadClass(className);
+ }
+ else
+ {
+ cls = Class.forName(className);
+ }
+
+ return new Implementation(cls.newInstance(), prov);
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new IllegalStateException(
+ "algorithm " + algorithm + " in provider " + prov.getName() + " but no class \"" + className + "\" found!");
+ }
+ catch (Exception e)
+ {
+ throw new IllegalStateException(
+ "algorithm " + algorithm + " in provider " + prov.getName() + " but class \"" + className + "\" inaccessible!");
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * return an implementation for a given algorithm/provider.
+ * If the provider is null, we grab the first avalaible who has the required algorithm.
+ *
+ * @return null if no algorithm found, an Implementation if it is.
+ * @exception NoSuchProviderException if a provider is specified and not found.
+ */
+ static Implementation getImplementation(
+ String baseName,
+ String algorithm,
+ String provider)
+ throws NoSuchProviderException
+ {
+ if (provider == null)
+ {
+ Provider[] prov = Security.getProviders();
+
+ //
+ // search every provider looking for the algorithm we want.
+ //
+ for (int i = 0; i != prov.length; i++)
+ {
+ //
+ // try case insensitive
+ //
+ Implementation imp = findImplementation(baseName, algorithm.toUpperCase(Locale.ENGLISH), prov[i]);
+ if (imp != null)
+ {
+ return imp;
+ }
+
+ imp = findImplementation(baseName, algorithm, prov[i]);
+ if (imp != null)
+ {
+ return imp;
+ }
+ }
+ }
+ else
+ {
+ Provider prov = Security.getProvider(provider);
+
+ if (prov == null)
+ {
+ throw new NoSuchProviderException("Provider " + provider + " not found");
+ }
+
+ //
+ // try case insensitive
+ //
+ Implementation imp = findImplementation(baseName, algorithm.toUpperCase(Locale.ENGLISH), prov);
+ if (imp != null)
+ {
+ return imp;
+ }
+
+ return findImplementation(baseName, algorithm, prov);
+ }
+
+ return null;
+ }
+
+ /**
+ * return an implementation for a given algorithm/provider.
+ * If the provider is null, we grab the first avalaible who has the required algorithm.
+ *
+ * @return null if no algorithm found, an Implementation if it is.
+ * @exception NoSuchProviderException if a provider is specified and not found.
+ */
+ static Implementation getImplementation(
+ String baseName,
+ String algorithm,
+ Provider provider)
+ {
+ if (provider == null)
+ {
+ Provider[] prov = Security.getProviders();
+
+ //
+ // search every provider looking for the algorithm we want.
+ //
+ for (int i = 0; i != prov.length; i++)
+ {
+ //
+ // try case insensitive
+ //
+ Implementation imp = findImplementation(baseName, algorithm.toUpperCase(Locale.ENGLISH), prov[i]);
+ if (imp != null)
+ {
+ return imp;
+ }
+
+ imp = findImplementation(baseName, algorithm, prov[i]);
+ if (imp != null)
+ {
+ return imp;
+ }
+ }
+ }
+ else
+ {
+ //
+ // try case insensitive
+ //
+ Implementation imp = findImplementation(baseName, algorithm.toUpperCase(Locale.ENGLISH), provider);
+ if (imp != null)
+ {
+ return imp;
+ }
+
+ return findImplementation(baseName, algorithm, provider);
+ }
+
+ return null;
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/KeyAgreement.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/KeyAgreement.java
new file mode 100644
index 000000000..6e8d768bd
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/KeyAgreement.java
@@ -0,0 +1,394 @@
+package javax.crypto;
+
+import java.security.Key;
+import java.security.Provider;
+import java.security.SecureRandom;
+import java.security.InvalidKeyException;
+import java.security.NoSuchProviderException;
+import java.security.NoSuchAlgorithmException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * This class provides the functionality of a key agreement (or key
+ * exchange) protocol.
+ * The keys involved in establishing a shared secret are created by one of the
+ * key generators (<code>KeyPairGenerator</code> or
+ * <code>KeyGenerator</code>), a <code>KeyFactory</code>, or as a result from
+ * an intermediate phase of the key agreement protocol
+ * (see <a href = "#doPhase(java.security.Key, boolean)">doPhase</a>).
+ *
+ * For each of the correspondents in the key exchange, <code>doPhase</code>
+ * needs to be called. For example, if this key exchange is with one other
+ * party, <code>doPhase</code> needs to be called once, with the
+ * <code>lastPhase</code> flag set to <code>true</code>.
+ * If this key exchange is
+ * with two other parties, <code>doPhase</code> needs to be called twice,
+ * the first time setting the <code>lastPhase</code> flag to
+ * <code>false</code>, and the second time setting it to <code>true</code>.
+ * There may be any number of parties involved in a key exchange.
+ *
+ * @see KeyGenerator
+ * @see SecretKey
+ */
+public class KeyAgreement
+{
+ KeyAgreementSpi keyAgreeSpi;
+ Provider provider;
+ String algorithm;
+
+ /**
+ * Creates a KeyAgreement object.
+ *
+ * @param keyAgreeSpi the delegate
+ * @param provider the provider
+ * @param algorithm the algorithm
+ */
+ protected KeyAgreement(
+ KeyAgreementSpi keyAgreeSpi,
+ Provider provider,
+ String algorithm)
+ {
+ this.keyAgreeSpi = keyAgreeSpi;
+ this.provider = provider;
+ this.algorithm = algorithm;
+ }
+
+ /**
+ * Returns the algorithm name of this <code>KeyAgreement</code> object.
+ * <p>
+ * This is the same name that was specified in one of the
+ * <code>getInstance</code> calls that created this
+ * <code>KeyAgreement</code> object.
+ *
+ * @return the algorithm name of this <code>KeyAgreement</code> object.
+ */
+ public final String getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ /**
+ * Generates a <code>KeyAgreement</code> object that implements the
+ * specified key agreement algorithm.
+ * If the default provider package provides an implementation of the
+ * requested key agreement algorithm, an instance of
+ * <code>KeyAgreement</code> containing that implementation is returned.
+ * If the algorithm is not available in the default provider package,
+ * other provider packages are searched.
+ *
+ * @param algorithm the standard name of the requested key agreement algorithm.
+ * See Appendix A in the Java Cryptography Extension API Specification &amp; Reference
+ * for information about standard algorithm names.
+ * @return the new <code>KeyAgreement</code> object
+ * @exception NoSuchAlgorithmException if the specified algorithm is not
+ * available in the default provider package or any of the other provider
+ * packages that were searched.
+ */
+ public static final KeyAgreement getInstance(
+ String algorithm)
+ throws NoSuchAlgorithmException
+ {
+ try
+ {
+ JCEUtil.Implementation imp = JCEUtil.getImplementation("KeyAgreement", algorithm, (String) null);
+
+ if (imp == null)
+ {
+ throw new NoSuchAlgorithmException(algorithm + " not found");
+ }
+
+ KeyAgreement keyAgree = new KeyAgreement((KeyAgreementSpi)imp.getEngine(), imp.getProvider(), algorithm);
+
+ return keyAgree;
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new NoSuchAlgorithmException(algorithm + " not found");
+ }
+ }
+
+ /**
+ * Generates a <code>KeyAgreement</code> object for the specified key
+ * agreement algorithm from the specified provider.
+ *
+ * @param algorithm the standard name of the requested key agreement algorithm.
+ * See Appendix A in the Java Cryptography Extension API Specification &amp; Reference
+ * for information about standard algorithm names.
+ * @param provider the provider
+ * @return the new <code>KeyAgreement</code> object
+ * @exception NoSuchAlgorithmException if the specified algorithm is not
+ * available from the specified provider.
+ */
+ public static final KeyAgreement getInstance(
+ String algorithm,
+ Provider provider)
+ throws NoSuchAlgorithmException
+ {
+ if (provider == null)
+ {
+ throw new IllegalArgumentException("No provider specified to KeyAgreement.getInstance()");
+ }
+
+ JCEUtil.Implementation imp = JCEUtil.getImplementation("KeyAgreement", algorithm, provider);
+
+ if (imp == null)
+ {
+ throw new NoSuchAlgorithmException(algorithm + " not found");
+ }
+
+ KeyAgreement keyAgree = new KeyAgreement((KeyAgreementSpi)imp.getEngine(), imp.getProvider(), algorithm);
+
+ return keyAgree;
+ }
+
+ /**
+ * Generates a <code>KeyAgreement</code> object for the specified key
+ * agreement algorithm from the specified provider.
+ *
+ * @param algorithm the standard name of the requested key agreement algorithm.
+ * See Appendix A in the Java Cryptography Extension API Specification &amp; Reference
+ * for information about standard algorithm names.
+ * @param provider the name of the provider
+ * @return the new <code>KeyAgreement</code> object
+ * @exception NoSuchAlgorithmException if the specified algorithm is not
+ * available from the specified provider.
+ * @exception NoSuchProviderException if the specified provider has not
+ * been configured.
+ */
+ public static final KeyAgreement getInstance(
+ String algorithm,
+ String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ if (provider == null)
+ {
+ throw new IllegalArgumentException("No provider specified to KeyAgreement.getInstance()");
+ }
+
+ JCEUtil.Implementation imp = JCEUtil.getImplementation("KeyAgreement", algorithm, provider);
+
+ if (imp == null)
+ {
+ throw new NoSuchAlgorithmException(algorithm + " not found");
+ }
+
+ KeyAgreement keyAgree = new KeyAgreement((KeyAgreementSpi)imp.getEngine(), imp.getProvider(), algorithm);
+
+ return keyAgree;
+ }
+
+ /**
+ * Returns the provider of this <code>KeyAgreement</code> object.
+ *
+ * @return the provider of this <code>KeyAgreement</code> object
+ */
+ public final Provider getProvider()
+ {
+ return provider;
+ }
+
+ /**
+ * Initializes this key agreement with the given key, which is required to
+ * contain all the algorithm parameters required for this key agreement.
+ * <p>
+ * If this key agreement requires any random bytes, 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.)
+ *
+ * @param key the party's private information. For example, in the case
+ * of the Diffie-Hellman key agreement, this would be the party's own
+ * Diffie-Hellman private key.
+ * @exception InvalidKeyException if the given key is
+ * inappropriate for this key agreement, e.g., is of the wrong type or
+ * has an incompatible algorithm type.
+ */
+ public final void init(
+ Key key)
+ throws InvalidKeyException
+ {
+ keyAgreeSpi.engineInit(key, null);
+ }
+
+ /**
+ * Initializes this key agreement with the given key and source of
+ * randomness. The given key is required to contain all the algorithm
+ * parameters required for this key agreement.
+ * <p>
+ * If the key agreement algorithm requires random bytes, it gets them
+ * from the given source of randomness, <code>random</code>.
+ * However, if the underlying
+ * algorithm implementation does not require any random bytes,
+ * <code>random</code> is ignored.
+ *
+ * @param key the party's private information. For example, in the case
+ * of the Diffie-Hellman key agreement, this would be the party's own
+ * Diffie-Hellman private key.
+ * @param random the source of randomness
+ * @exception InvalidKeyException if the given key is
+ * inappropriate for this key agreement, e.g., is of the wrong type or
+ * has an incompatible algorithm type.
+ */
+ public final void init(
+ Key key,
+ SecureRandom random)
+ throws InvalidKeyException
+ {
+ keyAgreeSpi.engineInit(key, random);
+ }
+
+ /**
+ * Initializes this key agreement with the given key and set of
+ * algorithm parameters.
+ * <p>
+ * If this key agreement requires any random bytes, 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.)
+ *
+ * @param key the party's private information. For example, in the case
+ * of the Diffie-Hellman key agreement, this would be the party's own
+ * Diffie-Hellman private key.
+ * @param params the key agreement parameters
+ * @exception InvalidKeyException if the given key is inappropriate for this
+ * key agreement, e.g., is of the wrong type or has an incompatible algorithm type.
+ * @exception InvalidAlgorithmParameterException if the given parameters
+ * are inappropriate for this key agreement.
+ */
+ public final void init(
+ Key key,
+ AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ keyAgreeSpi.engineInit(key, params, null);
+ }
+
+ /**
+ * Initializes this key agreement with the given key, set of
+ * algorithm parameters, and source of randomness.
+ *
+ * @param key the party's private information. For example, in the case
+ * of the Diffie-Hellman key agreement, this would be the party's own
+ * Diffie-Hellman private key.
+ * @param params the key agreement parameters
+ * @param random the source of randomness
+ * @exception InvalidKeyException if the given key is
+ * inappropriate for this key agreement, e.g., is of the wrong type or
+ * has an incompatible algorithm type.
+ * @exception InvalidAlgorithmParameterException if the given parameters
+ * are inappropriate for this key agreement.
+ */
+ public final void init(
+ Key key,
+ AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ keyAgreeSpi.engineInit(key, params, random);
+ }
+
+ /**
+ * Executes the next phase of this key agreement with the given
+ * key that was received from one of the other parties involved in this key
+ * agreement.
+ *
+ * @param key the key for this phase. For example, in the case of
+ * Diffie-Hellman between 2 parties, this would be the other party's
+ * Diffie-Hellman public key.
+ * @param lastPhase flag which indicates whether or not this is the last
+ * phase of this key agreement.
+ * @return the (intermediate) key resulting from this phase, or null
+ * if this phase does not yield a key
+ * @exception InvalidKeyException if the given key is inappropriate for this phase.
+ * @exception IllegalStateException if this key agreement has not been
+ * initialized.
+ */
+ public final Key doPhase(
+ Key key,
+ boolean lastPhase)
+ throws InvalidKeyException, IllegalStateException
+ {
+ return keyAgreeSpi.engineDoPhase(key, lastPhase);
+ }
+
+ /**
+ * Generates the shared secret and returns it in a new buffer.
+ * <p>
+ * This method resets this <code>KeyAgreement</code> object, so that it
+ * can be reused for further key agreements. Unless this key agreement is
+ * reinitialized with one of the <code>init</code> methods, the same
+ * private information and algorithm parameters will be used for
+ * subsequent key agreements.
+ *
+ * @return the new buffer with the shared secret
+ * @exception IllegalStateException if this key agreement has not been completed yet
+ */
+ public final byte[] generateSecret()
+ throws IllegalStateException
+ {
+ return keyAgreeSpi.engineGenerateSecret();
+ }
+
+ /**
+ * Generates the shared secret, and places it into the buffer
+ * <code>sharedSecret</code>, beginning at <code>offset</code> inclusive.
+ * <p>
+ * If the <code>sharedSecret</code> buffer is too small to hold the
+ * result, a <code>ShortBufferException</code> is thrown.
+ * In this case, this call should be repeated with a larger output buffer.
+ * <p>
+ * This method resets this <code>KeyAgreement</code> object, so that it
+ * can be reused for further key agreements. Unless this key agreement is
+ * reinitialized with one of the <code>init</code> methods, the same
+ * private information and algorithm parameters will be used for
+ * subsequent key agreements.
+ *
+ * @param sharedSecret the buffer for the shared secret
+ * @param offset the offset in <code>sharedSecret</code> where the
+ * shared secret will be stored
+ * @return the number of bytes placed into <code>sharedSecret</code>
+ * @exception IllegalStateException if this key agreement has not been
+ * completed yet
+ * @exception ShortBufferException if the given output buffer is too small
+ * to hold the secret
+ */
+ public final int generateSecret(
+ byte[] sharedSecret,
+ int offset)
+ throws IllegalStateException, ShortBufferException
+ {
+ return keyAgreeSpi.engineGenerateSecret(sharedSecret, offset);
+ }
+
+ /**
+ * Creates the shared secret and returns it as a <code>SecretKey</code>
+ * object of the specified algorithm.
+ * <p>
+ * This method resets this <code>KeyAgreement</code> object, so that it
+ * can be reused for further key agreements. Unless this key agreement is
+ * reinitialized with one of the <code>init</code> methods, the same
+ * private information and algorithm parameters will be used for
+ * subsequent key agreements.
+ *
+ * @param algorithm the requested secret-key algorithm
+ * @return the shared secret key
+ * @exception IllegalStateException if this key agreement has not been
+ * completed yet
+ * @exception NoSuchAlgorithmException if the specified secret-key
+ * algorithm is not available
+ * @exception InvalidKeyException if the shared secret-key material cannot
+ * be used to generate a secret key of the specified algorithm (e.g.,
+ * the key material is too short)
+ */
+ public final SecretKey generateSecret(
+ String algorithm)
+ throws IllegalStateException, NoSuchAlgorithmException, InvalidKeyException
+ {
+ return keyAgreeSpi.engineGenerateSecret(algorithm);
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/KeyAgreementSpi.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/KeyAgreementSpi.java
new file mode 100644
index 000000000..b4569a1eb
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/KeyAgreementSpi.java
@@ -0,0 +1,159 @@
+package javax.crypto;
+
+import java.security.Key;
+import java.security.SecureRandom;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.InvalidAlgorithmParameterException;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
+ * for the <code>KeyAgreement</code> class.
+ * All the abstract methods in this class must be implemented by each
+ * cryptographic service provider who wishes to supply the implementation
+ * of a particular key agreement algorithm.
+ * <p>
+ * The keys involved in establishing a shared secret are created by one of the
+ * key generators (<code>KeyPairGenerator</code> or <code>KeyGenerator</code>),
+ * a <code>KeyFactory</code>, or as a result from an intermediate phase of the key
+ * agreement protocol (see <a href = "#engineDoPhase(java.security.Key, boolean)">engineDoPhase</a>).
+ * <p>
+ * For each of the correspondents in the key exchange, <code>engineDoPhase</code>
+ * needs to be called. For example, if the key exchange is with one other
+ * party, <code>engineDoPhase</code> needs to be called once, with the
+ * <code>lastPhase</code> flag set to <code>true</code>.
+ * If the key exchange is with two other parties, <code>engineDoPhase</code> needs to be called twice,
+ * the first time setting the <code>lastPhase</code> flag to
+ * <code>false</code>, and the second time setting it to <code>true</code>.
+ * There may be any number of parties involved in a key exchange.
+ *
+ * @see KeyGenerator
+ * @see SecretKey
+ */
+public abstract class KeyAgreementSpi
+{
+ public KeyAgreementSpi()
+ {
+ }
+
+ /**
+ * Initializes this key agreement with the given key and source of
+ * randomness. The given key is required to contain all the algorithm
+ * parameters required for this key agreement.
+ * <p>
+ * If the key agreement algorithm requires random bytes, it gets them
+ * from the given source of randomness, <code>random</code>.
+ * However, if the underlying
+ * algorithm implementation does not require any random bytes,
+ * <code>random</code> is ignored.
+ *
+ * @param key the party's private information. For example, in the case
+ * of the Diffie-Hellman key agreement, this would be the party's own Diffie-Hellman private key.
+ * @param random the source of randomness
+ * @exception InvalidKeyException if the given key is inappropriate for this key agreement, e.g., is
+ * of the wrong type or has an incompatible algorithm type.
+ */
+ protected abstract void engineInit(
+ Key key,
+ SecureRandom random)
+ throws InvalidKeyException;
+
+ /**
+ * Initializes this key agreement with the given key, set of
+ * algorithm parameters, and source of randomness.
+ *
+ * @param key the party's private information. For example, in the case
+ * of the Diffie-Hellman key agreement, this would be the party's own
+ * Diffie-Hellman private key.
+ * @param params the key agreement parameters
+ * @param random the source of randomness
+ * @exception InvalidKeyException if the given key is inappropriate for this key agreement, e.g., is of the
+ * wrong type or has an incompatible algorithm type.
+ * @exception InvalidAlgorithmParameterException if the given parameters are inappropriate for this key
+ * agreement.
+ */
+ protected abstract void engineInit(
+ Key key,
+ AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException;
+
+ /**
+ * Executes the next phase of this key agreement with the given
+ * key that was received from one of the other parties involved in this key
+ * agreement.
+ * @param key the key for this phase. For example, in the case of
+ * Diffie-Hellman between 2 parties, this would be the other party's
+ * Diffie-Hellman public key.
+ * @param lastPhase flag which indicates whether or not this is the last
+ * phase of this key agreement.
+ * @return the (intermediate) key resulting from this phase, or null if this phase does not yield a key
+ * @exception InvalidKeyException if the given key is inappropriate for this phase.
+ * @exception IllegalStateException if this key agreement has not been initialized.
+ */
+ protected abstract Key engineDoPhase(
+ Key key,
+ boolean lastPhase)
+ throws InvalidKeyException, IllegalStateException;
+
+ /**
+ * Generates the shared secret and returns it in a new buffer.
+ * <p>
+ * This method resets this <code>KeyAgreementSpi</code> object, so that it
+ * can be reused for further key agreements. Unless this key agreement is
+ * reinitialized with one of the <code>engineInit</code> methods, the same
+ * private information and algorithm parameters will be used for
+ * subsequent key agreements.
+ * @return the new buffer with the shared secret
+ * @exception IllegalStateException if this key agreement has not been completed yet
+ */
+ protected abstract byte[] engineGenerateSecret()
+ throws IllegalStateException;
+
+ /**
+ * Generates the shared secret, and places it into the buffer
+ * <code>sharedSecret</code>, beginning at <code>offset</code> inclusive.
+ * <p>
+ * If the <code>sharedSecret</code> buffer is too small to hold the result,
+ * a <code>ShortBufferException</code> is thrown. In this case, this call should be
+ * repeated with a larger output buffer.
+ * <p>
+ * This method resets this <code>KeyAgreementSpi</code> object, so that it
+ * can be reused for further key agreements. Unless this key agreement is
+ * reinitialized with one of the <code>engineInit</code> methods, the same
+ * private information and algorithm parameters will be used for subsequent key agreements.
+ *
+ * @param sharedSecret the buffer for the shared secret
+ * @param offset the offset in <code>sharedSecret</code> where the shared secret will be stored
+ * @return the number of bytes placed into <code>sharedSecret</code>
+ * @exception IllegalStateException if this key agreement has not been completed yet
+ * @exception ShortBufferException if the given output buffer is too small to hold the secret
+ */
+ protected abstract int engineGenerateSecret(
+ byte[] sharedSecret,
+ int offset)
+ throws IllegalStateException, ShortBufferException;
+
+ /**
+ * Creates the shared secret and returns it as a secret key object
+ * of the requested algorithm type.
+ * <p>
+ * This method resets this <code>KeyAgreementSpi</code> object, so that it
+ * can be reused for further key agreements. Unless this key agreement is
+ * reinitialized with one of the <code>engineInit</code> methods, the same
+ * private information and algorithm parameters will be used for
+ * subsequent key agreements.
+ *
+ * @param algorithm the requested secret key algorithm
+ * @return the shared secret key
+ * @exception IllegalStateException if this key agreement has not been completed yet
+ * @exception NoSuchAlgorithmException if the requested secret key algorithm is not available
+ * @exception InvalidKeyException if the shared secret key material cannot be used to generate
+ * a secret key of the requested algorithm type (e.g., the key material is too short)
+ */
+ protected abstract SecretKey engineGenerateSecret(
+ String algorithm)
+ throws IllegalStateException, NoSuchAlgorithmException, InvalidKeyException;
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/KeyGenerator.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/KeyGenerator.java
new file mode 100644
index 000000000..19a34cedd
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/KeyGenerator.java
@@ -0,0 +1,302 @@
+package javax.crypto;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Provider;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * This class provides the functionality of a (symmetric) key generator.
+ * <p>
+ * Key generators are constructed using one of the <code>getInstance</code>
+ * class methods of this class.
+ * <p>
+ * KeyGenerator objects are reusable, i.e., after a key has been
+ * generated, the same KeyGenerator object can be re-used to generate further
+ * keys.
+ * <p>
+ * There are two ways to generate a key: in an algorithm-independent manner,
+ * and in an algorithm-specific manner. The only difference between the two is
+ * the initialization of the object:
+ *
+ * <ul>
+ * <li><b>Algorithm-Independent Initialization</b>
+ * <p>All key generators share the concepts of a <i>keysize</i> and a
+ * <i>source of randomness</i>.
+ * There is an
+ * <a href = "#init(int, java.security.SecureRandom)">init</a>
+ * method in this KeyGenerator class that takes these two universally
+ * shared types of arguments. There is also one that takes just a
+ * <code>keysize</code> argument, and uses the SecureRandom implementation
+ * of the highest-priority installed provider as the source of randomness
+ * (or a system-provided source of randomness if none of the installed
+ * providers supply a SecureRandom implementation), and one that takes just a
+ * source of randomness.
+ * <p>
+ * Since no other parameters are specified when you call the above
+ * algorithm-independent <code>init</code> methods, it is up to the
+ * provider what to do about the algorithm-specific parameters (if any) to be
+ * associated with each of the keys.
+ * <p>
+ * <li><b>Algorithm-Specific Initialization</b>
+ * <p>For situations where a set of algorithm-specific parameters already
+ * exists, there are two
+ * <a href = "#init(java.security.spec.AlgorithmParameterSpec)">init</a>
+ * methods that have an <code>AlgorithmParameterSpec</code>
+ * argument. One also has a <code>SecureRandom</code> argument, while the
+ * other uses the SecureRandom implementation
+ * of the highest-priority installed provider as the source of randomness
+ * (or a system-provided source of randomness if none of the installed
+ * providers supply a SecureRandom implementation).
+ * </ul>
+ *
+ * <p>In case the client does not explicitly initialize the KeyGenerator
+ * (via a call to an <code>init</code> method), each provider must
+ * supply (and document) a default initialization.
+ *
+ * @see SecretKey
+ */
+public class KeyGenerator
+{
+ private KeyGeneratorSpi keyGenerator;
+ private Provider provider;
+ private String algorithm;
+
+ /**
+ * Creates a KeyGenerator object.
+ *
+ * @param keyGenSpi the delegate
+ * @param provider the provider
+ * @param algorithm the algorithm
+ */
+ protected KeyGenerator(
+ KeyGeneratorSpi keyGenSpi,
+ Provider provider,
+ String algorithm)
+ {
+ this.keyGenerator = keyGenSpi;
+ this.provider = provider;
+ this.algorithm = algorithm;
+ }
+
+ /**
+ * Returns the algorithm name of this <code>KeyGenerator</code> object.
+ * <p>
+ * This is the same name that was specified in one of the
+ * <code>getInstance</code> calls that created this
+ * <code>KeyGenerator</code> object.
+ *
+ * @return the algorithm name of this <code>KeyGenerator</code> object.
+ */
+ public final String getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ /**
+ * Generates a <code>KeyGenerator</code> object for the specified algorithm.
+ * If the default provider package provides an implementation of the
+ * requested key generator, an instance of <code>KeyGenerator</code> containing
+ * that implementation is returned. If the requested key generator is not available
+ * in the default provider package, other provider packages are searched.
+ *
+ * @param algorithm the standard name of the requested key algorithm. See Appendix A in the
+ * Java Cryptography Extension API Specification &amp; Reference for information about standard
+ * algorithm names.
+ * @return the new <code>KeyGenerator</code> object
+ * @exception NoSuchAlgorithmException if a key generator for the specified algorithm is not
+ * available in the default provider package or any of the other provider packages that were searched.
+ */
+ public static final KeyGenerator getInstance(
+ String algorithm)
+ throws NoSuchAlgorithmException
+ {
+ try
+ {
+ JCEUtil.Implementation imp = JCEUtil.getImplementation("KeyGenerator", algorithm, (String) null);
+
+ if (imp == null)
+ {
+ throw new NoSuchAlgorithmException(algorithm + " not found");
+ }
+
+ KeyGenerator keyGen = new KeyGenerator((KeyGeneratorSpi)imp.getEngine(), imp.getProvider(), algorithm);
+
+ return keyGen;
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new NoSuchAlgorithmException(algorithm + " not found");
+ }
+ }
+
+ /**
+ * Generates a <code>KeyGenerator</code> object for the specified key
+ * algorithm from the specified provider.
+ *
+ * @param algorithm the standard name of the requested key algorithm. See Appendix A in the
+ * Java Cryptography Extension API Specification &amp; Reference for information about standard
+ * algorithm names.
+ * @param provider the provider
+ * @return the new <code>KeyGenerator</code> object
+ * @exception NoSuchAlgorithmException if a key generator for the specified algorithm is not
+ * available from the specified provider.
+ */
+ public static final KeyGenerator getInstance(
+ String algorithm,
+ Provider provider)
+ throws NoSuchAlgorithmException
+ {
+ if (provider == null)
+ {
+ throw new IllegalArgumentException("No provider specified to KeyGenerator.getInstance()");
+ }
+
+ JCEUtil.Implementation imp = JCEUtil.getImplementation("KeyGenerator", algorithm, provider);
+
+ if (imp == null)
+ {
+ throw new NoSuchAlgorithmException(algorithm + " not found");
+ }
+
+ KeyGenerator keyGen = new KeyGenerator((KeyGeneratorSpi)imp.getEngine(), imp.getProvider(), algorithm);
+
+ return keyGen;
+ }
+
+ /**
+ * Generates a <code>KeyGenerator</code> object for the specified key
+ * algorithm from the specified provider.
+ *
+ * @param algorithm the standard name of the requested key algorithm. See Appendix A in the
+ * Java Cryptography Extension API Specification &amp; Reference for information about standard
+ * algorithm names.
+ * @param provider the name of the provider
+ * @return the new <code>KeyGenerator</code> object
+ * @exception NoSuchAlgorithmException if a key generator for the specified algorithm is not
+ * available from the specified provider.
+ * @exception NoSuchProviderException if the specified provider has not been configured.
+ */
+ public static final KeyGenerator getInstance(
+ String algorithm,
+ String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ if (provider == null)
+ {
+ throw new IllegalArgumentException("No provider specified to KeyGenerator.getInstance()");
+ }
+
+ JCEUtil.Implementation imp = JCEUtil.getImplementation("KeyGenerator", algorithm, provider);
+
+ if (imp == null)
+ {
+ throw new NoSuchAlgorithmException(algorithm + " not found");
+ }
+
+ KeyGenerator keyGen = new KeyGenerator((KeyGeneratorSpi)imp.getEngine(), imp.getProvider(), algorithm);
+
+ return keyGen;
+ }
+
+ /**
+ * Returns the provider of this <code>KeyGenerator</code> object.
+ *
+ * @return the provider of this <code>KeyGenerator</code> object
+ */
+ public final Provider getProvider()
+ {
+ return provider;
+ }
+
+ /**
+ * Initializes this key generator.
+ *
+ * @param random the source of randomness for this generator
+ */
+ public final void init(
+ SecureRandom random)
+ {
+ keyGenerator.engineInit(random);
+ }
+
+ /**
+ * Initializes this key generator with the specified parameter set.
+ * <p>
+ * If this key generator requires any random bytes, 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.)
+ *
+ * @param params the key generation parameters
+ * @exception InvalidAlgorithmParameterException if the given parameters are inappropriate
+ * for this key generator
+ */
+ public final void init(
+ AlgorithmParameterSpec params)
+ throws InvalidAlgorithmParameterException
+ {
+ keyGenerator.engineInit(params, new SecureRandom());
+ }
+
+ /**
+ * Initializes this key generator with the specified parameter set and a user-provided source of randomness.
+ *
+ * @param params the key generation parameters
+ * @param random the source of randomness for this key generator
+ * @exception InvalidAlgorithmParameterException if <code>params</code> is inappropriate for this key generator
+ */
+ public final void init(
+ AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidAlgorithmParameterException
+ {
+ keyGenerator.engineInit(params, random);
+ }
+
+ /**
+ * Initializes this key generator for a certain keysize.
+ * <p>
+ * If this key generator requires any random bytes, 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.)
+ *
+ * @param keysize the keysize. This is an algorithm-specific metric, specified in number of bits.
+ * @exception InvalidParameterException if the keysize is wrong or not supported.
+ */
+ public final void init(
+ int keysize)
+ {
+ keyGenerator.engineInit(keysize, new SecureRandom());
+ }
+
+ /**
+ * Initializes this key generator for a certain keysize, using a user-provided source of randomness.
+ *
+ * @param keysize the keysize. This is an algorithm-specific metric, specified in number of bits.
+ * @param random the source of randomness for this key generator
+ * @exception InvalidParameterException if the keysize is wrong or not supported.
+ */
+ public final void init(
+ int keysize,
+ SecureRandom random)
+ {
+ keyGenerator.engineInit(keysize, random);
+ }
+
+ /**
+ * Generates a secret key.
+ *
+ * @return the new key
+ */
+ public final SecretKey generateKey()
+ {
+ return keyGenerator.engineGenerateKey();
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/KeyGeneratorSpi.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/KeyGeneratorSpi.java
new file mode 100644
index 000000000..dc7ad3da1
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/KeyGeneratorSpi.java
@@ -0,0 +1,64 @@
+package javax.crypto;
+
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.InvalidParameterException;
+import java.security.InvalidAlgorithmParameterException;
+
+/**
+ * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
+ * for the <code>KeyGenerator</code> class.
+ * All the abstract methods in this class must be implemented by each
+ * cryptographic service provider who wishes to supply the implementation
+ * of a key generator for a particular algorithm.
+ *
+ * @see SecretKey
+ */
+public abstract class KeyGeneratorSpi
+{
+ public KeyGeneratorSpi()
+ {
+ }
+
+ /**
+ * Initializes the key generator.
+ *
+ * @param random the source of randomness for this generator
+ */
+ protected abstract void engineInit(
+ SecureRandom random);
+
+ /**
+ * Initializes the key generator with the specified parameter
+ * set and a user-provided source of randomness.
+ *
+ * @param params the key generation parameters
+ * @param random the source of randomness for this key generator
+ * @exception InvalidAlgorithmParameterException if <code>params</code> is
+ * inappropriate for this key generator
+ */
+ protected abstract void engineInit(
+ AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidAlgorithmParameterException;
+
+ /**
+ * Initializes this key generator for a certain keysize, using the given
+ * source of randomness.
+ *
+ * @param keysize the keysize. This is an algorithm-specific metric, specified in number of bits.
+ * @param random the source of randomness for this key generator.
+ * @exception InvalidParameterException if keysize is wrong or not supported.
+ */
+ protected abstract void engineInit(
+ int keysize,
+ SecureRandom random)
+ throws InvalidParameterException;
+
+ /**
+ * Generates a secret key.
+ *
+ * @return the new key.
+ */
+ protected abstract SecretKey engineGenerateKey();
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/Mac.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/Mac.java
new file mode 100644
index 000000000..9f6174d82
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/Mac.java
@@ -0,0 +1,443 @@
+package javax.crypto;
+
+import java.security.Provider;
+import java.security.Key;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.InvalidAlgorithmParameterException;
+
+/**
+ * This class provides the functionality of a "Message Authentication Code"
+ * (MAC) algorithm.
+ * <p>
+ * A MAC provides a way to check the integrity of information transmitted over
+ * or stored in an unreliable medium, based on a secret key. Typically, message
+ * authentication codes are used between two parties that share a secret
+ * key in order to validate information transmitted between these
+ * parties.
+ * <p>
+ * A MAC mechanism that is based on cryptographic hash functions is
+ * referred to as HMAC. HMAC can be used with any cryptographic hash function,
+ * e.g., MD5 or SHA-1, in combination with a secret shared key. HMAC is
+ * specified in RFC 2104.
+ */
+public class Mac
+ implements Cloneable
+{
+ MacSpi macSpi;
+ Provider provider;
+ String algorithm;
+
+ private boolean initialised = false;
+
+ /**
+ * Creates a MAC object.
+ *
+ * @param macSpi the delegate
+ * @param provider the provider
+ * @param algorithm the algorithm
+ */
+ protected Mac(
+ MacSpi macSpi,
+ Provider provider,
+ String algorithm)
+ {
+ this.macSpi = macSpi;
+ this.provider = provider;
+ this.algorithm = algorithm;
+ }
+
+ /**
+ * Returns the algorithm name of this <code>Mac</code> object.
+ * <p>
+ * This is the same name that was specified in one of the
+ * <code>getInstance</code> calls that created this <code>Mac</code> object.
+ *
+ * @return the algorithm name of this <code>Mac</code> object.
+ */
+ public final String getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ /**
+ * Generates an <code>Mac</code> object that implements the
+ * specified MAC algorithm.
+ * If the default provider package provides an implementation of the
+ * requested MAC algorithm, an instance of
+ * <code>Mac</code> containing that implementation is returned.
+ * If the algorithm is not available in the default provider package,
+ * other provider packages are searched.
+ *
+ * @param algorithm the standard name of the requested MAC algorithm.
+ * See Appendix A in the Java Cryptography Extension API Specification &amp; Reference
+ * for information about standard algorithm names.
+ * @return the new <code>Mac</code> object.
+ * @exception NoSuchAlgorithmException if the specified algorithm is not
+ * available in the default provider package or any of the other provider
+ * packages that were searched.
+ */
+ public static final Mac getInstance(
+ String algorithm)
+ throws NoSuchAlgorithmException
+ {
+ try
+ {
+ JCEUtil.Implementation imp = JCEUtil.getImplementation("Mac", algorithm, (String) null);
+
+ if (imp == null)
+ {
+ throw new NoSuchAlgorithmException(algorithm + " not found");
+ }
+
+ Mac mac = new Mac((MacSpi)imp.getEngine(), imp.getProvider(), algorithm);
+
+ return mac;
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new NoSuchAlgorithmException(algorithm + " not found");
+ }
+ }
+
+ /**
+ * Generates an <code>Mac</code> object for the specified MAC
+ * algorithm from the specified provider.
+ *
+ * @param algorithm the standard name of the requested MAC algorithm.
+ * See Appendix A in the Java Cryptography Extension API Specification &amp; Reference
+ * for information about standard algorithm names.
+ * @param provider the name of the provider.
+ * @return the new <code>Mac</code> object.
+ * @exception NoSuchAlgorithmException if the specified algorithm is not available from the
+ * specified provider.
+ * @exception NoSuchProviderException if the specified provider has not been configured.
+ */
+ public static final Mac getInstance(
+ String algorithm,
+ String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ if (provider == null)
+ {
+ throw new IllegalArgumentException("No provider specified to Mac.getInstance()");
+ }
+
+ JCEUtil.Implementation imp = JCEUtil.getImplementation("Mac", algorithm, provider);
+
+ if (imp == null)
+ {
+ throw new NoSuchAlgorithmException(algorithm + " not found");
+ }
+
+ Mac mac = new Mac((MacSpi)imp.getEngine(), imp.getProvider(), algorithm);
+
+ return mac;
+ }
+
+ /**
+ * Generates an <code>Mac</code> object for the specified MAC
+ * algorithm from the specified provider.
+ *
+ * @param algorithm the standard name of the requested MAC algorithm.
+ * See Appendix A in the Java Cryptography Extension API Specification &amp; Reference
+ * for information about standard algorithm names.
+ * @param provider the provider.
+ * @return the new <code>Mac</code> object.
+ * @exception NoSuchAlgorithmException if the specified algorithm is not available from the
+ * specified provider.
+ */
+ public static final Mac getInstance(
+ String algorithm,
+ Provider provider)
+ throws NoSuchAlgorithmException
+ {
+ if (provider == null)
+ {
+ throw new IllegalArgumentException("No provider specified to Mac.getInstance()");
+ }
+
+ JCEUtil.Implementation imp = JCEUtil.getImplementation("Mac", algorithm, provider);
+
+ if (imp == null)
+ {
+ throw new NoSuchAlgorithmException(algorithm + " not found");
+ }
+
+ Mac mac = new Mac((MacSpi)imp.getEngine(), imp.getProvider(), algorithm);
+
+ return mac;
+ }
+
+ /**
+ * Returns the provider of this <code>Mac</code> object.
+ *
+ * @return the provider of this <code>Mac</code> object.
+ */
+ public final Provider getProvider()
+ {
+ return provider;
+ }
+
+ /**
+ * Returns the length of the MAC in bytes.
+ *
+ * @return the MAC length in bytes.
+ */
+ public final int getMacLength()
+ {
+ return macSpi.engineGetMacLength();
+ }
+
+ /**
+ * Initializes this <code>Mac</code> object with the given key.
+ *
+ * @param key the key.
+ * @exception InvalidKeyException if the given key is inappropriate for initializing this MAC.
+ */
+ public final void init(
+ Key key)
+ throws InvalidKeyException
+ {
+ try
+ {
+ macSpi.engineInit(key, null);
+ initialised = true;
+ }
+ catch (InvalidAlgorithmParameterException e)
+ {
+ throw new IllegalArgumentException("underlying mac waon't work without an AlgorithmParameterSpec");
+ }
+ }
+
+ /**
+ * Initializes this <code>Mac</code> object with the given key and
+ * algorithm parameters.
+ *
+ * @param key the key.
+ * @param params the algorithm parameters.
+ * @exception InvalidKeyException if the given key is inappropriate for initializing this MAC.
+ * @exception InvalidAlgorithmParameterException if the given algorithm parameters are inappropriate
+ * for this MAC.
+ */
+ public final void init(
+ Key key,
+ AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ macSpi.engineInit(key, params);
+ initialised = true;
+ }
+
+ /**
+ * Processes the given byte.
+ *
+ * @param input the input byte to be processed.
+ * @exception IllegalStateException if this <code>Mac</code> has not been initialized.
+ */
+ public final void update(
+ byte input)
+ throws IllegalStateException
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException("MAC not initialised");
+ }
+
+ macSpi.engineUpdate(input);
+ }
+
+ /**
+ * Processes the given array of bytes.
+ *
+ * @param input the array of bytes to be processed.
+ * @exception IllegalStateException if this <code>Mac</code> has not been initialized.
+ */
+ public final void update(
+ byte[] input)
+ throws IllegalStateException
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException("MAC not initialised");
+ }
+
+ if (input == null)
+ {
+ return;
+ }
+
+ macSpi.engineUpdate(input, 0, input.length);
+ }
+
+ /**
+ * Processes the first <code>len</code> bytes in <code>input</code>,
+ * starting at <code>offset</code> inclusive.
+ *
+ * @param input the input buffer.
+ * @param offset the offset in <code>input</code> where the input starts.
+ * @param len the number of bytes to process.
+ * @exception IllegalStateException if this <code>Mac</code> has not been initialized.
+ */
+ public final void update(
+ byte[] input,
+ int offset,
+ int len)
+ throws IllegalStateException
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException("MAC not initialised");
+ }
+
+ if (input == null)
+ {
+ throw new IllegalArgumentException("Null input passed");
+ }
+
+ if (len < 0 || offset < 0 || len > (input.length - offset))
+ {
+ throw new IllegalArgumentException("Bad offset/len");
+ }
+
+ if (input.length == 0)
+ {
+ return;
+ }
+
+ macSpi.engineUpdate(input, offset, len);
+ }
+
+ /**
+ * Finishes the MAC operation.
+ * <p>
+ * A call to this method resets this <code>Mac</code> object to the
+ * state it was in when previously initialized via a call to <code>init(Key)</code> or
+ * <code>init(Key, AlgorithmParameterSpec)</code>.
+ * That is, the object is reset and available to generate another MAC from
+ * the same key, if desired, via new calls to <code>update</code> and
+ * <code>doFinal</code>.
+ * (In order to reuse this <code>Mac</code> object with a different key,
+ * it must be reinitialized via a call to <code>init(Key)</code> or
+ * <code>init(Key, AlgorithmParameterSpec)</code>.
+ *
+ * @return the MAC result.
+ * @exception IllegalStateException if this <code>Mac</code> has not been initialized.
+ */
+ public final byte[] doFinal()
+ throws IllegalStateException
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException("MAC not initialised");
+ }
+
+ return macSpi.engineDoFinal();
+ }
+
+ /**
+ * Finishes the MAC operation.
+ *
+ * <p>A call to this method resets this <code>Mac</code> object to the
+ * state it was in when previously initialized via a call to
+ * <code>init(Key)</code> or
+ * <code>init(Key, AlgorithmParameterSpec)</code>.
+ * That is, the object is reset and available to generate another MAC from
+ * the same key, if desired, via new calls to <code>update</code> and
+ * <code>doFinal</code>.
+ * (In order to reuse this <code>Mac</code> object with a different key,
+ * it must be reinitialized via a call to <code>init(Key)</code> or
+ * <code>init(Key, AlgorithmParameterSpec)</code>.
+ * <p>
+ * The MAC result is stored in <code>output</code>, starting at
+ * <code>outOffset</code> inclusive.
+ *
+ * @param output the buffer where the MAC result is stored
+ * @param outOffset the offset in <code>output</code> where the MAC is stored
+ * @exception ShortBufferException if the given output buffer is too small to hold the result
+ * @exception IllegalStateException if this <code>Mac</code> has not been initialized.
+ */
+ public final void doFinal(
+ byte[] output,
+ int outOffset)
+ throws ShortBufferException, IllegalStateException
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException("MAC not initialised");
+ }
+
+ if ((output.length - outOffset) < macSpi.engineGetMacLength())
+ {
+ throw new ShortBufferException("buffer to short for MAC output");
+ }
+
+ byte[] mac = macSpi.engineDoFinal();
+
+ System.arraycopy(mac, 0, output, outOffset, mac.length);
+ }
+
+ /**
+ * Processes the given array of bytes and finishes the MAC operation.
+ * <p>
+ * A call to this method resets this <code>Mac</code> object to the
+ * state it was in when previously initialized via a call to <code>init(Key)</code> or
+ * <code>init(Key, AlgorithmParameterSpec)</code>. That is, the object is reset and
+ * available to generate another MAC from the same key, if desired, via new calls to
+ * <code>update</code> and <code>doFinal</code>.
+ * (In order to reuse this <code>Mac</code> object with a different key,
+ * it must be reinitialized via a call to <code>init(Key)</code> or
+ * <code>init(Key, AlgorithmParameterSpec)</code>.
+ *
+ * @return the MAC result.
+ * @exception IllegalStateException if this <code>Mac</code> has not been initialized.
+ */
+ public final byte[] doFinal(
+ byte[] input)
+ throws IllegalStateException
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException("MAC not initialised");
+ }
+
+ macSpi.engineUpdate(input, 0, input.length);
+
+ return macSpi.engineDoFinal();
+ }
+
+ /**
+ * Resets this <code>Mac</code> object.
+ * <p>
+ * A call to this method resets this <code>Mac</code> object to the
+ * state it was in when previously initialized via a call to
+ * <code>init(Key)</code> or <code>init(Key, AlgorithmParameterSpec)</code>.
+ * That is, the object is reset and available to generate another MAC from
+ * the same key, if desired, via new calls to <code>update</code> and
+ * <code>doFinal</code>.
+ * (In order to reuse this <code>Mac</code> object with a different key,
+ * it must be reinitialized via a call to <code>init(Key)</code> or
+ * <code>init(Key, AlgorithmParameterSpec)</code>.
+ */
+ public final void reset()
+ {
+ macSpi.engineReset();
+ }
+
+ /**
+ * Returns a clone if the provider implementation is cloneable.
+ *
+ * @return a clone if the provider implementation is cloneable.
+ * @exception CloneNotSupportedException if this is called on a delegate that does
+ * not support <code>Cloneable</code>.
+ */
+ public final Object clone()
+ throws CloneNotSupportedException
+ {
+ Mac result = new Mac((MacSpi)macSpi.clone(), provider, algorithm);
+ result.initialised = initialised;
+ return result;
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/MacSpi.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/MacSpi.java
new file mode 100644
index 000000000..d618ee536
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/MacSpi.java
@@ -0,0 +1,92 @@
+package javax.crypto;
+
+import java.security.Key;
+import java.security.InvalidKeyException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
+ * for the <code>Mac</code> class.
+ * All the abstract methods in this class must be implemented by each
+ * cryptographic service provider who wishes to supply the implementation
+ * of a particular MAC algorithm.
+ * <p>
+ * Implementations are free to implement the Cloneable interface.
+ */
+public abstract class MacSpi
+{
+ public MacSpi()
+ {
+ }
+
+ /**
+ * Returns the length of the MAC in bytes.
+ *
+ * @return the MAC length in bytes.
+ */
+ protected abstract int engineGetMacLength();
+
+ /**
+ * Initializes the MAC with the given (secret) key and algorithm
+ * parameters.
+ *
+ * @param key - the (secret) key.
+ * @param params - the algorithm parameters.
+ * @exception InvalidKeyException if the given key is inappropriate for initializing this MAC.
+ * @exception InvalidAlgorithmParameterException - if the given algorithm parameters are inappropriate
+ * for this MAC.
+ */
+ protected abstract void engineInit(
+ Key key,
+ AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException;
+
+ /**
+ * Processes the given byte.
+ *
+ * @param input - the input byte to be processed.
+ */
+ protected abstract void engineUpdate(
+ byte input);
+
+ /**
+ * Processes the first <code>len</code> bytes in <code>input</code>,
+ * starting at <code>offset</code> inclusive.
+ *
+ * @param input the input buffer.
+ * @param offset the offset in <code>input</code> where the input starts.
+ * @param len the number of bytes to process.
+ */
+ protected abstract void engineUpdate(
+ byte[] input,
+ int offset,
+ int len);
+
+ /**
+ * Completes the MAC computation and resets the MAC for further use,
+ * maintaining the secret key that the MAC was initialized with.
+ *
+ * @return the MAC result.
+ */
+ protected abstract byte[] engineDoFinal();
+
+ /**
+ * Resets the MAC for further use, maintaining the secret key that the
+ * MAC was initialized with.
+ */
+ protected abstract void engineReset();
+
+ /**
+ * Returns a clone if the implementation is cloneable.
+ *
+ * @return a clone if the implementation is cloneable.
+ * @exception CloneNotSupportedException if this is called on an implementation that does not support
+ * <code>Cloneable</code>.
+ */
+ public Object clone()
+ throws CloneNotSupportedException
+ {
+ throw new CloneNotSupportedException("Underlying MAC does not support cloning");
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/NoSuchPaddingException.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/NoSuchPaddingException.java
new file mode 100644
index 000000000..621732aa3
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/NoSuchPaddingException.java
@@ -0,0 +1,36 @@
+package javax.crypto;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * This exception is thrown when a particular padding mechanism is
+ * requested but is not available in the environment.
+ */
+public class NoSuchPaddingException
+ extends GeneralSecurityException
+{
+ private static final long serialVersionUID = -4572885201200175466L;
+
+ /**
+ * Constructs a NoSuchPaddingException with no detail
+ * message. A detail message is a String that describes this
+ * particular exception.
+ */
+ public NoSuchPaddingException()
+ {
+ }
+
+ /**
+ * Constructs a NoSuchPaddingException with the specified
+ * detail message. A detail message is a String that describes
+ * this particular exception, which may, for example, specify which
+ * algorithm is not available.
+ *
+ * @param msg - the detail message.
+ */
+ public NoSuchPaddingException(
+ String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/NullCipher.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/NullCipher.java
new file mode 100644
index 000000000..bb1ac7560
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/NullCipher.java
@@ -0,0 +1,240 @@
+package javax.crypto;
+
+import java.security.Key;
+import java.security.SecureRandom;
+import java.security.InvalidKeyException;
+import java.security.AlgorithmParameters;
+import java.security.NoSuchAlgorithmException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * The NullCipher class is a class that provides an
+ * "identity cipher" -- one that does not tranform the plaintext. As
+ * a consequence, the ciphertext is identical to the plaintext. All
+ * initialization methods do nothing, while the blocksize is set to 1
+ * byte.
+ *
+ * @since JCE1.2
+ */
+public class NullCipher
+ extends Cipher
+{
+ static private class NullCipherSpi
+ extends CipherSpi
+ {
+ /**
+ * Sets the mode of this cipher - no op.
+ */
+ protected void engineSetMode(
+ String mode)
+ throws NoSuchAlgorithmException
+ {
+ }
+
+ /**
+ * Sets the padding mechanism of this cipher - no op.
+ */
+ protected void engineSetPadding(
+ String padding)
+ throws NoSuchPaddingException
+ {
+ }
+
+ /**
+ * Returns the block size (in bytes) - 1
+ */
+ protected int engineGetBlockSize()
+ {
+ return 1;
+ }
+
+ /**
+ * 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).
+ *
+ * @param inputLen the input length (in bytes)
+ * @return the required output buffer size (in bytes)
+ */
+ protected int engineGetOutputSize(
+ int inputLen)
+ {
+ return inputLen;
+ }
+
+ /**
+ * Returns the initialization vector (IV) in a new buffer.
+ *
+ * @return null
+ */
+ protected byte[] engineGetIV()
+ {
+ return null;
+ }
+
+ /**
+ * Returns the parameters used with this cipher - null
+ */
+ protected AlgorithmParameters engineGetParameters()
+ {
+ return null;
+ }
+
+ /**
+ * Initializes this cipher with a key and a source
+ * of randomness - no op.
+ */
+ protected void engineInit(
+ int opmode,
+ Key key,
+ SecureRandom random)
+ throws InvalidKeyException
+ {
+ }
+
+ /**
+ * Initializes this cipher with a key, a set of
+ * algorithm parameters, and a source of randomness - no op.
+ */
+ protected void engineInit(
+ int opmode,
+ Key key,
+ AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ }
+
+ /**
+ * Initializes this cipher with a key, a set of
+ * algorithm parameters, and a source of randomness - no op.
+ */
+ protected void engineInit(
+ int opmode,
+ Key key,
+ AlgorithmParameters params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ }
+
+ /**
+ * Continues a multiple-part encryption or decryption operation
+ * (depending on how this cipher was initialized), processing another data
+ * part - in this case just return a copy of the input.
+ */
+ protected byte[] engineUpdate(
+ byte[] input,
+ int inputOffset,
+ int inputLen)
+ {
+ if (input == null)
+ {
+ return null;
+ }
+
+ byte[] tmp = new byte[inputLen];
+
+ System.arraycopy(input, inputOffset, tmp, 0, inputLen);
+
+ return tmp;
+ }
+
+ /**
+ * Continues a multiple-part encryption or decryption operation
+ * (depending on how this cipher was initialized), processing another data
+ * part - in this case just copy the input to the output.
+ */
+ protected int engineUpdate(
+ byte[] input,
+ int inputOffset,
+ int inputLen,
+ byte[] output,
+ int outputOffset)
+ throws ShortBufferException
+ {
+ if (input == null)
+ {
+ return 0;
+ }
+
+ if ((output.length - outputOffset) < inputLen)
+ {
+ throw new ShortBufferException("output buffer to short for NullCipher");
+ }
+
+ System.arraycopy(input, inputOffset, output, outputOffset, inputLen);
+
+ return 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
+ * - in this case just return a copy of the input.
+ */
+ protected byte[] engineDoFinal(
+ byte[] input,
+ int inputOffset,
+ int inputLen)
+ throws IllegalBlockSizeException, BadPaddingException
+ {
+ if (input == null)
+ {
+ return new byte[0];
+ }
+
+ byte[] tmp = new byte[inputLen];
+
+ System.arraycopy(input, inputOffset, tmp, 0, inputLen);
+
+ return tmp;
+ }
+
+ /**
+ * 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.
+ */
+ protected int engineDoFinal(
+ byte[] input,
+ int inputOffset,
+ int inputLen,
+ byte[] output,
+ int outputOffset)
+ throws ShortBufferException, IllegalBlockSizeException, BadPaddingException
+ {
+ if (input == null)
+ {
+ return 0;
+ }
+
+ if ((output.length - outputOffset) < inputLen)
+ {
+ throw new ShortBufferException("output buffer too short for NullCipher");
+ }
+
+ System.arraycopy(input, inputOffset, output, outputOffset, inputLen);
+
+ return inputLen;
+ }
+
+ /**
+ * Returns the key size of the given key object - 0
+ */
+ protected int engineGetKeySize(
+ Key key)
+ throws InvalidKeyException
+ {
+ return 0;
+ }
+ }
+
+ public NullCipher()
+ {
+ super(new NullCipherSpi(), null, "NULL");
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/SealedObject.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/SealedObject.java
new file mode 100644
index 000000000..576c03bd3
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/SealedObject.java
@@ -0,0 +1,302 @@
+package javax.crypto;
+
+import java.io.*;
+import java.security.*;
+
+/**
+ * This class enables a programmer to create an object and protect its
+ * confidentiality with a cryptographic algorithm.
+ *
+ * <p>
+ * Given any Serializable object, one can create a SealedObject
+ * that encapsulates the original object, in serialized
+ * format (i.e., a "deep copy"), and seals (encrypts) its serialized contents,
+ * using a cryptographic algorithm such as DES, to protect its
+ * confidentiality. The encrypted content can later be decrypted (with
+ * the corresponding algorithm using the correct decryption key) and
+ * de-serialized, yielding the original object.
+ *
+ * <p>
+ * Note that the Cipher object must be fully initialized with the
+ * correct algorithm, key, padding scheme, etc., before being applied
+ * to a SealedObject.
+ *
+ * <p>
+ * The original object that was sealed can be recovered in two different
+ * ways:
+ * <p>
+ *
+ * <ul>
+ *
+ * <li>by using the <a href="#getObject(javax.crypto.Cipher)">getObject</a>
+ * method that takes a <code>Cipher</code> object.
+ *
+ * <p>
+ * This method requires a fully initialized <code>Cipher</code> object,
+ * initialized with the
+ * exact same algorithm, key, padding scheme, etc., that were used to seal the
+ * object.
+ *
+ * <p>
+ * This approach has the advantage that the party who unseals the
+ * sealed object does not require knowledge of the decryption key. For example,
+ * after one party has initialized the cipher object with the required
+ * decryption key, it could hand over the cipher object to
+ * another party who then unseals the sealed object.
+ *
+ * <p>
+ *
+ * <li>by using one of the
+ * <a href="#getObject(java.security.Key)">getObject</a> methods
+ * that take a <code>Key</code> object.
+ *
+ * <p> In this approach, the <code>getObject</code> method creates a cipher
+ * object for the appropriate decryption algorithm and initializes it with the
+ * given decryption key and the algorithm parameters (if any) that were stored
+ * in the sealed object.
+ *
+ * <p> This approach has the advantage that the party who
+ * unseals the object does not need to keep track of the parameters (e.g., an
+ * IV) that were used to seal the object.
+ *
+ * </ul>
+ *
+ * @see Cipher
+ */
+public class SealedObject
+ implements Serializable
+{
+ private static final long serialVersionUID = 4482838265551344752L;
+
+ private byte[] encodedParams;
+ private byte[] encryptedContent;
+ private String paramsAlg;
+ private String sealAlg;
+
+ /**
+ * Constructs a SealedObject from any Serializable object.
+ * <p>
+ * The given object is serialized, and its serialized contents are
+ * encrypted using the given Cipher, which must be fully initialized.
+ * <p>
+ * Any algorithm parameters that may be used in the encryption
+ * operation are stored inside of the new <code>SealedObject</code>.
+ *
+ * @param object the object to be sealed.
+ * @param c the cipher used to seal the object.
+ * @exception IOException if an error occurs during serialization
+ * @exception IllegalBlockSizeException if the given cipher is a block
+ * cipher, no padding has been requested, and the total input length
+ * (i.e., the length of the serialized object contents) is not a multiple
+ * of the cipher's block size
+ */
+ public SealedObject(
+ Serializable object,
+ Cipher c)
+ throws IOException, IllegalBlockSizeException
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ObjectOutputStream oOut = new ObjectOutputStream(bOut);
+ oOut.writeObject(object);
+ oOut.close();
+ byte[] encodedObject = bOut.toByteArray();
+
+ if (c == null)
+ {
+ throw new IllegalArgumentException("cipher object is null!");
+ }
+
+ try
+ {
+ this.encryptedContent = c.doFinal(encodedObject);
+ }
+ catch (BadPaddingException e)
+ {
+ // should not happen
+ throw new IOException(e.getMessage());
+ }
+
+ this.sealAlg = c.getAlgorithm();
+ AlgorithmParameters params = c.getParameters();
+ if (params != null)
+ {
+ this.encodedParams = params.getEncoded();
+ this.paramsAlg = params.getAlgorithm();
+ }
+ }
+
+ /**
+ * Returns the algorithm that was used to seal this object.
+ *
+ * @return the algorithm that was used to seal this object.
+ */
+ public final String getAlgorithm()
+ {
+ return sealAlg;
+ }
+
+ /**
+ * Retrieves the original (encapsulated) object.
+ * <p>
+ * This method creates a cipher for the algorithm that had been used in
+ * the sealing operation.
+ * If the default provider package provides an implementation of that
+ * algorithm, an instance of Cipher containing that implementation is used.
+ * If the algorithm is not available in the default package, other
+ * packages are searched.
+ * The Cipher object is initialized for decryption, using the given
+ * <code>key</code> and the parameters (if any) that had been used in the
+ * sealing operation.
+ * <p>
+ * The encapsulated object is unsealed and de-serialized, before it is
+ * returned.
+ *
+ * @param key the key used to unseal the object.
+ * @return the original object.
+ * @exception IOException if an error occurs during de-serialiazation.
+ * @exception ClassNotFoundException if an error occurs during de-serialiazation.
+ * @exception NoSuchAlgorithmException if the algorithm to unseal the object is not available.
+ * @exception InvalidKeyException if the given key cannot be used to unseal
+ * the object (e.g., it has the wrong algorithm).
+ */
+ public final Object getObject(
+ Key key)
+ throws IOException, ClassNotFoundException, NoSuchAlgorithmException, InvalidKeyException
+ {
+ if (key == null)
+ {
+ throw new IllegalArgumentException("key object is null!");
+ }
+
+ try
+ {
+ return getObject(key, null);
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new NoSuchAlgorithmException(e.getMessage());
+ }
+ }
+
+ /**
+ * Retrieves the original (encapsulated) object.
+ * <p>
+ * The encapsulated object is unsealed (using the given Cipher,
+ * assuming that the Cipher is already properly initialized) and
+ * de-serialized, before it is returned.
+ *
+ * @param c the cipher used to unseal the object
+ * @return the original object.
+ * @exception IOException if an error occurs during de-serialiazation
+ * @exception ClassNotFoundException if an error occurs during de-serialiazation
+ * @exception IllegalBlockSizeException if the given cipher is a block
+ * cipher, no padding has been requested, and the total input length is
+ * not a multiple of the cipher's block size
+ * @exception BadPaddingException if the given cipher has been
+ * initialized for decryption, and padding has been specified, but
+ * the input data does not have proper expected padding bytes
+ */
+ public final Object getObject(
+ Cipher c)
+ throws IOException, ClassNotFoundException, IllegalBlockSizeException, BadPaddingException
+ {
+ if (c == null)
+ {
+ throw new IllegalArgumentException("cipher object is null!");
+ }
+
+ byte[] encodedObject = c.doFinal(encryptedContent);
+ ObjectInputStream oIn = new ObjectInputStream(
+ new ByteArrayInputStream(encodedObject));
+ return oIn.readObject();
+ }
+
+ /**
+ * Retrieves the original (encapsulated) object.
+ * <p>
+ * This method creates a cipher for the algorithm that had been used in
+ * the sealing operation, using an implementation of that algorithm from
+ * the given <code>provider</code>.
+ * The Cipher object is initialized for decryption, using the given
+ * <code>key</code> and the parameters (if any) that had been used in the
+ * sealing operation.
+ * <p>
+ * The encapsulated object is unsealed and de-serialized, before it is
+ * returned.
+ *
+ * @param key the key used to unseal the object.
+ * @param provider the name of the provider of the algorithm to unseal
+ * the object.
+ * @return the original object.
+ * @exception IOException if an error occurs during de-serialiazation.
+ * @exception ClassNotFoundException if an error occurs during
+ * de-serialization.
+ * @exception NoSuchAlgorithmException if the algorithm to unseal the
+ * object is not available.
+ * @exception NoSuchProviderException if the given provider is not
+ * configured.
+ * @exception InvalidKeyException if the given key cannot be used to unseal
+ * the object (e.g., it has the wrong algorithm).
+ */
+ public final Object getObject(
+ Key key,
+ String provider)
+ throws IOException, ClassNotFoundException,
+ NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException
+ {
+ if (key == null)
+ {
+ throw new IllegalArgumentException("key object is null!");
+ }
+
+ Cipher cipher = null;
+ try
+ {
+ if (provider != null)
+ {
+ cipher = Cipher.getInstance(sealAlg, provider);
+ }
+ else
+ {
+ cipher = Cipher.getInstance(sealAlg);
+ }
+ }
+ catch (NoSuchPaddingException e)
+ {
+ throw new NoSuchAlgorithmException(e.getMessage());
+ }
+
+ if (paramsAlg == null)
+ {
+ cipher.init(Cipher.DECRYPT_MODE, key);
+ }
+ else
+ {
+ AlgorithmParameters algParams =
+ AlgorithmParameters.getInstance(paramsAlg);
+ algParams.init(encodedParams);
+
+ try
+ {
+ cipher.init(Cipher.DECRYPT_MODE, key, algParams);
+ }
+ catch (InvalidAlgorithmParameterException e)
+ {
+ throw new IOException(e.getMessage());
+ }
+ }
+
+ try
+ {
+ return getObject(cipher);
+ }
+ catch (BadPaddingException e)
+ {
+ throw new IOException(e.getMessage());
+ }
+ catch (IllegalBlockSizeException e2)
+ {
+ throw new IOException(e2.getMessage());
+ }
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/SecretKey.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/SecretKey.java
new file mode 100644
index 000000000..8b22f02af
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/SecretKey.java
@@ -0,0 +1,28 @@
+package javax.crypto;
+
+import java.security.Key;
+
+/**
+ * A secret (symmetric) key.
+ * <p>
+ * This interface contains no methods or constants.
+ * Its only purpose is to group (and provide type safety for) secret keys.
+ * <p>
+ * Provider implementations of this interface must overwrite the
+ * <code>equals</code> and <code>hashCode</code> methods inherited from
+ * <code>java.lang.Object</code>, so that secret keys are compared based on
+ * their underlying key material and not based on reference.
+ * <p>
+ * Keys that implement this interface return the string <code>RAW</code>
+ * as their encoding format (see <code>getFormat</code>), and return the
+ * raw key bytes as the result of a <code>getEncoded</code> method call. (The
+ * <code>getFormat</code> and <code>getEncoded</code> methods are inherited
+ * from the <code>java.security.Key</code> parent interface.)
+ *
+ * @see SecretKeyFactory
+ * @see Cipher
+ */
+public abstract interface SecretKey
+ extends Key
+{
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/SecretKeyFactory.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/SecretKeyFactory.java
new file mode 100644
index 000000000..286f0b5f4
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/SecretKeyFactory.java
@@ -0,0 +1,245 @@
+package javax.crypto;
+
+import java.security.Provider;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.spec.KeySpec;
+import java.security.spec.InvalidKeySpecException;
+
+/**
+ * This class represents a factory for secret keys.
+ *
+ * <p>
+ * Key factories are used to convert <I>keys</I> (opaque
+ * cryptographic keys of type <code>Key</code>) into <I>key specifications</I>
+ * (transparent representations of the underlying key material), and vice versa.
+ * Secret key factories operate only on secret (symmetric) keys.
+ * <p>
+ * Key factories are bi-directional, i.e., they allow to build an opaque
+ * key object from a given key specification (key material), or to retrieve
+ * the underlying key material of a key object in a suitable format.
+ * <p>
+ * Application developers should refer to their provider's documentation
+ * to find out which key specifications are supported by the
+ * <a href="#generateSecret(java.security.spec.KeySpec)">generateSecret</a> and
+ * <a href="#getKeySpec(javax.crypto.SecretKey, java.lang.Class)">getKeySpec</a> methods.
+ * For example, the DES secret-key factory supplied by the "SunJCE" provider
+ * supports <code>DESKeySpec</code> as a transparent representation of DES
+ * keys, and that provider's secret-key factory for Triple DES keys supports
+ * <code>DESedeKeySpec</code> as a transparent representation of Triple DES keys.
+ *
+ * @see SecretKey
+ * @see javax.crypto.spec.DESKeySpec
+ * @see javax.crypto.spec.DESedeKeySpec
+ * @see javax.crypto.spec.PBEKeySpec
+ */
+public class SecretKeyFactory
+{
+ SecretKeyFactorySpi keyFacSpi;
+ Provider provider;
+ String algorithm;
+
+ /**
+ * Creates a SecretKeyFactory object.
+ *
+ * @param keyFacSpi the delegate
+ * @param provider the provider
+ * @param algorithm the secret-key algorithm
+ */
+ protected SecretKeyFactory(
+ SecretKeyFactorySpi keyFacSpi,
+ Provider provider,
+ String algorithm)
+ {
+ this.keyFacSpi = keyFacSpi;
+ this.provider = provider;
+ this.algorithm = algorithm;
+ }
+
+ /**
+ * Generates a <code>SecretKeyFactory</code> object for the specified secret-key algorithm.
+ * If the default provider package provides an implementation of the
+ * requested factory, an instance of <code>SecretKeyFactory</code>
+ * containing that implementation is returned.
+ * If the requested factory is not available in the default provider
+ * package, other provider packages are searched.
+ *
+ * @param algorithm the standard name of the requested secret-key algorithm.
+ * See Appendix A in the Java Cryptography Extension API Specification &amp; Reference </a>
+ * for information about standard algorithm names.
+ * @return a <code>SecretKeyFactory</code> object for the specified secret-key algorithm.
+ * @exception NoSuchAlgorithmException if a secret-key factory for the specified algorithm
+ * is not available in the default provider package or any of the other provider packages
+ * that were searched.
+ */
+ public static final SecretKeyFactory getInstance(
+ String algorithm)
+ throws NoSuchAlgorithmException
+ {
+ try
+ {
+ JCEUtil.Implementation imp = JCEUtil.getImplementation("SecretKeyFactory", algorithm, (String) null);
+
+ if (imp == null)
+ {
+ throw new NoSuchAlgorithmException(algorithm + " not found");
+ }
+
+ SecretKeyFactory keyFact = new SecretKeyFactory(
+ (SecretKeyFactorySpi)imp.getEngine(), imp.getProvider(), algorithm);
+
+ return keyFact;
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new NoSuchAlgorithmException(algorithm + " not found");
+ }
+ }
+
+ /**
+ * Generates a <code>SecretKeyFactory</code> object for the specified
+ * secret-key algorithm from the specified provider.
+ *
+ * @param algorithm the standard name of the requested secret-key algorithm.
+ * See Appendix A in the Java Cryptography Extension API Specification &amp; Reference
+ * for information about standard algorithm names.
+ * @param provider the name of the provider.
+ * @return a <code>SecretKeyFactory</code> object for the specified secret-key algorithm.
+ * @exception NoSuchAlgorithmException if a secret-key factory for the specified algorithm is not
+ * available from the specified provider.
+ * @exception NoSuchProviderException if the specified provider has not been configured.
+ */
+ public static final SecretKeyFactory getInstance(
+ String algorithm,
+ String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ if (provider == null)
+ {
+ throw new IllegalArgumentException("No provider specified to SecretKeyFactory.getInstance()");
+ }
+
+ JCEUtil.Implementation imp = JCEUtil.getImplementation("SecretKeyFactory", algorithm, provider);
+
+ if (imp == null)
+ {
+ throw new NoSuchAlgorithmException(algorithm + " not found");
+ }
+
+ SecretKeyFactory keyFact = new SecretKeyFactory(
+ (SecretKeyFactorySpi)imp.getEngine(), imp.getProvider(), algorithm);
+
+ return keyFact;
+ }
+
+ /**
+ * Generates a <code>SecretKeyFactory</code> object for the specified
+ * secret-key algorithm from the specified provider.
+ *
+ * @param algorithm the standard name of the requested secret-key algorithm.
+ * See Appendix A in the Java Cryptography Extension API Specification &amp; Reference
+ * for information about standard algorithm names.
+ * @param provider the provider.
+ * @return a <code>SecretKeyFactory</code> object for the specified secret-key algorithm.
+ * @exception NoSuchAlgorithmException if a secret-key factory for the specified algorithm is not
+ * available from the specified provider.
+ */
+ public static final SecretKeyFactory getInstance(
+ String algorithm,
+ Provider provider)
+ throws NoSuchAlgorithmException
+ {
+ if (provider == null)
+ {
+ throw new IllegalArgumentException("No provider specified to SecretKeyFactory.getInstance()");
+ }
+
+ JCEUtil.Implementation imp = JCEUtil.getImplementation("SecretKeyFactory", algorithm, provider);
+
+ if (imp == null)
+ {
+ throw new NoSuchAlgorithmException(algorithm + " not found");
+ }
+
+ SecretKeyFactory keyFact = new SecretKeyFactory(
+ (SecretKeyFactorySpi)imp.getEngine(), imp.getProvider(), algorithm);
+
+ return keyFact;
+ }
+
+ /**
+ * Returns the provider of this <code>SecretKeyFactory</code> object.
+ *
+ * @return the provider of this <code>SecretKeyFactory</code> object
+ */
+ public final Provider getProvider()
+ {
+ return provider;
+ }
+
+ /**
+ * Returns the algorithm name of this <code>SecretKeyFactory</code> object.
+ * <p>
+ * This is the same name that was specified in one of the <code>getInstance</code> calls
+ * that created this <code>SecretKeyFactory</code> object.
+ *
+ * @return the algorithm name of this <code>SecretKeyFactory</code> object.
+ */
+ public final String getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ /**
+ * Generates a <code>SecretKey</code> object from the provided key specification (key material).
+ *
+ * @param keySpec the specification (key material) of the secret key
+ * @return the secret key
+ * @exception InvalidKeySpecException if the given key specification
+ * is inappropriate for this secret-key factory to produce a secret key.
+ */
+ public final SecretKey generateSecret(
+ KeySpec keySpec)
+ throws InvalidKeySpecException
+ {
+ return keyFacSpi.engineGenerateSecret(keySpec);
+ }
+
+ /**
+ * Returns a specification (key material) of the given key object
+ * in the requested format.
+ *
+ * @param key the key
+ * @param keySpec the requested format in which the key material shall be
+ * returned
+ * @return the underlying key specification (key material) in the requested format
+ * @exception InvalidKeySpecException if the requested key specification is inappropriate for
+ * the given key (e.g., the algorithms associated with <code>key</code> and <code>keySpec</code> do
+ * not match, or <code>key</code> references a key on a cryptographic hardware device whereas
+ * <code>keySpec</code> is the specification of a software-based key), or the given key cannot be dealt with
+ * (e.g., the given key has an algorithm or format not supported by this secret-key factory).
+ */
+ public final KeySpec getKeySpec(
+ SecretKey key,
+ Class keySpec)
+ throws InvalidKeySpecException
+ {
+ return keyFacSpi.engineGetKeySpec(key, keySpec);
+ }
+
+ /**
+ * Translates a key object, whose provider may be unknown or potentially
+ * untrusted, into a corresponding key object of this secret-key factory.
+ *
+ * @param key the key whose provider is unknown or untrusted
+ * @return the translated key
+ * @exception InvalidKeyException if the given key cannot be processed by this secret-key factory.
+ */
+ public final SecretKey translateKey(
+ SecretKey key)
+ throws InvalidKeyException
+ {
+ return keyFacSpi.engineTranslateKey(key);
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/SecretKeyFactorySpi.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/SecretKeyFactorySpi.java
new file mode 100644
index 000000000..b430f3bd3
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/SecretKeyFactorySpi.java
@@ -0,0 +1,72 @@
+package javax.crypto;
+
+import java.security.InvalidKeyException;
+import java.security.spec.KeySpec;
+import java.security.spec.InvalidKeySpecException;
+
+/**
+ * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
+ * for the <code>SecretKeyFactory</code> class.
+ * All the abstract methods in this class must be implemented by each
+ * cryptographic service provider who wishes to supply the implementation
+ * of a secret-key factory for a particular algorithm.
+ * <p>
+ * A provider should document all the key specifications supported by its
+ * secret key factory.
+ * For example, the DES secret-key factory supplied by the "SunJCE" provider
+ * supports <code>DESKeySpec</code> as a transparent representation of DES
+ * keys, and that provider's secret-key factory for Triple DES keys supports
+ * <code>DESedeKeySpec</code> as a transparent representation of Triple DES
+ * keys.
+ *
+ * @see SecretKey
+ * @see javax.crypto.spec.DESKeySpec
+ * @see javax.crypto.spec.DESedeKeySpec
+ */
+public abstract class SecretKeyFactorySpi
+{
+ public SecretKeyFactorySpi()
+ {
+ }
+
+ /**
+ * Generates a <code>SecretKey</code> object from the
+ * provided key specification (key material).
+ *
+ * @param keySpec the specification (key material) of the secret key
+ * @return the secret key
+ * @exception InvalidKeySpecException if the given key specification
+ * is inappropriate for this secret-key factory to produce a secret key.
+ */
+ protected abstract SecretKey engineGenerateSecret(
+ KeySpec keySpec)
+ throws InvalidKeySpecException;
+
+ /**
+ * Returns a specification (key material) of the given key object in the requested format.
+ *
+ * @param key the key
+ * @param keySpec the requested format in which the key material shall be returned
+ * @return the underlying key specification (key material) in the requested format
+ * @exception InvalidKeySpecException if the requested key specification is inappropriate for
+ * the given key (e.g., the algorithms associated with <code>key</code> and <code>keySpec</code> do
+ * not match, or <code>key</code> references a key on a cryptographic hardware device whereas
+ * <code>keySpec</code> is the specification of a software-based key), or the given key cannot be
+ * dealt with (e.g., the given key has an algorithm or format not supported by this secret-key factory).
+ */
+ protected abstract KeySpec engineGetKeySpec(
+ SecretKey key,
+ Class keySpec)
+ throws InvalidKeySpecException;
+
+ /**
+ * Translates a key object, whose provider may be unknown or potentially untrusted, into a
+ * corresponding key object of this secret-key factory.
+ *
+ * @param key the key whose provider is unknown or untrusted
+ * @return InvalidKeyException if the given key cannot be processed by this secret-key factory.
+ */
+ protected abstract SecretKey engineTranslateKey(
+ SecretKey key)
+ throws InvalidKeyException;
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/ShortBufferException.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/ShortBufferException.java
new file mode 100644
index 000000000..273a6cf5c
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/ShortBufferException.java
@@ -0,0 +1,36 @@
+package javax.crypto;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * This exception is thrown when an output buffer provided by the user
+ * is too short to hold the operation result.
+ */
+public class ShortBufferException
+ extends GeneralSecurityException
+{
+ private static final long serialVersionUID = 8427718640832943747L;
+
+ /**
+ * Constructs a ShortBufferException with no detail
+ * message. A detail message is a String that describes this
+ * particular exception.
+ */
+ public ShortBufferException()
+ {
+ }
+
+ /**
+ * Constructs a ShortBufferException with the specified
+ * detail message. A detail message is a String that describes
+ * this particular exception, which may, for example, specify which
+ * algorithm is not available.
+ *
+ * @param msg the detail message.
+ */
+ public ShortBufferException(
+ String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/interfaces/DHKey.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/interfaces/DHKey.java
new file mode 100644
index 000000000..5d404110f
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/interfaces/DHKey.java
@@ -0,0 +1,20 @@
+package javax.crypto.interfaces;
+
+import javax.crypto.spec.DHParameterSpec;
+
+/**
+ * The interface to a Diffie-Hellman key.
+ *
+ * @see DHParameterSpec
+ * @see DHPublicKey
+ * @see DHPrivateKey
+ */
+public abstract interface DHKey
+{
+ /**
+ * Returns the key parameters.
+ *
+ * @return the key parameters
+ */
+ public DHParameterSpec getParams();
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/interfaces/DHPrivateKey.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/interfaces/DHPrivateKey.java
new file mode 100644
index 000000000..3fc7de99b
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/interfaces/DHPrivateKey.java
@@ -0,0 +1,21 @@
+package javax.crypto.interfaces;
+
+import java.math.BigInteger;
+import java.security.PrivateKey;
+
+/**
+ * The interface to a Diffie-Hellman private key.
+ *
+ * @see DHKey
+ * @see DHPublicKey
+ */
+public abstract interface DHPrivateKey
+ extends DHKey, PrivateKey
+{
+ /**
+ * Returns the private value, <code>x</code>.
+ *
+ * @return the private value, <code>x</code>
+ */
+ public BigInteger getX();
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/interfaces/DHPublicKey.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/interfaces/DHPublicKey.java
new file mode 100644
index 000000000..3d395afa4
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/interfaces/DHPublicKey.java
@@ -0,0 +1,21 @@
+package javax.crypto.interfaces;
+
+import java.math.BigInteger;
+import java.security.PublicKey;
+
+/**
+ * The interface to a Diffie-Hellman public key.
+ *
+ * @see DHKey
+ * @see DHPrivateKey
+ */
+public abstract interface DHPublicKey
+ extends DHKey, PublicKey
+{
+ /**
+ * Returns the public value, <code>y</code>.
+ *
+ * @return the public value, <code>y</code>
+ */
+ public BigInteger getY();
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/interfaces/PBEKey.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/interfaces/PBEKey.java
new file mode 100644
index 000000000..8d9ab1f67
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/interfaces/PBEKey.java
@@ -0,0 +1,41 @@
+package javax.crypto.interfaces;
+
+import javax.crypto.SecretKey;
+
+/**
+ * The interface to a PBE key.
+ *
+ * @see PBEKeySpec, SecretKey
+ */
+public interface PBEKey
+ extends SecretKey
+{
+ /**
+ * Returns the password.
+ *
+ * Note: this method should return a copy of the password. It is the
+ * caller's responsibility to zero out the password information after it is
+ * no longer needed.
+ *
+ * @return the password.
+ */
+ public char[] getPassword();
+
+ /**
+ * Returns the salt or null if not specified.
+ *
+ * Note: this method should return a copy of the salt. It is the caller's
+ * responsibility to zero out the salt information after it is no longer
+ * needed.
+ *
+ * @return the salt.
+ */
+ public byte[] getSalt();
+
+ /**
+ * Returns the iteration count or 0 if not specified.
+ *
+ * @return the iteration count.
+ */
+ public int getIterationCount();
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/DESKeySpec.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/DESKeySpec.java
new file mode 100644
index 000000000..8509a5464
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/DESKeySpec.java
@@ -0,0 +1,194 @@
+package javax.crypto.spec;
+
+import java.security.InvalidKeyException;
+import java.security.spec.KeySpec;
+
+/**
+ * This class specifies a DES key.
+ */
+public class DESKeySpec
+ implements KeySpec
+{
+ public static final int DES_KEY_LEN = 8;
+
+ private byte[] keyBytes = new byte[DES_KEY_LEN];
+
+ /**
+ * Uses the first 8 bytes in <code>key</code> as the key material for the DES key.
+ * <p>
+ * The bytes that constitute the DES key are those between
+ * <code>key[0]</code> and <code>key[7]</code> inclusive.
+ *
+ * @param key - the buffer with the DES key material.
+ * @exception InvalidKeyException - if the given key material is shorter than 8 bytes.
+ */
+ public DESKeySpec(
+ byte[] key)
+ throws InvalidKeyException
+ {
+ if (key.length < DES_KEY_LEN)
+ {
+ throw new InvalidKeyException("DES key material too short in construction");
+ }
+
+ System.arraycopy(key, 0, keyBytes, 0, keyBytes.length);
+ }
+
+ /**
+ * Uses the first 8 bytes in <code>key</code>, beginning at
+ * <code>offset</code> inclusive, as the key material for the DES key.
+ * <p>
+ * The bytes that constitute the DES key are those between
+ * <code>key[offset]</code> and <code>key[offset+7]</code> inclusive.
+ *
+ * @param key the buffer with the DES key material.
+ * @param offset the offset in <code>key</code>, where the DES key material starts.
+ * @exception InvalidKeyException if the given key material, starting at
+ * <code>offset</code> inclusive, is shorter than 8 bytes.
+ */
+ public DESKeySpec(
+ byte[] key,
+ int offset)
+ throws InvalidKeyException
+ {
+ if ((key.length - offset) < DES_KEY_LEN)
+ {
+ throw new InvalidKeyException("DES key material too short in construction");
+ }
+
+ System.arraycopy(key, offset, keyBytes, 0, keyBytes.length);
+ }
+
+ /**
+ * Returns the DES key material.
+ *
+ * @return the DES key material.
+ */
+ public byte[] getKey()
+ {
+ byte[] tmp = new byte[DES_KEY_LEN];
+
+ System.arraycopy(keyBytes, 0, tmp, 0, tmp.length);
+
+ return tmp;
+ }
+
+ /**
+ * Checks if the given DES key material, starting at <code>offset</code>
+ * inclusive, is parity-adjusted.
+ *
+ * @param key the buffer with the DES key material.
+ * @param offset the offset in <code>key</code>, where the DES key material starts.
+ * @returns true if the given DES key material is parity-adjusted, false otherwise.
+ * @exception InvalidKeyException if the given key material, starting at <code>offset</code>
+ * inclusive, is shorter than 8 bytes.
+ */
+ public static boolean isParityAdjusted(
+ byte[] key,
+ int offset)
+ throws InvalidKeyException
+ {
+ if ((key.length - offset) < DES_KEY_LEN)
+ {
+ throw new InvalidKeyException("key material too short in DESKeySpec.isParityAdjusted");
+ }
+
+ for (int i = 0; i < DES_KEY_LEN; i++)
+ {
+ byte keyByte = key[i + offset];
+ int count = 0;
+
+ keyByte = (byte)((keyByte & 0xff) >> 1);
+
+ while (keyByte != 0)
+ {
+ /*
+ * we increment for every "on" bit
+ */
+ if ((keyByte & 0x01) != 0)
+ {
+ count++;
+ }
+
+ keyByte = (byte)((keyByte & 0xff) >> 1);
+ }
+
+ if ((count & 1) == 1)
+ {
+ if ((key[i + offset] & 1) == 1)
+ {
+ return false;
+ }
+ }
+ else if ((key[i + offset] & 1) != 1)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /*
+ * Table of weak and semi-weak keys taken from Schneier pp281
+ */
+ static private final int N_DES_WEAK_KEYS = 16;
+
+ static private byte[] DES_weak_keys =
+ {
+ /* weak keys */
+ (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01, (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01,
+ (byte)0x1f,(byte)0x1f,(byte)0x1f,(byte)0x1f, (byte)0x0e,(byte)0x0e,(byte)0x0e,(byte)0x0e,
+ (byte)0xe0,(byte)0xe0,(byte)0xe0,(byte)0xe0, (byte)0xf1,(byte)0xf1,(byte)0xf1,(byte)0xf1,
+ (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe, (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe,
+
+ /* semi-weak keys */
+ (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe, (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe,
+ (byte)0x1f,(byte)0xe0,(byte)0x1f,(byte)0xe0, (byte)0x0e,(byte)0xf1,(byte)0x0e,(byte)0xf1,
+ (byte)0x01,(byte)0xe0,(byte)0x01,(byte)0xe0, (byte)0x01,(byte)0xf1,(byte)0x01,(byte)0xf1,
+ (byte)0x1f,(byte)0xfe,(byte)0x1f,(byte)0xfe, (byte)0x0e,(byte)0xfe,(byte)0x0e,(byte)0xfe,
+ (byte)0x01,(byte)0x1f,(byte)0x01,(byte)0x1f, (byte)0x01,(byte)0x0e,(byte)0x01,(byte)0x0e,
+ (byte)0xe0,(byte)0xfe,(byte)0xe0,(byte)0xfe, (byte)0xf1,(byte)0xfe,(byte)0xf1,(byte)0xfe,
+ (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01, (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01,
+ (byte)0xe0,(byte)0x1f,(byte)0xe0,(byte)0x1f, (byte)0xf1,(byte)0x0e,(byte)0xf1,(byte)0x0e,
+ (byte)0xe0,(byte)0x01,(byte)0xe0,(byte)0x01, (byte)0xf1,(byte)0x01,(byte)0xf1,(byte)0x01,
+ (byte)0xfe,(byte)0x1f,(byte)0xfe,(byte)0x1f, (byte)0xfe,(byte)0x0e,(byte)0xfe,(byte)0x0e,
+ (byte)0x1f,(byte)0x01,(byte)0x1f,(byte)0x01, (byte)0x0e,(byte)0x01,(byte)0x0e,(byte)0x01,
+ (byte)0xfe,(byte)0xe0,(byte)0xfe,(byte)0xe0, (byte)0xfe,(byte)0xf1,(byte)0xfe,(byte)0xf1
+ };
+
+ /**
+ * Checks if the given DES key material is weak or semi-weak.
+ *
+ * @param key the buffer with the DES key material.
+ * @param offset the offset in <code>key</code>, where the DES key
+ * material starts.
+ * @return true if the given DES key material is weak or semi-weak, false otherwise.
+ * @exception InvalidKeyException if the given key material, starting at <code>offset</code>
+ * inclusive, is shorter than 8 bytes.
+ */
+ public static boolean isWeak(
+ byte[] key,
+ int offset)
+ throws InvalidKeyException
+ {
+ if (key.length - offset < DES_KEY_LEN)
+ {
+ throw new InvalidKeyException("key material too short in DESKeySpec.isWeak");
+ }
+
+ nextkey: for (int i = 0; i < N_DES_WEAK_KEYS; i++)
+ {
+ for (int j = 0; j < DES_KEY_LEN; j++)
+ {
+ if (key[j + offset] != DES_weak_keys[i * DES_KEY_LEN + j])
+ {
+ continue nextkey;
+ }
+ }
+
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/DESedeKeySpec.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/DESedeKeySpec.java
new file mode 100644
index 000000000..edfcd3c43
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/DESedeKeySpec.java
@@ -0,0 +1,100 @@
+package javax.crypto.spec;
+
+import java.security.InvalidKeyException;
+import java.security.spec.KeySpec;
+
+/**
+ * This class specifies a DES-EDE ("triple-DES") key.
+ */
+public class DESedeKeySpec
+ implements KeySpec
+{
+ public static final int DES_EDE_KEY_LEN = 24;
+
+ private byte[] keyBytes = new byte[DES_EDE_KEY_LEN];
+
+ /**
+ * Uses the first 24 bytes in <code>key</code> as the DES-EDE key.
+ * <p>
+ * The bytes that constitute the DES-EDE key are those between
+ * <code>key[0]</code> and <code>key[23]</code> inclusive
+ *
+ * @param key the buffer with the DES-EDE key material.
+ * @exception InvalidKeyException if the given key material is shorter
+ * than 24 bytes.
+ */
+ public DESedeKeySpec(
+ byte[] key)
+ throws InvalidKeyException
+ {
+ if (key.length < DES_EDE_KEY_LEN)
+ {
+ throw new InvalidKeyException("DESede key material too short in construction");
+ }
+
+ System.arraycopy(key, 0, keyBytes, 0, keyBytes.length);
+ }
+
+ /**
+ * Uses the first 24 bytes in <code>key</code>, beginning at
+ * <code>offset</code> inclusive, as the DES-EDE key.
+ * <p>
+ * The bytes that constitute the DES-EDE key are those between
+ * <code>key[offset]</code> and <code>key[offset+23]</code> inclusive.
+ * @param key the buffer with the DES-EDE key material.
+ * @param offset the offset in <code>key</code>, where the DES-EDE key
+ * material starts.
+ * @exception InvalidKeyException if the given key material, starting at
+ * <code>offset</code> inclusive, is shorter than 24 bytes
+ */
+ public DESedeKeySpec(
+ byte[] key,
+ int offset)
+ throws InvalidKeyException
+ {
+ if ((key.length - offset) < DES_EDE_KEY_LEN)
+ {
+ throw new InvalidKeyException("DESede key material too short in construction");
+ }
+
+ System.arraycopy(key, 0, keyBytes, 0, keyBytes.length);
+ }
+
+ /**
+ * Returns the DES-EDE key.
+ *
+ * @return the DES-EDE key
+ */
+ public byte[] getKey()
+ {
+ byte[] tmp = new byte[DES_EDE_KEY_LEN];
+
+ System.arraycopy(keyBytes, 0, tmp, 0, tmp.length);
+
+ return tmp;
+ }
+
+ /**
+ * Checks if the given DES-EDE key, starting at <code>offset</code>
+ * inclusive, is parity-adjusted.
+ *
+ * @return true if the given DES-EDE key is parity-adjusted, false
+ * otherwise
+ * @exception InvalidKeyException if the given key material, starting at
+ * <code>offset</code> inclusive, is shorter than 24 bytes
+ */
+ public static boolean isParityAdjusted(
+ byte[] key,
+ int offset)
+ throws InvalidKeyException
+ {
+ if ((key.length - offset) < DES_EDE_KEY_LEN)
+ {
+ throw new InvalidKeyException("key material too short in DESedeKeySpec.isParityAdjusted");
+ }
+
+ return (DESKeySpec.isParityAdjusted(key, offset)
+ && DESKeySpec.isParityAdjusted(key, offset + 8)
+ && DESKeySpec.isParityAdjusted(key, offset + 16));
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/DHGenParameterSpec.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/DHGenParameterSpec.java
new file mode 100644
index 000000000..56645d135
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/DHGenParameterSpec.java
@@ -0,0 +1,56 @@
+package javax.crypto.spec;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * This class specifies the set of parameters used for generating
+ * Diffie-Hellman (system) parameters for use in Diffie-Hellman key
+ * agreement. This is typically done by a central
+ * authority.
+ * <p>
+ * The central authority, after computing the parameters, must send this
+ * information to the parties looking to agree on a secret key.
+ */
+public class DHGenParameterSpec
+ implements AlgorithmParameterSpec
+{
+ private int primeSize;
+ private int exponentSize;
+
+ /**
+ * Constructs a parameter set for the generation of Diffie-Hellman
+ * (system) parameters. The constructed parameter set can be used to
+ * initialize an <a href="http://java.sun.com/products/jdk/1.2/docs/api/java.security.AlgorithmParameterGenerator.html"><code>AlgorithmParameterGenerator</code></a>
+ * object for the generation of Diffie-Hellman parameters.
+ *
+ * @param primeSize the size (in bits) of the prime modulus.
+ * @param exponentSize the size (in bits) of the random exponent.
+ */
+ public DHGenParameterSpec(
+ int primeSize,
+ int exponentSize)
+ {
+ this.primeSize = primeSize;
+ this.exponentSize = exponentSize;
+ }
+
+ /**
+ * Returns the size in bits of the prime modulus.
+ *
+ * @return the size in bits of the prime modulus
+ */
+ public int getPrimeSize()
+ {
+ return primeSize;
+ }
+
+ /**
+ * Returns the size in bits of the random exponent (private value).
+ *
+ * @return the size in bits of the random exponent (private value)
+ */
+ public int getExponentSize()
+ {
+ return exponentSize;
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/DHParameterSpec.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/DHParameterSpec.java
new file mode 100644
index 000000000..2eceba4ce
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/DHParameterSpec.java
@@ -0,0 +1,95 @@
+package javax.crypto.spec;
+
+import java.math.BigInteger;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * This class specifies the set of parameters used with the Diffie-Hellman
+ * algorithm, as specified in PKCS #3: <i>Diffie-Hellman Key-Agreement
+ * Standard</i>.
+ * <p>
+ * A central authority generates parameters and gives them to the two
+ * entities seeking to generate a secret key. The parameters are a prime
+ * <code>p</code>, a base <code>g</code>, and optionally the length
+ * in bits of the private value, <code>l</code>.
+ * <p>
+ * It is possible that more than one instance of parameters may be
+ * generated by a given central authority, and that there may be more than
+ * one central authority. Indeed, each individual may be its own central
+ * authority, with different entities having different parameters.
+ *
+ * @see javax.crypto.KeyAgreement
+ */
+public class DHParameterSpec
+ implements AlgorithmParameterSpec
+{
+ private BigInteger p;
+ private BigInteger g;
+ private int l;
+
+ /**
+ * Constructs a parameter set for Diffie-Hellman, using a prime modulus
+ * <code>p</code> and a base generator <code>g</code>.
+ *
+ * @param p the prime modulus
+ * @param g the base generator
+ */
+ public DHParameterSpec(
+ BigInteger p,
+ BigInteger g)
+ {
+ this.p = p;
+ this.g = g;
+ }
+
+ /**
+ * Constructs a parameter set for Diffie-Hellman, using a prime modulus
+ * <code>p</code>, a base generator <code>g</code>, and the size in bits,
+ * <code>l</code>, of the random exponent (private value).
+ *
+ * @param p the prime modulus
+ * @param g the base generator
+ * @param l the size in bits of the random exponent (private value)
+ */
+ public DHParameterSpec(
+ BigInteger p,
+ BigInteger g,
+ int l)
+ {
+ this.p = p;
+ this.g = g;
+ this.l = l;
+ }
+
+ /**
+ * Returns the prime modulus <code>p</code>.
+ *
+ * @return the prime modulus <code>p</code>
+ */
+ public BigInteger getP()
+ {
+ return p;
+ }
+
+ /**
+ * Returns the base generator <code>g</code>.
+ *
+ * @return the base generator <code>g</code>
+ */
+ public BigInteger getG()
+ {
+ return g;
+ }
+
+ /**
+ * Returns the size in bits, <code>l</code>, of the random exponent
+ * (private value).
+ *
+ * @return the size in bits, <code>l</code>, of the random exponent
+ * (private value), or 0 if this size has not been set
+ */
+ public int getL()
+ {
+ return l;
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/DHPrivateKeySpec.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/DHPrivateKeySpec.java
new file mode 100644
index 000000000..79fa62281
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/DHPrivateKeySpec.java
@@ -0,0 +1,61 @@
+package javax.crypto.spec;
+
+import java.math.BigInteger;
+import java.security.spec.KeySpec;
+
+/**
+ * This class specifies a Diffie-Hellman private key with its associated parameters.
+ *
+ * @see DHPublicKeySpec
+ */
+public class DHPrivateKeySpec
+ implements KeySpec
+{
+ private BigInteger x;
+ private BigInteger p;
+ private BigInteger g;
+
+ /**
+ * Constructor that takes a private value <code>x</code>, a prime
+ * modulus <code>p</code>, and a base generator <code>g</code>.
+ */
+ public DHPrivateKeySpec(
+ BigInteger x,
+ BigInteger p,
+ BigInteger g)
+ {
+ this.x = x;
+ this.p = p;
+ this.g = g;
+ }
+
+ /**
+ * Returns the private value <code>x</code>.
+ *
+ * @return the private value <code>x</code>
+ */
+ public BigInteger getX()
+ {
+ return x;
+ }
+
+ /**
+ * Returns the prime modulus <code>p</code>.
+ *
+ * @return the prime modulus <code>p</code>
+ */
+ public BigInteger getP()
+ {
+ return p;
+ }
+
+ /**
+ * Returns the base generator <code>g</code>.
+ *
+ * @return the base generator <code>g</code>
+ */
+ public BigInteger getG()
+ {
+ return g;
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/DHPublicKeySpec.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/DHPublicKeySpec.java
new file mode 100644
index 000000000..1e610d154
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/DHPublicKeySpec.java
@@ -0,0 +1,61 @@
+package javax.crypto.spec;
+
+import java.math.BigInteger;
+import java.security.spec.KeySpec;
+
+/**
+ * This class specifies a Diffie-Hellman public key with its associated parameters.
+ *
+ * @see DHPrivateKeySpec
+ */
+public class DHPublicKeySpec
+ implements KeySpec
+{
+ private BigInteger y;
+ private BigInteger p;
+ private BigInteger g;
+
+ /**
+ * Constructor that takes a public value <code>y</code>, a prime
+ * modulus <code>p</code>, and a base generator <code>g</code>.
+ */
+ public DHPublicKeySpec(
+ BigInteger y,
+ BigInteger p,
+ BigInteger g)
+ {
+ this.y = y;
+ this.p = p;
+ this.g = g;
+ }
+
+ /**
+ * Returns the public value <code>y</code>.
+ *
+ * @return the public value <code>y</code>
+ */
+ public BigInteger getY()
+ {
+ return y;
+ }
+
+ /**
+ * Returns the prime modulus <code>p</code>.
+ *
+ * @return the prime modulus <code>p</code>
+ */
+ public BigInteger getP()
+ {
+ return p;
+ }
+
+ /**
+ * Returns the base generator <code>g</code>.
+ *
+ * @return the base generator <code>g</code>
+ */
+ public BigInteger getG()
+ {
+ return g;
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/IvParameterSpec.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/IvParameterSpec.java
new file mode 100644
index 000000000..4ed7376c0
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/IvParameterSpec.java
@@ -0,0 +1,75 @@
+package javax.crypto.spec;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * This class specifies an <i>initialization vector</i> (IV). IVs are used
+ * by ciphers in feedback mode, e.g., DES in CBC mode.
+ */
+public class IvParameterSpec
+ implements AlgorithmParameterSpec
+{
+ private byte[] iv;
+
+ /**
+ * Uses the bytes in <code>iv</code> as the IV.
+ *
+ * @param iv the buffer with the IV
+ */
+ public IvParameterSpec(
+ byte[] iv)
+ {
+ if (iv == null)
+ {
+ throw new IllegalArgumentException("null iv passed");
+ }
+
+ this.iv = new byte[iv.length];
+
+ System.arraycopy(iv, 0, this.iv, 0, iv.length);
+ }
+
+ /**
+ * Uses the first <code>len</code> bytes in <code>iv</code>,
+ * beginning at <code>offset</code> inclusive, as the IV.
+ * <p>
+ * The bytes that constitute the IV are those between
+ * <code>iv[offset]</code> and <code>iv[offset+len-1]</code> inclusive.
+ *
+ * @param iv the buffer with the IV
+ * @param offset the offset in <code>iv</code> where the IV starts
+ * @param len the number of IV bytes
+ */
+ public IvParameterSpec(
+ byte[] iv,
+ int offset,
+ int len)
+ {
+ if (iv == null)
+ {
+ throw new IllegalArgumentException("Null iv passed");
+ }
+
+ if (offset < 0 || len < 0 || (iv.length - offset) < len)
+ {
+ throw new IllegalArgumentException("Bad offset/len");
+ }
+
+ this.iv = new byte[len];
+
+ System.arraycopy(iv, offset, this.iv, 0, len);
+ }
+
+ /**
+ * Returns the initialization vector (IV).
+ *
+ * @return the initialization vector (IV)
+ */
+ public byte[] getIV()
+ {
+ byte[] tmp = new byte[iv.length];
+
+ System.arraycopy(iv, 0, tmp, 0, iv.length);
+ return tmp;
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/OAEPParameterSpec.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/OAEPParameterSpec.java
new file mode 100644
index 000000000..ccc5ad86e
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/OAEPParameterSpec.java
@@ -0,0 +1,103 @@
+package javax.crypto.spec;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * This class specifies the set of parameters used with OAEP Padding, as defined
+ * in the PKCS #1 standard. Its ASN.1 definition in PKCS#1 standard is described
+ * below:
+ *
+ * </pre>
+ *
+ * RSAES-OAEP-params ::= SEQUENCE { hashAlgorithm [0] OAEP-PSSDigestAlgorithms
+ * DEFAULT sha1, maskGenAlgorithm [1] PKCS1MGFAlgorithms DEFAULT mgf1SHA1,
+ * pSourceAlgorithm [2] PKCS1PSourceAlgorithms DEFAULT pSpecifiedEmpty }
+ *
+ * </pre>
+ *
+ * where
+ *
+ * <pre>
+ *
+ * OAEP-PSSDigestAlgorithms ALGORITHM-IDENTIFIER ::= { { OID id-sha1 PARAMETERS
+ * NULL }| { OID id-sha256 PARAMETERS NULL }| { OID id-sha384 PARAMETERS NULL } | {
+ * OID id-sha512 PARAMETERS NULL }, ... -- Allows for future expansion -- }
+ * PKCS1MGFAlgorithms ALGORITHM-IDENTIFIER ::= { { OID id-mgf1 PARAMETERS
+ * OAEP-PSSDigestAlgorithms }, ... -- Allows for future expansion -- }
+ * PKCS1PSourceAlgorithms ALGORITHM-IDENTIFIER ::= { { OID id-pSpecified
+ * PARAMETERS OCTET STRING }, ... -- Allows for future expansion -- }
+ *
+ * </pre>
+ *
+ * @see PSource
+ */
+public class OAEPParameterSpec
+ implements AlgorithmParameterSpec
+{
+ private String mdName;
+ private String mgfName;
+ private AlgorithmParameterSpec mgfSpec;
+ private PSource pSrc;
+
+ /**
+ * Constructs a parameter set for OAEP padding as defined in the PKCS #1
+ * standard using the specified message digest algorithm mdName, mask
+ * generation function algorithm mgfName, parameters for the mask generation
+ * function mgfSpec, and source of the encoding input P pSrc.
+ *
+ * @param mdName the algorithm name for the message digest.
+ * @param mgfName the algorithm name for the mask generation function.
+ * @param mgfSpec the parameters for the mask generation function. If null is
+ * specified, null will be returned by getMGFParameters().
+ * @param pSrc the source of the encoding input P.
+ * @throws NullPointerException if mdName, mgfName, or pSrc is null.
+ */
+ public OAEPParameterSpec(String mdName, String mgfName,
+ AlgorithmParameterSpec mgfSpec, PSource pSrc)
+ {
+ this.mdName = mdName;
+ this.mgfName = mgfName;
+ this.mgfSpec = mgfSpec;
+ this.pSrc = pSrc;
+ }
+
+ /**
+ * Returns the message digest algorithm name.
+ *
+ * @return the message digest algorithm name.
+ */
+ public String getDigestAlgorithm()
+ {
+ return mdName;
+ }
+
+ /**
+ * Returns the mask generation function algorithm name.
+ *
+ * @return the mask generation function algorithm name.
+ */
+ public String getMGFAlgorithm()
+ {
+ return mgfName;
+ }
+
+ /**
+ * Returns the parameters for the mask generation function.
+ *
+ * @return the parameters for the mask generation function.
+ */
+ public AlgorithmParameterSpec getMGFParameters()
+ {
+ return mgfSpec;
+ }
+
+ /**
+ * Returns the source of encoding input P.
+ *
+ * @return the source of encoding input P.
+ */
+ public PSource getPSource()
+ {
+ return pSrc;
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/PBEKeySpec.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/PBEKeySpec.java
new file mode 100644
index 000000000..3727031bc
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/PBEKeySpec.java
@@ -0,0 +1,222 @@
+package javax.crypto.spec;
+
+import java.security.spec.KeySpec;
+
+import javax.crypto.SecretKeyFactory;
+
+/**
+ * A user-chosen password that can be used with password-based encryption (PBE).
+ * <p>
+ * The password can be viewed as some kind of raw key material, from which the
+ * encryption mechanism that uses it derives a cryptographic key.
+ * <p>
+ * Different PBE mechanisms may consume different bits of each password
+ * character. For example, the PBE mechanism defined in PKCS #5 looks at only
+ * the low order 8 bits of each character, whereas PKCS #12 looks at all 16 bits
+ * of each character.
+ * <p>
+ * You convert the password characters to a PBE key by creating an instance of
+ * the appropriate secret-key factory. For example, a secret-key factory for
+ * PKCS #5 will construct a PBE key from only the low order 8 bits of each
+ * password character, whereas a secret-key factory for PKCS #12 will take all
+ * 16 bits of each character.
+ * <p>
+ * Also note that this class stores passwords as char arrays instead of String
+ * objects (which would seem more logical), because the String class is
+ * immutable and there is no way to overwrite its internal value when the
+ * password stored in it is no longer needed. Hence, this class requests the
+ * password as a char array, so it can be overwritten when done.
+ *
+ * @see SecretKeyFactory
+ * @see PBEParameterSpec
+ */
+public class PBEKeySpec
+ implements KeySpec
+{
+
+ private char[] password;
+
+ private byte[] salt;
+
+ private int iterationCount;
+
+ private int keyLength;
+
+ private boolean isPasswordCleared;
+
+ /**
+ * Constructor that takes a password. An empty char[] is used if null is
+ * specified.
+ * <p>
+ * Note: password is cloned before it is stored in the new PBEKeySpec
+ * object.
+ *
+ * @param password -
+ * the password.
+ */
+ public PBEKeySpec(char[] password)
+ {
+ if (password == null)
+ {
+ this.password = new char[0];
+ }
+ else
+ {
+ this.password = new char[password.length];
+
+ System.arraycopy(password, 0, this.password, 0, password.length);
+ }
+ }
+
+ /**
+ * Returns a copy of the password.
+ * <p>
+ * Note: this method returns a copy of the password. It is the caller's
+ * responsibility to zero out the password information after it is no longer
+ * needed.
+ *
+ * @return the password
+ * @throws IllegalStateException -
+ * if password has been cleared by calling clearPassword method.
+ */
+ public final char[] getPassword()
+ {
+ if (isPasswordCleared)
+ {
+ throw new IllegalStateException("Password has been cleared");
+ }
+ return password;
+ }
+
+ /**
+ * Constructor that takes a password, salt, iteration count, and
+ * to-be-derived key length for generating PBEKey of variable-key-size PBE
+ * ciphers. An empty char[] is used if null is specified for password.
+ * <p>
+ * Note: the password and salt are cloned before they are stored in the new
+ * PBEKeySpec object.
+ *
+ *
+ * @param password
+ * password - the password.
+ * @param salt
+ * salt - the salt.
+ * @param iterationCount
+ * iterationCount - the iteration count.
+ * @param keyLength
+ * keyLength - the to-be-derived key length.
+ * @throws NullPointerException -
+ * if salt is null.
+ * @throws IllegalArgumentException -
+ * if salt is empty, i.e. 0-length, iterationCount or keyLength
+ * is not positive.
+ */
+ public PBEKeySpec(char[] password, byte[] salt, int iterationCount, int keyLength)
+ {
+ this(password);
+ if (salt == null)
+ {
+ throw new NullPointerException("salt is null");
+ }
+ if (salt.length == 0)
+ {
+ throw new IllegalArgumentException("salt is empty");
+ }
+ if (iterationCount < 0)
+ {
+ throw new IllegalArgumentException("iterationCount is not positive");
+ }
+ if (keyLength < 0)
+ {
+ throw new IllegalArgumentException("keyLength is not positive");
+ }
+ this.keyLength = keyLength;
+ this.iterationCount = iterationCount;
+ this.salt = (byte[]) salt.clone();
+ }
+
+ /**
+ * Constructor that takes a password, salt, iteration count for generating
+ * PBEKey of fixed-key-size PBE ciphers. An empty char[] is used if null is
+ * specified for password.
+ * <p>
+ * Note: the password and salt are cloned before they are stored in the new
+ * PBEKeySpec object.
+ *
+ * @param password -
+ * the password.
+ * @param salt -
+ * the salt.
+ * @param iterationCount -
+ * the iteration count.
+ * @throws NullPointerException -
+ * if salt is null.
+ * @throws IllegalArgumentException -
+ * if salt is empty, i.e. 0-length, or iterationCount is not
+ * positive.
+ */
+ public PBEKeySpec(char[] password, byte[] salt, int iterationCount)
+ {
+ this(password, salt, iterationCount, 0);
+ }
+
+ /**
+ * Clears the internal copy of the password.
+ */
+ public final void clearPassword()
+ {
+ for (int i = 0; i < password.length; i++)
+ {
+ password[i] = 0;
+ }
+ password = null;
+ isPasswordCleared = true;
+ }
+
+ /**
+ * Returns a copy of the salt or null if not specified.
+ *
+ * Note: this method should return a copy of the salt. It is the caller's
+ * responsibility to zero out the salt information after it is no longer
+ * needed.
+ *
+ * @return the salt.
+ */
+ public final byte[] getSalt()
+ {
+ if (salt != null)
+ {
+ byte[] tmp = new byte[salt.length];
+
+ System.arraycopy(salt, 0, tmp, 0, salt.length);
+
+ return tmp;
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the iteration count or 0 if not specified.
+ *
+ * @return the iteration count.
+ */
+ public final int getIterationCount()
+ {
+ return iterationCount;
+ }
+
+ /**
+ * Returns the to-be-derived key length or 0 if not specified.
+ * <p>
+ * Note: this is used to indicate the preference on key length for
+ * variable-key-size ciphers. The actual key size depends on each provider's
+ * implementation.
+ *
+ * @return the to-be-derived key length.
+ */
+ public final int getKeyLength()
+ {
+ return keyLength;
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/PBEParameterSpec.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/PBEParameterSpec.java
new file mode 100644
index 000000000..2f714ea9e
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/PBEParameterSpec.java
@@ -0,0 +1,55 @@
+package javax.crypto.spec;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * This class specifies the set of parameters used with password-based encryption (PBE), as defined in the
+ * <a href="http://www.rsa.com/rsalabs/pubs/PKCS/html/pkcs-5.html">PKCS #5</a> standard.
+ */
+public class PBEParameterSpec
+ implements AlgorithmParameterSpec
+{
+ private byte[] salt;
+ private int iterationCount;
+
+ /**
+ * Constructs a parameter set for password-based encryption as defined in
+ * the PKCS #5 standard.
+ *
+ * @param salt the salt.
+ * @param iterationCount the iteration count.
+ */
+ public PBEParameterSpec(
+ byte[] salt,
+ int iterationCount)
+ {
+ this.salt = new byte[salt.length];
+ System.arraycopy(salt, 0, this.salt, 0, salt.length);
+
+ this.iterationCount = iterationCount;
+ }
+
+ /**
+ * Returns the salt.
+ *
+ * @return the salt
+ */
+ public byte[] getSalt()
+ {
+ byte[] tmp = new byte[salt.length];
+
+ System.arraycopy(salt, 0, tmp, 0, salt.length);
+
+ return tmp;
+ }
+
+ /**
+ * Returns the iteration count.
+ *
+ * @return the iteration count
+ */
+ public int getIterationCount()
+ {
+ return iterationCount;
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/PSource.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/PSource.java
new file mode 100644
index 000000000..03016e1f2
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/PSource.java
@@ -0,0 +1,98 @@
+package javax.crypto.spec;
+
+/**
+ * This class specifies the source for encoding input P in OAEP Padding, as
+ * defined in the {@link http://www.ietf.org/rfc/rfc3447.txt PKCS #1} standard.
+ *
+ * <pre>
+ *
+ * PKCS1PSourceAlgorithms ALGORITHM-IDENTIFIER ::= {
+ * { OID id-pSpecified PARAMETERS OCTET STRING },
+ * ... -- Allows for future expansion --
+ * }
+ * </pre>
+ */
+public class PSource
+{
+ /**
+ * This class is used to explicitly specify the value for encoding input P
+ * in OAEP Padding.
+ *
+ */
+ public final static class PSpecified
+ extends PSource
+ {
+ private byte[] p;
+
+ /**
+ * The encoding input P whose value equals byte[0].
+ */
+ public static final PSpecified DEFAULT = new PSpecified(new byte[0]);
+
+ /**
+ * Constructs the source explicitly with the specified value p as the
+ * encoding input P.
+ *
+ * @param p the value of the encoding input. The contents of the array
+ * are copied to protect against subsequent modification.
+ * @throws NullPointerException if p is null.
+ */
+ public PSpecified(byte[] p)
+ {
+ super("PSpecified");
+ if (p == null)
+ {
+ throw new NullPointerException("The encoding input is null");
+ }
+ this.p = copyOf(p);
+ }
+
+ /**
+ * Returns the value of encoding input P.
+ *
+ * @return the value of encoding input P. A new array is returned each
+ * time this method is called.
+ */
+ public byte[] getValue()
+ {
+ return copyOf(p);
+ }
+
+ private byte[] copyOf(byte[] b)
+ {
+ byte[] tmp = new byte[b.length];
+
+ System.arraycopy(b, 0, tmp, 0, b.length);
+
+ return tmp;
+ }
+ }
+
+ private String pSrcName;
+
+ /**
+ * Constructs a source of the encoding input P for OAEP padding as defined
+ * in the PKCS #1 standard using the specified PSource algorithm.
+ *
+ * @param pSrcName the algorithm for the source of the encoding input P.
+ * @throws NullPointerException if pSrcName is null.
+ */
+ protected PSource(String pSrcName)
+ {
+ if (pSrcName == null)
+ {
+ throw new NullPointerException("pSrcName is null");
+ }
+ this.pSrcName = pSrcName;
+ }
+
+ /**
+ * Returns the PSource algorithm name.
+ *
+ * @return the PSource algorithm name.
+ */
+ public String getAlgorithm()
+ {
+ return pSrcName;
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/RC2ParameterSpec.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/RC2ParameterSpec.java
new file mode 100644
index 000000000..bea52516d
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/RC2ParameterSpec.java
@@ -0,0 +1,162 @@
+package javax.crypto.spec;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * This class specifies the parameters used with the
+ * <a href="http://www.rsa.com/rsalabs/newfaq/q75.html"><i>RC2</i></a>
+ * algorithm.
+ * <p>
+ * The parameters consist of an effective key size and optionally
+ * an 8-byte initialization vector (IV) (only in feedback mode).
+ * <p>
+ * This class can be used to initialize a <code>Cipher</code> object that
+ * implements the <i>RC2</i> algorithm.
+ */
+public class RC2ParameterSpec
+ implements AlgorithmParameterSpec
+{
+ private int effectiveKeyBits;
+ private byte[] iv = new byte[8];
+
+ /**
+ * Constructs a parameter set for RC2 from the given effective key size
+ * (in bits).
+ *
+ * @param effectiveKeyBits the effective key size in bits.
+ */
+ public RC2ParameterSpec(
+ int effectiveKeyBits)
+ {
+ this.effectiveKeyBits = effectiveKeyBits;
+ }
+
+ /**
+ * Constructs a parameter set for RC2 from the given effective key size
+ * (in bits) and an 8-byte IV.
+ * <p>
+ * The bytes that constitute the IV are those between
+ * <code>iv[0]</code> and <code>iv[7]</code> inclusive.
+ *
+ * @param effectiveKeyBits the effective key size in bits.
+ * @param iv the buffer with the 8-byte IV.
+ */
+ public RC2ParameterSpec(
+ int effectiveKeyBits,
+ byte[] iv)
+ {
+ this(effectiveKeyBits, iv, 0);
+ }
+
+ /**
+ * Constructs a parameter set for RC2 from the given effective key size
+ * (in bits) and IV.
+ * <p>
+ * The IV is taken from <code>iv</code>, starting at
+ * <code>offset</code> inclusive.
+ * The bytes that constitute the IV are those between
+ * <code>iv[offset]</code> and <code>iv[offset+7]</code> inclusive.
+ *
+ * @param effectiveKeyBits the effective key size in bits.
+ * @param iv the buffer with the IV.
+ * @param offset the offset in <code>iv</code> where the 8-byte IV starts.
+ */
+ public RC2ParameterSpec(
+ int effectiveKeyBits,
+ byte[] iv,
+ int offset)
+ {
+ this.effectiveKeyBits = effectiveKeyBits;
+
+ this.iv = new byte[8];
+ System.arraycopy(iv, offset, this.iv, 0, this.iv.length);
+ }
+
+ /**
+ * Returns the effective key size in bits.
+ *
+ * @return the effective key size in bits.
+ */
+ public int getEffectiveKeyBits()
+ {
+ return effectiveKeyBits;
+ }
+
+ /**
+ * Returns the IV or null if this parameter set does not contain an IV.
+ *
+ * @return the IV or null if this parameter set does not contain an IV.
+ */
+ public byte[] getIV()
+ {
+ if (iv == null)
+ {
+ return null;
+ }
+
+ byte[] tmp = new byte[iv.length];
+
+ System.arraycopy(iv, 0, tmp, 0, tmp.length);
+
+ return tmp;
+ }
+
+ /**
+ * Tests for equality between the specified object and this
+ * object. Two RC2ParameterSpec objects are considered equal if their
+ * effective key sizes and IVs are equal.
+ * (Two IV references are considered equal if both are <tt>null</tt>.)
+ *
+ * @param obj the object to test for equality with this object.
+ * @return true if the objects are considered equal, false otherwise.
+ * @override equals in class java.lang.Object
+ */
+ public boolean equals(
+ Object obj)
+ {
+ if ((obj == null) || !(obj instanceof RC2ParameterSpec))
+ {
+ return false;
+ }
+
+ RC2ParameterSpec spec = (RC2ParameterSpec)obj;
+
+ if (this.effectiveKeyBits != spec.effectiveKeyBits)
+ {
+ return false;
+ }
+
+ if (iv != null)
+ {
+ if (spec.iv == null)
+ {
+ return false;
+ }
+
+ for (int i = 0; i != iv.length; i++)
+ {
+ if (iv[i] != spec.iv[i])
+ {
+ return false;
+ }
+ }
+ }
+ else if (spec.iv != null)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Calculates a hash code value for the object.
+ * Objects that are equal will also have the same hashcode.
+ *
+ * @override hashCode in class java.lang.Object
+ */
+ public int hashCode()
+ {
+ throw new RuntimeException("Not yet implemented");
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/RC5ParameterSpec.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/RC5ParameterSpec.java
new file mode 100644
index 000000000..a34c645b4
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/RC5ParameterSpec.java
@@ -0,0 +1,224 @@
+package javax.crypto.spec;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * This class specifies the parameters used with the
+ * <a href="http://www.rsa.com/rsalabs/newfaq/q76.html"><i>RC5</i></a>
+ * algorithm.
+ * <p>
+ * The parameters consist of a version number, a rounds count, a word
+ * size, and optionally an initialization vector (IV) (only in feedback mode).
+ * <p>
+ * This class can be used to initialize a <code>Cipher</code> object that
+ * implements the <i>RC5</i> algorithm as supplied by
+ * <a href="http://www.rsa.com">RSA Data Security, Inc.</a> (RSA DSI),
+ * or any parties authorized by RSA DSI.
+ */
+public class RC5ParameterSpec
+ implements AlgorithmParameterSpec
+{
+ private int version;
+ private int rounds;
+ private int wordSize;
+
+ private byte[] iv;
+
+ /**
+ * Constructs a parameter set for RC5 from the given version, number of
+ * rounds and word size (in bits).
+ *
+ * @param version the version.
+ * @param rounds the number of rounds.
+ * @param wordSize the word size in bits.
+ */
+ public RC5ParameterSpec(
+ int version,
+ int rounds,
+ int wordSize)
+ {
+ this.version = version;
+ this.rounds = rounds;
+ this.wordSize = wordSize;
+ this.iv = null;
+ }
+
+ /**
+ * Constructs a parameter set for RC5 from the given version, number of
+ * rounds, word size (in bits), and IV.
+ * <p>
+ * Note that the size of the IV (block size) must be twice the word
+ * size. The bytes that constitute the IV are those between
+ * <code>iv[0]</code> and <code>iv[2*(wordSize/8)-1]</code> inclusive.
+ *
+ * @param version the version.
+ * @param rounds the number of rounds.
+ * @param wordSize the word size in bits.
+ * @param iv the buffer with the IV.
+ */
+ public RC5ParameterSpec(
+ int version,
+ int rounds,
+ int wordSize,
+ byte[] iv)
+ {
+ this(version, rounds, wordSize, iv, 0);
+ }
+
+ /**
+ * Constructs a parameter set for RC5 from the given version, number of
+ * rounds, word size (in bits), and IV.
+ * <p>
+ * The IV is taken from <code>iv</code>, starting at <code>offset</code> inclusive.
+ * Note that the size of the IV (block size), starting at
+ * <code>offset</code> inclusive, must be twice the word size.
+ * The bytes that constitute the IV are those between
+ * <code>iv[offset]</code> and <code>iv[offset+2*(wordSize/8)-1]</code>
+ * inclusive.
+ *
+ * @param version the version.
+ * @param rounds the number of rounds.
+ * @param wordSize the word size in bits.
+ * @param iv the buffer with the IV.
+ * @param offset the offset in <code>iv</code> where the IV starts.
+ */
+ public RC5ParameterSpec(
+ int version,
+ int rounds,
+ int wordSize,
+ byte[] iv,
+ int offset)
+ {
+ this.version = version;
+ this.rounds = rounds;
+ this.wordSize = wordSize;
+ this.iv = new byte[2 * (wordSize / 8)];
+
+ System.arraycopy(iv, offset, this.iv, 0, this.iv.length);
+ }
+
+ /**
+ * Returns the version.
+ *
+ * @return the version.
+ */
+ public int getVersion()
+ {
+ return version;
+ }
+
+ /**
+ * Returns the number of rounds.
+ *
+ * @return the number of rounds.
+ */
+ public int getRounds()
+ {
+ return rounds;
+ }
+
+ /**
+ * Returns the word size in bits
+ *
+ * @return the word size in bits.
+ */
+ public int getWordSize()
+ {
+ return wordSize;
+ }
+
+ /**
+ * Returns the IV or null if this parameter set does not contain an IV.
+ *
+ * @return the IV or null if this parameter set does not contain an IV.
+ */
+ public byte[] getIV()
+ {
+ if (iv == null)
+ {
+ return null;
+ }
+
+ byte[] tmp = new byte[iv.length];
+
+ System.arraycopy(iv, 0, tmp, 0, iv.length);
+
+ return tmp;
+ }
+
+ /**
+ * Tests for equality between the specified object and this
+ * object. Two RC5ParameterSpec objects are considered equal if their
+ * version numbers, number of rounds, word sizes, and IVs are equal.
+ * (Two IV references are considered equal if both are <tt>null</tt>.)
+ *
+ * @param obj the object to test for equality with this object.
+ * @return true if the objects are considered equal, false otherwise.
+ */
+ public boolean equals(
+ Object obj)
+ {
+ if ((obj == null) || !(obj instanceof RC5ParameterSpec))
+ {
+ return false;
+ }
+
+ RC5ParameterSpec spec = (RC5ParameterSpec)obj;
+
+ if (this.version != spec.version)
+ {
+ return false;
+ }
+
+ if (this.rounds != spec.rounds)
+ {
+ return false;
+ }
+
+ if (this.wordSize != spec.wordSize)
+ {
+ return false;
+ }
+
+ if (iv != null)
+ {
+ if (spec.iv == null || spec.iv.length != iv.length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i != iv.length; i++)
+ {
+ if (iv[i] != spec.iv[i])
+ {
+ return false;
+ }
+ }
+ }
+ else if (spec.iv != null)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Calculates a hash code value for the object.
+ * Objects that are equal will also have the same hashcode.
+ */
+ public int hashCode()
+ {
+ int code = version ^ rounds ^ wordSize;
+
+ if (iv != null)
+ {
+ for (int i = 0; i != iv.length; i++)
+ {
+ code ^= iv[i] << (8 * (i % 4));
+ }
+ }
+
+ return code;
+ }
+}
diff --git a/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/SecretKeySpec.java b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/SecretKeySpec.java
new file mode 100644
index 000000000..e60be1605
--- /dev/null
+++ b/libraries/spongycastle/jce/src/main/java/javax/crypto/spec/SecretKeySpec.java
@@ -0,0 +1,193 @@
+package javax.crypto.spec;
+
+import javax.crypto.SecretKey;
+import java.security.spec.KeySpec;
+
+/**
+ * This class specifies a secret key in a provider-independent fashion.
+ * <p>
+ * It can be used to construct a <code>SecretKey</code> from a byte array,
+ * without having to go through a (provider-based)
+ * <code>SecretKeyFactory</code>.
+ * <p>
+ * This class is only useful for raw secret keys that can be represented as
+ * a byte array and have no key parameters associated with them, e.g., DES or
+ * Triple DES keys.
+ *
+ * @see SecretKey
+ * @see javax.crypto.SecretKeyFactory
+ */
+public class SecretKeySpec
+ implements KeySpec, SecretKey
+{
+ private static final long serialVersionUID = 6577238317307289933L;
+
+ private String algorithm;
+ private byte[] key;
+
+ /**
+ * Constructs a secret key from the given byte array.
+ * <p>
+ * This constructor does not check if the given bytes indeed specify a
+ * secret key of the specified algorithm. For example, if the algorithm is
+ * DES, this constructor does not check if <code>key</code> is 8 bytes
+ * long, and also does not check for weak or semi-weak keys.
+ * In order for those checks to be performed, an algorithm-specific
+ * <i>key specification</i> class (in this case:
+ * <a href = "DESKeySpec.html"><code>DESKeySpec</code></a>)
+ * should be used.
+ *
+ * @param key the key material of the secret key.
+ * @param algorithm the name of the secret-key algorithm to be associated
+ * See Appendix A in the Java Cryptography Extension API Specification &amp; Reference
+ * for information about standard algorithm names.
+ */
+ public SecretKeySpec(
+ byte[] key,
+ String algorithm)
+ {
+ if (key == null)
+ {
+ throw new IllegalArgumentException("null key passed");
+ }
+
+ if (algorithm == null)
+ {
+ throw new IllegalArgumentException("null algorithm passed");
+ }
+
+ this.key = new byte[key.length];
+ System.arraycopy(key, 0, this.key, 0, key.length);
+ this.algorithm = algorithm;
+ }
+
+ /**
+ * Constructs a secret key from the given byte array, using the first
+ * <code>len</code> bytes of <code>key</code>, starting at
+ * <code>offset</code> inclusive.
+ * <p>
+ * The bytes that constitute the secret key are those between <code>key[offset]</code> and
+ * <code>key[offset+len-1]</code> inclusive.
+ * <p>
+ * This constructor does not check if the given bytes indeed specify a
+ * secret key of the specified algorithm. For example, if the algorithm is
+ * DES, this constructor does not check if <code>key</code> is 8 bytes
+ * long, and also does not check for weak or semi-weak keys.
+ * In order for those checks to be performed, an algorithm-specific key
+ * specification class (in this case: <a href = "DESKeySpec.html"><code>DESKeySpec</code></a>)
+ * must be used.
+ *
+ * @param key the key material of the secret key.
+ * @param offset the offset in <code>key</code> where the key material starts.
+ * @param len the length of the key material.
+ * @param algorithm the name of the secret-key algorithm to be associated
+ * with the given key material. See Appendix A in the Java Cryptography Extension API
+ * Specification &amp; Reference for information about standard algorithm names.
+ */
+ public SecretKeySpec(
+ byte[] key,
+ int offset,
+ int len,
+ String algorithm)
+ {
+ if (key == null)
+ {
+ throw new IllegalArgumentException("Null key passed");
+ }
+
+ if ((key.length - offset) < len)
+ {
+ throw new IllegalArgumentException("Bad offset/len");
+ }
+
+ if (algorithm == null)
+ {
+ throw new IllegalArgumentException("Null algorithm string passed");
+ }
+
+ this.key = new byte[len];
+ System.arraycopy(key, offset, this.key, 0, len);
+ this.algorithm = algorithm;
+ }
+
+ /**
+ * Returns the name of the algorithm associated with this secret key.
+ *
+ * @return the secret key algorithm.
+ */
+ public String getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ /**
+ * Returns the name of the encoding format for this secret key.
+ *
+ * @return the string "RAW".
+ */
+ public java.lang.String getFormat()
+ {
+ return "RAW";
+ }
+
+ /**
+ * Returns the key material of this secret key.
+ *
+ * @return the key material
+ */
+ public byte[] getEncoded()
+ {
+ byte[] tmp = new byte[key.length];
+
+ System.arraycopy(key, 0, tmp, 0, tmp.length);
+
+ return tmp;
+ }
+
+ /**
+ * Calculates a hash code value for the object.
+ * Objects that are equal will also have the same hashcode.
+ */
+ public int hashCode()
+ {
+ int code = algorithm.toUpperCase().hashCode();
+
+ for (int i = 0; i != this.key.length; i++)
+ {
+ code ^= this.key[i] << (8 * (i % 4));
+ }
+
+ return code;
+ }
+
+ public boolean equals(
+ Object obj)
+ {
+ if ((obj == null) || !(obj instanceof SecretKeySpec))
+ {
+ return false;
+ }
+
+ SecretKeySpec spec = (SecretKeySpec)obj;
+
+ if (!this.algorithm.equalsIgnoreCase(spec.algorithm))
+ {
+ return false;
+ }
+
+ if (this.key.length != spec.key.length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i != this.key.length; i++)
+ {
+ if (this.key[i] != spec.key[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}