Académique Documents
Professionnel Documents
Culture Documents
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package javax.crypto;
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
java.nio.ByteBuffer;
java.security.AlgorithmParameters;
java.security.InvalidAlgorithmParameterException;
java.security.InvalidKeyException;
java.security.InvalidParameterException;
java.security.Key;
java.security.NoSuchAlgorithmException;
java.security.NoSuchProviderException;
java.security.Provider;
java.security.SecureRandom;
java.security.Security;
java.security.cert.Certificate;
java.security.cert.X509Certificate;
java.security.spec.AlgorithmParameterSpec;
java.util.Set;
org.apache.harmony.crypto.internal.NullCipherSpi;
org.apache.harmony.security.fortress.Engine;
/**
* This class provides access to implementations of cryptographic ciphers for
* encryption and decryption. Cipher classes can not be instantiated directly,
* one has to call the Cipher's {@code getInstance} method with the name of a
* requested transformation, optionally with a provider. A transformation
* specifies an operation (or a set of operations) as a string in the form:
* <ul>
* <li><i>"algorithm/mode/padding"</i></li> or
* <li><i>"algorithm"</i></li>
* </ul>
* <i>algorithm</i> is the name of a cryptographic algorithm, <i>mode</i> is the
* name of a feedback mode and <i>padding</i> is the name of a padding scheme.
* If <i>mode</i> and/or <i>padding</i> values are omitted, provider specific
* default values will be used.
* <p>
* A valid transformation would be:
* <ul>
* {@code Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");}
* </ul>
* When a block cipher is requested in in stream cipher mode, the number of bits
* to be processed at a time can be optionally specified by appending it to the
* mode name. e.g. <i>"AES/CFB8/NoPadding"</i>. If no number is specified, a
* provider specific default value is used.
*/
public class Cipher {
/**
* Constant for decryption operation mode.
*/
public static final int DECRYPT_MODE = 2;
/**
* Constant for encryption operation mode.
*/
public static final int ENCRYPT_MODE = 1;
/**
* Constant indicating that the key to be unwrapped is a private key.
*/
public static final int PRIVATE_KEY = 2;
/**
* Constant indicating that the key to be unwrapped is a public key.
*/
public static final int PUBLIC_KEY = 1;
/**
* Constant indicating that the key to be unwrapped is a secret key.
*/
public static final int SECRET_KEY = 3;
/**
* Constant for key unwrapping operation mode.
*/
public static final int UNWRAP_MODE = 4;
/**
* Constant for key wrapping operation mode.
*/
public static final int WRAP_MODE = 3;
private int mode;
/**
* The service name.
*/
private static final String SERVICE = "Cipher";
/**
* Used to access common engine functionality.
*/
private static final Engine ENGINE = new Engine(SERVICE);
/**
* The provider.
*/
private Provider provider;
/**
* The SPI implementation.
*/
private CipherSpi spiImpl;
/**
* The transformation.
*/
private String transformation;
private static SecureRandom secureRandom;
/**
* Creates a new Cipher instance.
*
* @param cipherSpi
*
the implementation delegate of the cipher.
* @param provider
*
the provider of the implementation of this cipher.
* @param transformation
*
the name of the transformation that this cipher performs.
* @throws NullPointerException
*
if either cipherSpi is {@code null} or provider is {@code
*
null} and {@code cipherSpi} is a {@code NullCipherSpi}.
*/
protected Cipher(CipherSpi cipherSpi, Provider provider,
String transformation) {
if (cipherSpi == null) {
throw new NullPointerException();
}
if (!(cipherSpi instanceof NullCipherSpi) && provider == null) {
throw new NullPointerException();
}
this.provider = provider;
this.transformation = transformation;
this.spiImpl = cipherSpi;
}
/**
* Creates a new Cipher for the specified transformation. The installed
* providers are searched in order for an implementation of the specified
* transformation. The first found provider providing the transformation is
* used to create the cipher. If no provider is found an exception is
* thrown.
*
* @param transformation
*
the name of the transformation to create a cipher for.
* @return a cipher for the requested transformation.
* @throws NoSuchAlgorithmException
*
if no installed provider can provide the
*
<i>transformation</i>, or it is {@code null}, empty or in an
*
invalid format.
* @throws NoSuchPaddingException
*
if no installed provider can provide the padding scheme in
*
the <i>transformation</i>.
*/
public static final Cipher getInstance(String transformation)
throws NoSuchAlgorithmException, NoSuchPaddingException {
return getCipher(transformation, null);
}
/**
* Creates a new cipher for the specified transformation provided by the
* specified provider.
*
* @param transformation
*
the name of the transformation to create a cipher for.
* @param provider
*
the name of the provider to ask for the transformation.
* @return a cipher for the requested transformation.
* @throws NoSuchAlgorithmException
*
if the specified provider can not provide the
*
<i>transformation</i>, or it is {@code null}, empty or in an
*
invalid format.
* @throws NoSuchProviderException
*
if no provider with the specified name can be found.
* @throws NoSuchPaddingException
*
if the requested padding scheme in the <i>transformation</i>
*
is not available.
* @throws IllegalArgumentException
*
if the specified provider is {@code null}.
*/
public static final Cipher getInstance(String transformation,
String provider) throws NoSuchAlgorithmException,
NoSuchProviderException, NoSuchPaddingException {
if (provider == null) {
throw new IllegalArgumentException("provider == null");
}
Provider p = Security.getProvider(provider);
if (p == null) {
throw new NoSuchProviderException("Provider not available: " + provi
der);
}
return getInstance(transformation, p);
}
/**
* Creates a new cipher for the specified transformation.
*
* @param transformation
*
the name of the transformation to create a cipher for.
* @param provider
*
the provider to ask for the transformation.
* @return a cipher for the requested transformation.
* @throws NoSuchAlgorithmException
*
if the specified provider can not provide the
*
<i>transformation</i>, or it is {@code null}, empty or in an
*
invalid format.
* @throws NoSuchPaddingException
*
if the requested padding scheme in the <i>transformation</i>
*
is not available.
* @throws IllegalArgumentException
*
if the provider is {@code null}.
*/
public static final Cipher getInstance(String transformation,
Provider provider) throws NoSuchAlgorithmException,
NoSuchPaddingException {
if (provider == null) {
throw new IllegalArgumentException("provider == null");
}
Cipher c = getCipher(transformation, provider);
return c;
}
} catch (NoSuchAlgorithmException e) {
if (i == searchOrder.length-1) {
throw new NoSuchAlgorithmException(transformation, e);
}
}
}
switch (i) {
case 1: // "algorithm/mode"
needSetPadding = true;
break;
case 2: // "algorithm//padding"
needSetMode = true;
break;
case 3: // "algorithm"
needSetPadding = true;
needSetMode = true;
}
}
if (engineSpi == null || engineProvider == null) {
throw new NoSuchAlgorithmException(transformation);
}
if (!(engineSpi instanceof CipherSpi)) {
throw new NoSuchAlgorithmException(engineSpi.getClass().getName());
}
CipherSpi cspi = (CipherSpi) engineSpi;
Cipher c = new Cipher(cspi, engineProvider, transformation);
if (needSetMode) {
c.spiImpl.engineSetMode(transf[1]);
}
if (needSetPadding) {
c.spiImpl.engineSetPadding(transf[2]);
}
return c;
}
private static String[] checkTransformation(String transformation) throws No
SuchAlgorithmException {
// ignore an extra prefix / characters such as in
// "/DES/CBC/PKCS5Paddin" http://b/3387688
if (transformation.startsWith("/")) {
transformation = transformation.substring(1);
}
// 'transformation' should be of the form "algorithm/mode/padding".
String[] pieces = transformation.split("/");
if (pieces.length > 3) {
throw invalidTransformation(transformation);
}
// Empty or missing pieces are represented by null.
String[] result = new String[3];
for (int i = 0; i < pieces.length; ++i) {
String piece = pieces[i].trim();
if (!piece.isEmpty()) {
result[i] = piece;
}
}
// You MUST specify an algorithm.
if (result[0] == null) {
throw invalidTransformation(transformation);
}
if (!(result[1] == null && result[2] == null) && (result[1] == null || r
esult[2] == null)) {
throw invalidTransformation(transformation);
}
return result;
}
/**
* Returns the provider of this cipher instance.
*
* @return the provider of this cipher instance.
*/
public final Provider getProvider() {
return provider;
}
/**
* Returns the name of the algorithm of this cipher instance.
* <p>
* This is the name of the <i>transformation</i> argument used in the
* {@code getInstance} call creating this object.
*
* @return the name of the algorithm of this cipher instance.
*/
public final String getAlgorithm() {
return transformation;
}
/**
* Returns this ciphers block size (in bytes).
*
* @return this ciphers block size.
*/
public final int getBlockSize() {
return spiImpl.engineGetBlockSize();
}
/**
* Returns the length in bytes an output buffer needs to be when this cipher
* is updated with {@code inputLen} bytes.
*
* @param inputLen
*
the number of bytes of the input.
* @return the output buffer length for the input length.
* @throws IllegalStateException
*
if this cipher instance is in an invalid state.
*/
public final int getOutputSize(int inputLen) {
if (mode == 0) {
throw new IllegalStateException("Cipher has not yet been initialized
");
}
return spiImpl.engineGetOutputSize(inputLen);
}
/**
* Returns the <i>initialization vector</i> for this cipher instance.
*
* @return the <i>initialization vector</i> for this cipher instance.
*/
public final byte[] getIV() {
return spiImpl.engineGetIV();
}
/**
* Returns the parameters that where used to create this cipher instance.
* <p>
* These may be a the same parameters that were used to create this cipher
* instance, or may be a combination of default and random parameters,
* depending on the underlying cipher implementation.
*
* @return the parameters that where used to create this cipher instance, or
*
{@code null} if this cipher instance does not have any
*
parameters.
*/
public final AlgorithmParameters getParameters() {
return spiImpl.engineGetParameters();
}
/**
* Returns the exemption mechanism associated with this cipher.
*
* @return currently {@code null}
*/
public final ExemptionMechanism getExemptionMechanism() {
//FIXME implement getExemptionMechanism
//
//
try {
return ExemptionMechanism.getInstance(transformation, prov
ider);
//
} catch (NoSuchAlgorithmException e) {
return null;
//
}
}
/**
* Initializes this cipher instance with the specified key.
* <p>
* The cipher is initialized for the specified operational mode (one of:
* encryption, decryption, key wrapping or key unwrapping) depending on
* {@code opmode}.
* <p>
* If this cipher instance needs any algorithm parameters or random values
* that the specified key can not provide, the underlying implementation of
* this cipher is supposed to generate the required parameters (using its
* provider or random values).
* <p>
* When a cipher instance is initialized by a call to any of the {@code
* init} methods, the state of the instance is overridden, meaning that it
* is equivalent to creating a new instance and calling its {@code init}
* method.
*
* @param opmode
*
the operation this cipher instance should be initialized for
*
(one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
*
WRAP_MODE} or {@code UNWRAP_MODE}).
* @param key
*
the input key for the operation.
* @throws InvalidKeyException
*
if the specified key can not be used to initialize this
*
cipher instance.
*/
public final void init(int opmode, Key key) throws InvalidKeyException {
if (secureRandom == null) {
// In theory it might be thread-unsafe but in the given case it's OK
// since it does not matter which SecureRandom instance is passed
// to the init()
secureRandom = new SecureRandom();
}
init(opmode, key, secureRandom);
}
/**
* Initializes this cipher instance with the specified key and a source of
* randomness.
* <p>
* The cipher is initialized for the specified operational mode (one of:
* encryption, decryption, key wrapping or key unwrapping) depending on
* {@code opmode}.
* <p>
* If this cipher instance needs any algorithm parameters or random values
* that the specified key can not provide, the underlying implementation of
* this cipher is supposed to generate the required parameters (using its
* provider or random values). Random values are generated using {@code
* random};
* <p>
* When a cipher instance is initialized by a call to any of the {@code
* init} methods, the state of the instance is overridden, means it is
* equivalent to creating a new instance and calling it {@code init} method.
*
* @param opmode
*
the operation this cipher instance should be initialized for
*
(one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
*
WRAP_MODE} or {@code UNWRAP_MODE}).
* @param key
*
the input key for the operation.
* @param random
*
the source of randomness to use.
* @throws InvalidKeyException
*
if the specified key can not be used to initialize this
*
cipher instance.
* @throws InvalidParameterException
*
if the specified opmode is invalid.
*/
public final void init(int opmode, Key key, SecureRandom random) throws Inva
lidKeyException {
checkMode(opmode);
//
FIXME InvalidKeyException
//
if keysize exceeds the maximum allowable keysize
//
(jurisdiction policy files)
spiImpl.engineInit(opmode, key, random);
mode = opmode;
}
private void checkMode(int mode) {
if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE
&& mode != UNWRAP_MODE && mode != WRAP_MODE) {
throw new InvalidParameterException("Invalid mode: " + mode);
}
}
/**
* Initializes this cipher instance with the specified key and algorithm
* parameters.
* <p>
* The cipher is initialized for the specified operational mode (one of:
* encryption, decryption, key wrapping or key unwrapping).
* <p>
* If this cipher instance needs any algorithm parameters and {@code params}
* is {@code null}, the underlying implementation of this cipher is supposed
* to generate the required parameters (using its provider or random
* values).
* <p>
* When a cipher instance is initialized by a call to any of the {@code
* init} methods, the state of the instance is overridden, means it is
* equivalent to creating a new instance and calling it {@code init} method.
*
* @param opmode
*
the operation this cipher instance should be initialized for
*
(one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
*
WRAP_MODE} or {@code UNWRAP_MODE}).
* @param key
*
the input key for the operation.
* @param params
*
the algorithm parameters.
* @throws InvalidKeyException
*
if the specified key can not be used to initialize this
*
cipher instance.
* @throws InvalidAlgorithmParameterException
*
it the specified parameters are inappropriate for this
*
cipher.
*/
public final void init(int opmode, Key key, AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException {
if (secureRandom == null) {
secureRandom = new SecureRandom();
}
init(opmode, key, params, secureRandom);
}
/**
* Initializes this cipher instance with the specified key, algorithm
* parameters and a source of randomness.
* <p>
* The cipher is initialized for the specified operational mode (one of:
* encryption, decryption, key wrapping or key unwrapping) depending on
* {@code opmode}.
* <p>
* If this cipher instance needs any algorithm parameters and {@code params}
* is {@code null}, the underlying implementation of this cipher is supposed
* to generate the required parameters (using its provider or random
* values). Random values are generated using {@code random};
* <p>
* When a cipher instance is initialized by a call to any of the {@code
* init} methods, the state of the instance is overridden, meaning that it
* is equivalent to creating a new instance and calling it {@code init}
* method.
*
* @param opmode
*
the operation this cipher instance should be initialized for
*
(one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
*
WRAP_MODE} or {@code UNWRAP_MODE}).
* @param key
*
the input key for the operation.
* @param params
*
the algorithm parameters.
* @param random
*
the source of randomness to use.
* @throws InvalidKeyException
*
if the specified key can not be used to initialize this
*
cipher instance.
* @throws InvalidAlgorithmParameterException
*
it the specified parameters are inappropriate for this
*
cipher.
* @throws InvalidParameterException
*
if the specified {@code opmode} is invalid.
*/
public final void init(int opmode, Key key, AlgorithmParameterSpec params,
SecureRandom random) throws InvalidKeyException,
InvalidAlgorithmParameterException {
checkMode(opmode);
//
FIXME InvalidKeyException
//
if keysize exceeds the maximum allowable keysize
//
(jurisdiction policy files)
//
FIXME InvalidAlgorithmParameterException
//
cryptographic strength exceed the legal limits
//
(jurisdiction policy files)
spiImpl.engineInit(opmode, key, params, random);
mode = opmode;
}
/**
* Initializes this cipher instance with the specified key and algorithm
* parameters.
* <p>
* The cipher is initialized for the specified operation (one of:
* encryption, decryption, key wrapping or key unwrapping) depending on
* {@code opmode}.
* <p>
* If this cipher instance needs any algorithm parameters and {@code params}
* is {@code null}, the underlying implementation of this cipher is supposed
* to generate the required parameters (using its provider or random
* values).
* <p>
* When a cipher instance is initialized by a call to any of the {@code
* init} methods, the state of the instance is overridden, meaning that it
* is equivalent to creating a new instance and calling it {@code init}
* method.
*
* @param opmode
*
the operation this cipher instance should be initialized for
*
(one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
*
WRAP_MODE} or {@code UNWRAP_MODE}).
* @param key
*
the input key for the operation.
* @param params
*
the algorithm parameters.
* @throws InvalidKeyException
*
if the specified key can not be used to initialize this
*
cipher instance.
* @throws InvalidAlgorithmParameterException
*
it the specified parameters are inappropriate for this
*
cipher.
*/
public final void init(int opmode, Key key, AlgorithmParameters params)
throws InvalidKeyException, InvalidAlgorithmParameterException {
if (secureRandom == null) {
secureRandom = new SecureRandom();
}
init(opmode, key, params, secureRandom);
}
/**
* Initializes this cipher instance with the specified key, algorithm
* parameters and a source of randomness.
* <p>
* The cipher will be initialized for the specified operation (one of:
* encryption, decryption, key wrapping or key unwrapping) depending on
* {@code opmode}.
* <p>
* If this cipher instance needs any algorithm parameters and {@code params}
* is {@code null}, the underlying implementation of this cipher is supposed
* to generate the required parameters (using its provider or random
* values). Random values are generated using {@code random}.
* <p>
* When a cipher instance is initialized by a call to any of the {@code
* init} methods, the state of the instance is overridden, means it is
* equivalent to creating a new instance and calling it {@code init} method.
*
* @param opmode
*
the operation this cipher instance should be initialized for
*
(one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
*
WRAP_MODE} or {@code UNWRAP_MODE}).
* @param key
*
the input key for the operation.
* @param params
*
the algorithm parameters.
* @param random
*
the source of randomness to use.
* @throws InvalidKeyException
*
if the specified key can not be used to initialize this
*
cipher instance.
* @throws InvalidAlgorithmParameterException
*
if the specified parameters are inappropriate for this
*
cipher.
* @throws InvalidParameterException
*
if the specified {@code opmode} is invalid.
*/
public final void init(int opmode, Key key, AlgorithmParameters params,
SecureRandom random) throws InvalidKeyException,
InvalidAlgorithmParameterException {
checkMode(opmode);
//
FIXME InvalidKeyException
//
if keysize exceeds the maximum allowable keysize
//
(jurisdiction policy files)
//
FIXME InvalidAlgorithmParameterException
//
cryptographic strength exceed the legal limits
//
(jurisdiction policy files)
spiImpl.engineInit(opmode, key, params, random);
mode = opmode;
}
/**
* Initializes this cipher instance with the public key from the specified
* certificate.
* <p>
* The cipher will be initialized for the specified operation (one of:
* encryption, decryption, key wrapping or key unwrapping) depending on
* {@code opmode}.
* <p>
* It the type of the certificate is X.509 and the certificate has a <i>key
* usage</i> extension field marked as critical, the specified {@code
* opmode} has the be enabled for this key, otherwise an {@code
* InvalidKeyException} is thrown.
* <p>
* If this cipher instance needs any algorithm parameters that the key in
* the certificate can not provide, the underlying implementation of this
* cipher is supposed to generate the required parameters (using its
* provider or random values).
* <p>
* When a cipher instance is initialized by a call to any of the {@code
* init} methods, the state of the instance is overridden, means it is
* equivalent to creating a new instance and calling it {@code init} method.
*
* @param opmode
*
the operation this cipher instance should be initialized for
*
(one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
*
WRAP_MODE} or {@code UNWRAP_MODE}).
* @param certificate
*
the certificate.
* @throws InvalidKeyException
*
if the public key in the certificate can not be used to
*
initialize this cipher instance.
*/
public final void init(int opmode, Certificate certificate)
throws InvalidKeyException {
if (secureRandom == null) {
secureRandom = new SecureRandom();
}
init(opmode, certificate, secureRandom);
}
/**
* Initializes this cipher instance with the public key from the specified
* certificate and a source of randomness.
* <p>
* The cipher will be initialized for the specified operation (one of:
* encryption, decryption, key wrapping or key unwrapping) depending on
* {@code opmode}.
* <p>
* It the type of the certificate is X.509 and the certificate has a <i>key
* usage</i> extension field marked as critical, the specified {@code
* opmode} has the be enabled for this key, otherwise an {@code
* InvalidKeyException} is thrown.
* <p>
* If this cipher instance needs any algorithm parameters that the key in
* the certificate can not provide, the underlying implementation of this
* cipher is supposed to generate the required parameters (using its
* provider or random values). Random values are generated using {@code
* random}.
* <p>
* When a cipher instance is initialized by a call to any of the {@code
* init} methods, the state of the instance is overridden, means it is
* equivalent to creating a new instance and calling it {@code init} method.
*
* @param opmode
*
the operation this cipher instance should be initialized for
*
(one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
*
WRAP_MODE} or {@code UNWRAP_MODE}).
* @param certificate
*
the certificate.
* @param random
*
the source of randomness to be used.
* @throws InvalidKeyException
*
if the public key in the certificate can not be used to
*
initialize this cipher instance.
*/
public final void init(int opmode, Certificate certificate,
SecureRandom random) throws InvalidKeyException {
checkMode(opmode);
if (certificate instanceof X509Certificate) {
Set<String> ce = ((X509Certificate) certificate).getCriticalExtensio
nOIDs();
boolean critical = false;
if (ce != null && !ce.isEmpty()) {
for (String oid : ce) {
if (oid.equals("2.5.29.15")) { // KeyUsage OID = 2.5.29.15
critical = true;
break;
}
}
if (critical) {
boolean[] keyUsage = ((X509Certificate) certificate).getKeyU
sage();
// As specified in RFC 3280:
// Internet X.509 Public Key Infrastructure
// Certificate and Certificate Revocation List (CRL) Profi
le.
// Section 4.2.1.3 Key Usage
// http://www.ietf.org/rfc/rfc3280.txt
//
// KeyUsage ::= BIT STRING {digitalSignature (0),
//
nonRepudiation (1),
//
keyEncipherment (2),
//
dataEncipherment (3),
//
keyAgreement
(4),
//
keyCertSign
(5),
//
cRLSign
(6),
//
encipherOnly
(7),
//
decipherOnly
(8) }
if (keyUsage != null) {
if (opmode == ENCRYPT_MODE && !keyUsage[3]) {
throw new InvalidKeyException("The public key in the
certificate "
+ "cannot be used for
ENCRYPT_MODE");
} else if (opmode == WRAP_MODE && !keyUsage[2]) {
throw new InvalidKeyException("The public key in the
certificate "
+ "cannot be used for
WRAP_MODE");
}
}
}
}
}
//
FIXME InvalidKeyException
//
if keysize exceeds the maximum allowable keysize
//
(jurisdiction policy files)
spiImpl.engineInit(opmode, certificate.getPublicKey(), random);
mode = opmode;
}
/**
* Continues a multi-part transformation (encryption or decryption). The
* transformed bytes are returned.
*
* @param input
*
the input bytes to transform.
* @return the transformed bytes in a new buffer, or {@code null} if the
*
input has zero length.
* @throws IllegalStateException
*
if this cipher instance is not initialized for encryption or
*
decryption.
* @throws IllegalArgumentException
*
if the input is {@code null}.
*/
public final byte[] update(byte[] input) {
if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
throw new IllegalStateException();
}
if (input == null) {
throw new IllegalArgumentException("input == null");
}
if (input.length == 0) {
return null;
}
return spiImpl.engineUpdate(input, 0, input.length);
}
/**
* Continues a multi-part transformation (encryption or decryption). The
* transformed bytes are returned.
*
* @param input
*
the input bytes to transform.
* @param inputOffset
*
the offset in the input to start.
* @param inputLen
*
the length of the input to transform.
* @return the transformed bytes in a new buffer, or {@code null} if the
*
input has zero length.
* @throws IllegalStateException
*
if this cipher instance is not initialized for encryption or
*
decryption.
* @throws IllegalArgumentException
*
if the input is {@code null}, or if {@code inputOffset} and
*
{@code inputLen} do not specify a valid chunk in the input
*
buffer.
*/
/**
* Continues a multi-part transformation (encryption or decryption). The
* transformed bytes are stored in the {@code output} buffer.
* <p>
* If the size of the {@code output} buffer is too small to hold the result,
* a {@code ShortBufferException} is thrown. Use
* {@link Cipher#getOutputSize getOutputSize} to check for the size of the
* output buffer.
*
* @param input
*
the input bytes to transform.
* @param inputOffset
*
the offset in the input to start.
* @param inputLen
*
the length of the input to transform.
* @param output
*
the output buffer.
* @param outputOffset
*
the offset in the output buffer.
* @return the number of bytes placed in output.
* @throws ShortBufferException
*
if the size of the {@code output} buffer is too small.
* @throws IllegalStateException
*
if this cipher instance is not initialized for encryption or
*
decryption.
* @throws IllegalArgumentException
*
if the input is {@code null}, the output is {@code null}, or
*
if {@code inputOffset} and {@code inputLen} do not specify a
*
valid chunk in the input buffer.
*/
public final int update(byte[] input, int inputOffset, int inputLen,
byte[] output, int outputOffset) throws ShortBufferException {
if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
throw new IllegalStateException();
}
if (input == null) {
throw new IllegalArgumentException("input == null");
}
if (output == null) {
throw new IllegalArgumentException("output == null");
}
if (outputOffset < 0) {
throw new IllegalArgumentException("outputOffset < 0. outputOffset="
+ outputOffset);
}
checkInputOffsetAndCount(input.length, inputOffset, inputLen);
if (input.length == 0) {
return 0;
}
return spiImpl.engineUpdate(input, inputOffset, inputLen, output,
outputOffset);
}
/**
* Continues a multi-part transformation (encryption or decryption). The
* {@code input.remaining()} bytes starting at {@code input.position()} are
* transformed and stored in the {@code output} buffer.
* <p>
* If the {@code output.remaining()} is too small to hold the transformed
* bytes a {@code ShortBufferException} is thrown. Use
* @param output
*
the output buffer.
* @param outputOffset
*
the offset in the output buffer.
* @return the number of bytes placed in the output buffer.
* @throws IllegalBlockSizeException
*
if the size of the resulting bytes is not a multiple of the
*
cipher block size.
* @throws ShortBufferException
*
if the size of the {@code output} buffer is too small.
* @throws BadPaddingException
*
if the padding of the data does not match the padding scheme.
* @throws IllegalStateException
*
if this cipher instance is not initialized for encryption or
*
decryption.
*/
public final int doFinal(byte[] output, int outputOffset)
throws IllegalBlockSizeException, ShortBufferException,
BadPaddingException {
if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
throw new IllegalStateException();
}
if (outputOffset < 0) {
throw new IllegalArgumentException("outputOffset < 0. outputOffset="
+ outputOffset);
}
return spiImpl.engineDoFinal(null, 0, 0, output, outputOffset);
}
/**
* Finishes a multi-part transformation (encryption or decryption).
* <p>
* Processes the bytes in {@code input} buffer, and any bytes that have been
* buffered in previous {@code update} calls.
*
* @param input
*
the input buffer.
* @return the final bytes from the transformation.
* @throws IllegalBlockSizeException
*
if the size of the resulting bytes is not a multiple of the
*
cipher block size.
* @throws BadPaddingException
*
if the padding of the data does not match the padding scheme.
* @throws IllegalStateException
*
if this cipher instance is not initialized for encryption or
*
decryption.
*/
public final byte[] doFinal(byte[] input) throws IllegalBlockSizeException,
BadPaddingException {
if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
throw new IllegalStateException();
}
return spiImpl.engineDoFinal(input, 0, input.length);
}
/**
* Finishes a multi-part transformation (encryption or decryption).
* <p>
* Processes the {@code inputLen} bytes in {@code input} buffer at {@code
* inputOffset}, and any bytes that have been buffered in previous {@code
* update} calls.
*
* @param input
*
the input buffer.
* @param inputOffset
*
the offset in the input buffer.
* @param inputLen
*
the length of the input
* @return the final bytes from the transformation.
* @throws IllegalBlockSizeException
*
if the size of the resulting bytes is not a multiple of the
*
cipher block size.
* @throws BadPaddingException
*
if the padding of the data does not match the padding scheme.
* @throws IllegalStateException
*
if this cipher instance is not initialized for encryption or
*
decryption.
* @throws IllegalArgumentException
*
if {@code inputOffset} and {@code inputLen} do not specify an
*
valid chunk in the input buffer.
*/
public final byte[] doFinal(byte[] input, int inputOffset, int inputLen)
throws IllegalBlockSizeException, BadPaddingException {
if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
throw new IllegalStateException();
}
checkInputOffsetAndCount(input.length, inputOffset, inputLen);
return spiImpl.engineDoFinal(input, inputOffset, inputLen);
}
/**
* Finishes a multi-part transformation (encryption or decryption).
* <p>
* Processes the {@code inputLen} bytes in {@code input} buffer at {@code
* inputOffset}, and any bytes that have been buffered in previous {@code
* update} calls.
*
* @param input
*
the input buffer.
* @param inputOffset
*
the offset in the input buffer.
* @param inputLen
*
the length of the input.
* @param output
*
the output buffer for the transformed bytes.
* @return the number of bytes placed in the output buffer.
* @throws ShortBufferException
*
if the size of the {@code output} buffer is too small.
* @throws IllegalBlockSizeException
*
if the size of the resulting bytes is not a multiple of the
*
cipher block size.
* @throws BadPaddingException
*
if the padding of the data does not match the padding scheme.
* @throws IllegalStateException
*
if this cipher instance is not initialized for encryption or
*
decryption.
* @throws IllegalArgumentException
*
if {@code inputOffset} and {@code inputLen} do not specify an
*
valid chunk in the input buffer.
*/
*
the output buffer.
* @return the number of bytes placed into the output buffer.
* @throws ShortBufferException
*
if the size of the {@code output} buffer is too small.
* @throws IllegalBlockSizeException
*
if the size of the resulting bytes is not a multiple of the
*
cipher block size.
* @throws BadPaddingException
*
if the padding of the data does not match the padding scheme.
* @throws IllegalArgumentException
*
if the input buffer and the output buffer are the same
*
object.
* @throws IllegalStateException
*
if this cipher instance is not initialized for encryption or
*
decryption.
*/
public final int doFinal(ByteBuffer input, ByteBuffer output)
throws ShortBufferException, IllegalBlockSizeException,
BadPaddingException {
if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
throw new IllegalStateException();
}
if (input == output) {
throw new IllegalArgumentException("input == output");
}
return spiImpl.engineDoFinal(input, output);
}
/**
* Wraps a key using this cipher instance.
*
* @param key
*
the key to wrap.
* @return the wrapped key.
* @throws IllegalBlockSizeException
*
if the size of the resulting bytes is not a multiple of the
*
cipher block size.
* @throws InvalidKeyException
*
if this cipher instance can not wrap this key.
* @throws IllegalStateException
*
if this cipher instance is not initialized for wrapping.
*/
public final byte[] wrap(Key key) throws IllegalBlockSizeException,
InvalidKeyException {
if (mode != WRAP_MODE) {
throw new IllegalStateException();
}
return spiImpl.engineWrap(key);
}
/**
* Unwraps a key using this cipher instance.
*
* @param wrappedKey
*
the wrapped key to unwrap.
* @param wrappedKeyAlgorithm
*
the algorithm for the wrapped key.
* @param wrappedKeyType
*
the type of the wrapped key (one of: {@code SECRET_KEY
*
<code>, <code>PRIVATE_KEY} or {@code PUBLIC_KEY})