aboutsummaryrefslogtreecommitdiffstats
path: root/libraries/spongycastle/jce/src/main/java/javax/crypto/SealedObject.java
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/spongycastle/jce/src/main/java/javax/crypto/SealedObject.java')
-rw-r--r--libraries/spongycastle/jce/src/main/java/javax/crypto/SealedObject.java302
1 files changed, 302 insertions, 0 deletions
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());
+ }
+ }
+}