mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8187443: Forest Consolidation: Move files to unified layout
Reviewed-by: darcy, ihse
This commit is contained in:
parent
270fe13182
commit
3789983e89
56923 changed files with 3 additions and 15727 deletions
487
src/java.base/share/classes/javax/crypto/SealedObject.java
Normal file
487
src/java.base/share/classes/javax/crypto/SealedObject.java
Normal file
|
@ -0,0 +1,487 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package javax.crypto;
|
||||
|
||||
import java.io.*;
|
||||
import java.security.AlgorithmParameters;
|
||||
import java.security.Key;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
|
||||
/**
|
||||
* 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 AES, 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:
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li>by using the {@link #getObject(javax.crypto.Cipher) getObject}
|
||||
* 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.
|
||||
*
|
||||
* <li>by using one of the
|
||||
* {@link #getObject(java.security.Key) getObject} 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>
|
||||
*
|
||||
* @author Li Gong
|
||||
* @author Jan Luehe
|
||||
* @see Cipher
|
||||
* @since 1.4
|
||||
*/
|
||||
|
||||
public class SealedObject implements Serializable {
|
||||
|
||||
static final long serialVersionUID = 4482838265551344752L;
|
||||
|
||||
/**
|
||||
* The serialized object contents in encrypted format.
|
||||
*
|
||||
* @serial
|
||||
*/
|
||||
private byte[] encryptedContent = null;
|
||||
|
||||
/**
|
||||
* The algorithm that was used to seal this object.
|
||||
*
|
||||
* @serial
|
||||
*/
|
||||
private String sealAlg = null;
|
||||
|
||||
/**
|
||||
* The algorithm of the parameters used.
|
||||
*
|
||||
* @serial
|
||||
*/
|
||||
private String paramsAlg = null;
|
||||
|
||||
/**
|
||||
* The cryptographic parameters used by the sealing Cipher,
|
||||
* encoded in the default format.
|
||||
* <p>
|
||||
* That is, <code>cipher.getParameters().getEncoded()</code>.
|
||||
*
|
||||
* @serial
|
||||
*/
|
||||
protected byte[] encodedParams = null;
|
||||
|
||||
/**
|
||||
* 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; can be null.
|
||||
* @param c the cipher used to seal the object.
|
||||
*
|
||||
* @exception NullPointerException if the given cipher is null.
|
||||
* @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
|
||||
{
|
||||
/*
|
||||
* Serialize the object
|
||||
*/
|
||||
|
||||
// creating a stream pipe-line, from a to b
|
||||
ByteArrayOutputStream b = new ByteArrayOutputStream();
|
||||
ObjectOutput a = new ObjectOutputStream(b);
|
||||
byte[] content;
|
||||
try {
|
||||
// write and flush the object content to byte array
|
||||
a.writeObject(object);
|
||||
a.flush();
|
||||
content = b.toByteArray();
|
||||
} finally {
|
||||
a.close();
|
||||
}
|
||||
|
||||
/*
|
||||
* Seal the object
|
||||
*/
|
||||
try {
|
||||
this.encryptedContent = c.doFinal(content);
|
||||
}
|
||||
catch (BadPaddingException ex) {
|
||||
// if sealing is encryption only
|
||||
// Should never happen??
|
||||
}
|
||||
|
||||
// Save the parameters
|
||||
if (c.getParameters() != null) {
|
||||
this.encodedParams = c.getParameters().getEncoded();
|
||||
this.paramsAlg = c.getParameters().getAlgorithm();
|
||||
}
|
||||
|
||||
// Save the encryption algorithm
|
||||
this.sealAlg = c.getAlgorithm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a SealedObject object from the passed-in SealedObject.
|
||||
*
|
||||
* @param so a SealedObject object
|
||||
* @exception NullPointerException if the given sealed object is null.
|
||||
*/
|
||||
protected SealedObject(SealedObject so) {
|
||||
this.encryptedContent = so.encryptedContent.clone();
|
||||
this.sealAlg = so.sealAlg;
|
||||
this.paramsAlg = so.paramsAlg;
|
||||
if (so.encodedParams != null) {
|
||||
this.encodedParams = so.encodedParams.clone();
|
||||
} else {
|
||||
this.encodedParams = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 this.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).
|
||||
* @exception NullPointerException if <code>key</code> is null.
|
||||
*/
|
||||
public final Object getObject(Key key)
|
||||
throws IOException, ClassNotFoundException, NoSuchAlgorithmException,
|
||||
InvalidKeyException
|
||||
{
|
||||
if (key == null) {
|
||||
throw new NullPointerException("key is null");
|
||||
}
|
||||
|
||||
try {
|
||||
return unseal(key, null);
|
||||
} catch (NoSuchProviderException nspe) {
|
||||
// we've already caught NoSuchProviderException's and converted
|
||||
// them into NoSuchAlgorithmException's with details about
|
||||
// the failing algorithm
|
||||
throw new NoSuchAlgorithmException("algorithm not found");
|
||||
} catch (IllegalBlockSizeException ibse) {
|
||||
throw new InvalidKeyException(ibse.getMessage());
|
||||
} catch (BadPaddingException bpe) {
|
||||
throw new InvalidKeyException(bpe.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 NullPointerException if the given cipher is null.
|
||||
* @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
|
||||
{
|
||||
/*
|
||||
* Unseal the object
|
||||
*/
|
||||
byte[] content = c.doFinal(this.encryptedContent);
|
||||
|
||||
/*
|
||||
* De-serialize it
|
||||
*/
|
||||
// creating a stream pipe-line, from b to a
|
||||
ByteArrayInputStream b = new ByteArrayInputStream(content);
|
||||
ObjectInput a = new extObjectInputStream(b);
|
||||
try {
|
||||
Object obj = a.readObject();
|
||||
return obj;
|
||||
} finally {
|
||||
a.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 IllegalArgumentException if the given provider is null
|
||||
* or empty.
|
||||
* @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 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).
|
||||
* @exception NullPointerException if <code>key</code> is null.
|
||||
*/
|
||||
public final Object getObject(Key key, String provider)
|
||||
throws IOException, ClassNotFoundException, NoSuchAlgorithmException,
|
||||
NoSuchProviderException, InvalidKeyException
|
||||
{
|
||||
if (key == null) {
|
||||
throw new NullPointerException("key is null");
|
||||
}
|
||||
if (provider == null || provider.length() == 0) {
|
||||
throw new IllegalArgumentException("missing provider");
|
||||
}
|
||||
|
||||
try {
|
||||
return unseal(key, provider);
|
||||
} catch (IllegalBlockSizeException | BadPaddingException ex) {
|
||||
throw new InvalidKeyException(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Object unseal(Key key, String provider)
|
||||
throws IOException, ClassNotFoundException, NoSuchAlgorithmException,
|
||||
NoSuchProviderException, InvalidKeyException,
|
||||
IllegalBlockSizeException, BadPaddingException
|
||||
{
|
||||
/*
|
||||
* Create the parameter object.
|
||||
*/
|
||||
AlgorithmParameters params = null;
|
||||
if (this.encodedParams != null) {
|
||||
try {
|
||||
if (provider != null)
|
||||
params = AlgorithmParameters.getInstance(this.paramsAlg,
|
||||
provider);
|
||||
else
|
||||
params = AlgorithmParameters.getInstance(this.paramsAlg);
|
||||
|
||||
} catch (NoSuchProviderException nspe) {
|
||||
if (provider == null) {
|
||||
throw new NoSuchAlgorithmException(this.paramsAlg
|
||||
+ " not found");
|
||||
} else {
|
||||
throw new NoSuchProviderException(nspe.getMessage());
|
||||
}
|
||||
}
|
||||
params.init(this.encodedParams);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create and initialize the cipher.
|
||||
*/
|
||||
Cipher c;
|
||||
try {
|
||||
if (provider != null)
|
||||
c = Cipher.getInstance(this.sealAlg, provider);
|
||||
else
|
||||
c = Cipher.getInstance(this.sealAlg);
|
||||
} catch (NoSuchPaddingException nspe) {
|
||||
throw new NoSuchAlgorithmException("Padding that was used in "
|
||||
+ "sealing operation not "
|
||||
+ "available");
|
||||
} catch (NoSuchProviderException nspe) {
|
||||
if (provider == null) {
|
||||
throw new NoSuchAlgorithmException(this.sealAlg+" not found");
|
||||
} else {
|
||||
throw new NoSuchProviderException(nspe.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (params != null)
|
||||
c.init(Cipher.DECRYPT_MODE, key, params);
|
||||
else
|
||||
c.init(Cipher.DECRYPT_MODE, key);
|
||||
} catch (InvalidAlgorithmParameterException iape) {
|
||||
// this should never happen, because we use the exact same
|
||||
// parameters that were used in the sealing operation
|
||||
throw new RuntimeException(iape.getMessage());
|
||||
}
|
||||
|
||||
/*
|
||||
* Unseal the object
|
||||
*/
|
||||
byte[] content = c.doFinal(this.encryptedContent);
|
||||
|
||||
/*
|
||||
* De-serialize it
|
||||
*/
|
||||
// creating a stream pipe-line, from b to a
|
||||
ByteArrayInputStream b = new ByteArrayInputStream(content);
|
||||
ObjectInput a = new extObjectInputStream(b);
|
||||
try {
|
||||
Object obj = a.readObject();
|
||||
return obj;
|
||||
} finally {
|
||||
a.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores the state of the SealedObject from a stream.
|
||||
* @param s the object input stream.
|
||||
* @exception NullPointerException if s is null.
|
||||
*/
|
||||
private void readObject(java.io.ObjectInputStream s)
|
||||
throws java.io.IOException, ClassNotFoundException
|
||||
{
|
||||
s.defaultReadObject();
|
||||
if (encryptedContent != null)
|
||||
encryptedContent = encryptedContent.clone();
|
||||
if (encodedParams != null)
|
||||
encodedParams = encodedParams.clone();
|
||||
}
|
||||
}
|
||||
|
||||
final class extObjectInputStream extends ObjectInputStream {
|
||||
extObjectInputStream(InputStream in)
|
||||
throws IOException, StreamCorruptedException {
|
||||
super(in);
|
||||
}
|
||||
|
||||
protected Class<?> resolveClass(ObjectStreamClass v)
|
||||
throws IOException, ClassNotFoundException
|
||||
{
|
||||
|
||||
try {
|
||||
/*
|
||||
* Calling the super.resolveClass() first
|
||||
* will let us pick up bug fixes in the super
|
||||
* class (e.g., 4171142).
|
||||
*/
|
||||
return super.resolveClass(v);
|
||||
} catch (ClassNotFoundException cnfe) {
|
||||
/*
|
||||
* This is a workaround for bug 4224921.
|
||||
*/
|
||||
ClassLoader loader = Thread.currentThread().getContextClassLoader();
|
||||
if (loader == null) {
|
||||
loader = ClassLoader.getSystemClassLoader();
|
||||
if (loader == null) {
|
||||
throw new ClassNotFoundException(v.getName());
|
||||
}
|
||||
}
|
||||
|
||||
return Class.forName(v.getName(), false, loader);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue