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 Service Provider Interface (SPI)
* for the Cipher
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.
*
* In order to create an instance of Cipher
, which
* encapsulates an instance of this CipherSpi
class, an
* application calls one of the
* getInstance
* factory methods of the
* Cipher engine class and specifies the requested
* transformation.
* Optionally, the application may also specify the name of a provider.
*
* A transformation 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., DES), and may be followed by a feedback mode and * padding scheme. *
* A transformation is of the form: *
*
*
(in the latter case, * provider-specific default values for the mode and padding scheme are used). * For example, the following is a valid transformation:
* *
* Cipher c = Cipher.getInstance("DES/CBC/PKCS5Padding"); ** *
A provider may supply a separate class for each combination
* of algorithm/mode/padding, or may decide to provide more generic
* classes representing sub-transformations corresponding to
* algorithm or algorithm/mode or algorithm//padding
* (note the double slashes),
* in which case the requested mode and/or padding are set automatically by
* the getInstance
methods of Cipher
, which invoke
* the engineSetMode and
* engineSetPadding
* methods of the provider's subclass of CipherSpi
.
*
*
A Cipher
property in a provider master class may have one of
* the following formats:
*
*
* // provider's subclass of "CipherSpi" implements "algName" with
* // pluggable mode and padding
* Cipher.
algName
*
*
*
* // provider's subclass of "CipherSpi" implements "algName" in the
* // specified "mode", with pluggable padding
* Cipher.
algName/mode
*
*
*
* // provider's subclass of "CipherSpi" implements "algName" with the
* // specified "padding", with pluggable mode
* Cipher.
algName//padding
*
*
*
* // provider's subclass of "CipherSpi" implements "algName" with the
* // specified "mode" and "padding"
* Cipher.
algName/mode/padding
*
*
* For example, a provider may supply a subclass of CipherSpi
* that implements DES/ECB/PKCS5Padding, one that implements
* DES/CBC/PKCS5Padding, one that implements
* DES/CFB/PKCS5Padding, and yet another one that implements
* DES/OFB/PKCS5Padding. That provider would have the following
* Cipher
properties in its master class:
* *
* Cipher.
DES/ECB/PKCS5Padding
*
*
*
* Cipher.
DES/CBC/PKCS5Padding
*
*
*
* Cipher.
DES/CFB/PKCS5Padding
*
*
*
* Cipher.
DES/OFB/PKCS5Padding
*
*
* Another provider may implement a class for each of the above modes
* (i.e., one class for ECB, one for CBC, one for CFB,
* and one for OFB), one class for PKCS5Padding,
* and a generic DES class that subclasses from CipherSpi
.
* That provider would have the following
* Cipher
properties in its master class:
* *
* Cipher.
DES
*
*
* The getInstance
factory method of the Cipher
* engine class follows these rules in order to instantiate a provider's
* implementation of CipherSpi
for a
* transformation of the form "algorithm":
*
*
CipherSpi
* for the specified "algorithm".
* If the answer is YES, instantiate this * class, for whose mode and padding scheme default values (as supplied by * the provider) are used. *
If the answer is NO, throw a NoSuchAlgorithmException
* exception.
*
The getInstance
factory method of the Cipher
* engine class follows these rules in order to instantiate a provider's
* implementation of CipherSpi
for a
* transformation of the form "algorithm/mode/padding":
*
*
CipherSpi
* for the specified "algorithm/mode/padding" transformation.
* If the answer is YES, instantiate it. *
If the answer is NO, go to the next step.
*
CipherSpi
* for the sub-transformation "algorithm/mode".
* If the answer is YES, instantiate it, and call
* engineSetPadding(padding)
on the new instance.
*
If the answer is NO, go to the next step.
*
CipherSpi
* for the sub-transformation "algorithm//padding" (note the double
* slashes).
* If the answer is YES, instantiate it, and call
* engineSetMode(mode)
on the new instance.
*
If the answer is NO, go to the next step.
*
CipherSpi
* for the sub-transformation "algorithm".
* If the answer is YES, instantiate it, and call
* engineSetMode(mode)
and
* engineSetPadding(padding)
on the new instance.
*
If the answer is NO, throw a NoSuchAlgorithmException
* exception.
*
update
* or doFinal
operation, given the input length
* inputLen
(in bytes).
*
* This call takes into account any unprocessed (buffered) data from a
* previous update
call, and padding.
*
* The actual output length of the next update
or
* doFinal
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.
*
* 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. *
* 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. *
* The cipher is initialized for one of the following four operations:
* encryption, decryption, key wrapping or key unwrapping, depending on
* the value of opmode
.
*
* If this cipher requires any algorithm parameters that cannot be
* derived from the given key
, 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
* InvalidKeyException
if it is being
* initialized for decryption or key unwrapping.
* The generated parameters can be retrieved using
* engineGetParameters or
* engineGetIV (if the parameter is an IV).
*
* If this cipher (including its underlying feedback or padding scheme)
* requires any random bytes (e.g., for parameter generation), it will get
* them from random
.
*
*
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:
* ENCRYPT_MODE
, DECRYPT_MODE
,
* WRAP_MODE
or UNWRAP_MODE
)
* @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.
*
* The cipher is initialized for one of the following four operations:
* encryption, decryption, key wrapping or key unwrapping, depending on
* the value of opmode
.
*
* If this cipher requires any algorithm parameters and
* params
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
* InvalidAlgorithmParameterException
if it is being
* initialized for decryption or key unwrapping.
* The generated parameters can be retrieved using
* engineGetParameters or
* engineGetIV (if the parameter is an IV).
*
* If this cipher (including its underlying feedback or padding scheme)
* requires any random bytes (e.g., for parameter generation), it will get
* them from random
.
*
* 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:
* ENCRYPT_MODE
, DECRYPT_MODE
,
* WRAP_MODE
or UNWRAP_MODE
)
* @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 params
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.
*
* The cipher is initialized for one of the following four operations:
* encryption, decryption, key wrapping or key unwrapping, depending on
* the value of opmode
.
*
* If this cipher requires any algorithm parameters and
* params
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
* InvalidAlgorithmParameterException
if it is being
* initialized for decryption or key unwrapping.
* The generated parameters can be retrieved using
* engineGetParameters or
* engineGetIV (if the parameter is an IV).
*
* If this cipher (including its underlying feedback or padding scheme)
* requires any random bytes (e.g., for parameter generation), it will get
* them from random
.
*
* 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:
* ENCRYPT_MODE
, DECRYPT_MODE
, WRAP_MODE
* or UNWRAP_MODE
)
* @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 params
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.
*
* The first inputLen
bytes in the input
* buffer, starting at inputOffset
inclusive, are processed,
* and the result is stored in a new buffer.
*
* @param input the input buffer
* @param inputOffset the offset in input
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.
*
* The first inputLen
bytes in the input
* buffer, starting at inputOffset
inclusive, are processed,
* and the result is stored in the output
buffer, starting at
* outputOffset
inclusive.
*
* If the output
buffer is too small to hold the result,
* a ShortBufferException
is thrown.
*
* @param input the input buffer
* @param inputOffset the offset in input
where the input starts
* @param inputLen the input length
* @param output the buffer for the result
* @param outputOffset the offset in output
where the result is stored
* @return the number of bytes stored in output
* @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.
*
* The first inputLen
bytes in the input
* buffer, starting at inputOffset
inclusive, and any input
* bytes that may have been buffered during a previous update
* operation, are processed, with padding (if requested) being applied.
* The result is stored in a new buffer.
*
* A call to this method resets this cipher object to the state
* it was in when previously initialized via a call to engineInit
.
* That is, the object is reset and available to encrypt or decrypt
* (depending on the operation mode that was specified in the call to
* engineInit
) more data.
*
* @param input the input buffer
* @param inputOffset the offset in input
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.
*
* The first inputLen
bytes in the input
* buffer, starting at inputOffset
inclusive, and any input
* bytes that may have been buffered during a previous update
* operation, are processed, with padding (if requested) being applied.
* The result is stored in the output
buffer, starting at
* outputOffset
inclusive.
*
* If the output
buffer is too small to hold the result,
* a ShortBufferException
is thrown.
*
* A call to this method resets this cipher object to the state
* it was in when previously initialized via a call to
* engineInit
.
* That is, the object is reset and available to encrypt or decrypt
* (depending on the operation mode that was specified in the call to
* engineInit
) more data.
*
* @param input the input buffer
* @param inputOffset the offset in input
where the input starts
* @param inputLen the input length
* @param output the buffer for the result
* @param outputOffset the offset in output
where the result is stored
* @return the number of bytes stored in output
* @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.
*
* 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. * *
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 SECRET_KEY
,
* PRIVATE_KEY
, or PUBLIC_KEY
.
* @return the unwrapped key.
* @exception InvalidKeyException if wrappedKey
does not represent a wrapped key,
* or if the algorithm associated with the wrapped key is different from wrappedKeyAlgorithm
* and/or its key type is different from wrappedKeyType
.
* @exception NoSuchAlgorithmException - if no installed providers can create keys for the
* wrappedKeyAlgorithm
.
*/
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.
*
* This concrete method has been added to this previously-defined
* abstract class. It throws an UnsupportedOperationException
* 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 key
is invalid.
*/
protected int engineGetKeySize(
Key key)
throws InvalidKeyException
{
throw new UnsupportedOperationException("Key size unavailable");
}
}