blob: d8153c448f5706d8d1b705520becbb8c607c4bcc [file] [log] [blame]
package org.bouncycastle.pqc.jcajce.provider.util;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.InvalidParameterException;
import java.security.Key;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.BadPaddingException;
import javax.crypto.ShortBufferException;
import org.bouncycastle.crypto.CryptoServicesRegistrar;
/**
* The AsymmetricHybridCipher class extends CipherSpiExt.
* NOTE: Some Ciphers are using Padding. OneAndZeroesPadding is used as default
* padding. However padding can still be specified, but mode is not supported;
* if you try to instantiate the cipher with something else than "NONE" as mode,
* NoSuchAlgorithmException is thrown.
*/
public abstract class AsymmetricHybridCipher
extends CipherSpiExt
{
/**
* ParameterSpec used with this cipher
*/
protected AlgorithmParameterSpec paramSpec;
/**
* Since asymmetric hybrid ciphers do not support modes, this method does
* nothing.
*
* @param modeName the cipher mode (unused)
*/
protected final void setMode(String modeName)
{
// empty
}
/**
* Since asymmetric hybrid ciphers do not support padding, this method does
* nothing.
*
* @param paddingName the name of the padding scheme (not used)
*/
protected final void setPadding(String paddingName)
{
// empty
}
/**
* @return <tt>null</tt> since no initialization vector is used.
*/
public final byte[] getIV()
{
return null;
}
/**
* @return 0 since the implementing algorithms are not block ciphers
*/
public final int getBlockSize()
{
return 0;
}
/**
* Return the parameters used with this cipher.
* <p>
* The returned parameters may be the same that were used to initialize this
* cipher, or may contain the default set of parameters or a set of randomly
* generated parameters used by the underlying cipher implementation
* (provided that the underlying cipher implementation uses a default set of
* parameters or creates new parameters if it needs parameters but was not
* initialized with any).
* </p>
* @return the parameters used with this cipher, or <tt>null</tt> if this
* cipher does not use any parameters.
*/
public final AlgorithmParameterSpec getParameters()
{
return paramSpec;
}
/**
* Return the length in bytes that an output buffer would need to be in
* order to hold the result of the next update or doFinal operation, given
* the input length <tt>inLen</tt> (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 inLen the length of the input
* @return the length of the output of the next <tt>update()</tt> or
* <tt>doFinal()</tt> call
*/
public final int getOutputSize(int inLen)
{
return opMode == ENCRYPT_MODE ? encryptOutputSize(inLen)
: decryptOutputSize(inLen);
}
/**
* Initialize the cipher for encryption by forwarding it to
* {@link #initEncrypt(Key, AlgorithmParameterSpec, SecureRandom)}.
* <p>
* 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, and raise an
* InvalidKeyException if it is being initialized for decryption. The
* generated parameters can be retrieved using {@link #getParameters()}.
* </p>
* @param key the encryption key
* @throws InvalidKeyException if the given key is inappropriate for initializing this
* cipher.
* @throws InvalidParameterException if this cipher needs algorithm parameters for
* initialization and cannot generate parameters itself.
*/
public final void initEncrypt(Key key)
throws InvalidKeyException
{
try
{
initEncrypt(key, null, CryptoServicesRegistrar.getSecureRandom());
}
catch (InvalidAlgorithmParameterException e)
{
throw new InvalidParameterException(
"This cipher needs algorithm parameters for initialization (cannot be null).");
}
}
/**
* Initialize this cipher for encryption by forwarding it to
* {@link #initEncrypt(Key, AlgorithmParameterSpec, SecureRandom)}.
* <p>
* 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, and raise an
* InvalidKeyException if it is being initialized for decryption. The
* generated parameters can be retrieved using {@link #getParameters()}.
* </p>
* @param key the encryption key
* @param random the source of randomness
* @throws InvalidKeyException if the given key is inappropriate for initializing this
* cipher.
* @throws InvalidParameterException if this cipher needs algorithm parameters for
* initialization and cannot generate parameters itself.
*/
public final void initEncrypt(Key key, SecureRandom random)
throws InvalidKeyException
{
try
{
initEncrypt(key, null, random);
}
catch (InvalidAlgorithmParameterException iape)
{
throw new InvalidParameterException(
"This cipher needs algorithm parameters for initialization (cannot be null).");
}
}
/**
* Initialize the cipher for encryption by forwarding it to initEncrypt(Key,
* FlexiSecureRandom, AlgorithmParameterSpec).
*
* @param key the encryption key
* @param params the algorithm parameters
* @throws InvalidKeyException if the given key is inappropriate for initializing this
* cipher.
* @throws InvalidAlgorithmParameterException if the given algorithm parameters are inappropriate for
* this cipher, or if this cipher is initialized with
* <tt>null</tt> parameters and cannot generate parameters
* itself.
*/
public final void initEncrypt(Key key, AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException
{
initEncrypt(key, params, CryptoServicesRegistrar.getSecureRandom());
}
/**
* Initialize the cipher with a certain key for data encryption.
* <p>
* If this cipher requires any random bytes (e.g., for parameter
* generation), it will get them from <tt>random</tt>.
* </p><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.
* </p>
* @param key the encryption key
* @param random the source of randomness
* @param params the algorithm parameters
* @throws InvalidKeyException if the given key is inappropriate for initializing this
* cipher
* @throws InvalidAlgorithmParameterException if the given algorithm parameters are inappropriate for
* this cipher, or if this cipher is initialized with
* <tt>null</tt> parameters and cannot generate parameters
* itself.
*/
public final void initEncrypt(Key key, AlgorithmParameterSpec params,
SecureRandom random)
throws InvalidKeyException,
InvalidAlgorithmParameterException
{
opMode = ENCRYPT_MODE;
initCipherEncrypt(key, params, random);
}
/**
* Initialize the cipher for decryption by forwarding it to initDecrypt(Key,
* FlexiSecureRandom).
* <p>
* 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, and raise an
* InvalidKeyException if it is being initialized for decryption. The
* generated parameters can be retrieved using {@link #getParameters()}.
* </p>
* @param key the decryption key
* @throws InvalidKeyException if the given key is inappropriate for initializing this
* cipher.
*/
public final void initDecrypt(Key key)
throws InvalidKeyException
{
try
{
initDecrypt(key, null);
}
catch (InvalidAlgorithmParameterException iape)
{
throw new InvalidParameterException(
"This cipher needs algorithm parameters for initialization (cannot be null).");
}
}
/**
* Initialize the cipher with a certain key for data decryption.
* <p>
* If this cipher requires any random bytes (e.g., for parameter
* generation), it will get them from <tt>random</tt>.
* </p><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
* </p>
* @param key the decryption key
* @param params the algorithm parameters
* @throws InvalidKeyException if the given key is inappropriate for initializing this
* cipher
* @throws InvalidAlgorithmParameterException if the given algorithm parameters are inappropriate for
* this cipher, or if this cipher is initialized with
* <tt>null</tt> parameters and cannot generate parameters
* itself.
*/
public final void initDecrypt(Key key, AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException
{
opMode = DECRYPT_MODE;
initCipherDecrypt(key, params);
}
/**
* Continue a multiple-part encryption or decryption operation (depending on
* how this cipher was initialized), processing another data part.
*
* @param input the input buffer
* @param inOff the offset where the input starts
* @param inLen the input length
* @return a new buffer with the result (maybe an empty byte array)
*/
public abstract byte[] update(byte[] input, int inOff, int inLen);
/**
* Continue a multiple-part encryption or decryption operation (depending on
* how this cipher was initialized), processing another data part.
*
* @param input the input buffer
* @param inOff the offset where the input starts
* @param inLen the input length
* @param output the output buffer
* @param outOff the offset where the result is stored
* @return the length of the output
* @throws ShortBufferException if the output buffer is too small to hold the result.
*/
public final int update(byte[] input, int inOff, int inLen, byte[] output,
int outOff)
throws ShortBufferException
{
if (output.length < getOutputSize(inLen))
{
throw new ShortBufferException("output");
}
byte[] out = update(input, inOff, inLen);
System.arraycopy(out, 0, output, outOff, out.length);
return out.length;
}
/**
* Finish a multiple-part encryption or decryption operation (depending on
* how this cipher was initialized).
*
* @param input the input buffer
* @param inOff the offset where the input starts
* @param inLen the input length
* @return a new buffer with the result
* @throws BadPaddingException if the ciphertext is invalid.
*/
public abstract byte[] doFinal(byte[] input, int inOff, int inLen)
throws BadPaddingException;
/**
* Finish a multiple-part encryption or decryption operation (depending on
* how this cipher was initialized).
*
* @param input the input buffer
* @param inOff the offset where the input starts
* @param inLen the input length
* @param output the buffer for the result
* @param outOff the offset where the result is stored
* @return the output length
* @throws ShortBufferException if the output buffer is too small to hold the result.
* @throws BadPaddingException if the ciphertext is invalid.
*/
public final int doFinal(byte[] input, int inOff, int inLen, byte[] output,
int outOff)
throws ShortBufferException, BadPaddingException
{
if (output.length < getOutputSize(inLen))
{
throw new ShortBufferException("Output buffer too short.");
}
byte[] out = doFinal(input, inOff, inLen);
System.arraycopy(out, 0, output, outOff, out.length);
return out.length;
}
/**
* Compute the output size of an update() or doFinal() operation of a hybrid
* asymmetric cipher in encryption mode when given input of the specified
* length.
*
* @param inLen the length of the input
* @return the output size
*/
protected abstract int encryptOutputSize(int inLen);
/**
* Compute the output size of an update() or doFinal() operation of a hybrid
* asymmetric cipher in decryption mode when given input of the specified
* length.
*
* @param inLen the length of the input
* @return the output size
*/
protected abstract int decryptOutputSize(int inLen);
/**
* Initialize the AsymmetricHybridCipher with a certain key for data
* encryption.
*
* @param key the key which has to be used to encrypt data
* @param params the algorithm parameters
* @param sr the source of randomness
* @throws InvalidKeyException if the given key is inappropriate for initializing this
* cipher.
* @throws InvalidAlgorithmParameterException if the given parameters are inappropriate for
* initializing this cipher.
*/
protected abstract void initCipherEncrypt(Key key,
AlgorithmParameterSpec params, SecureRandom sr)
throws InvalidKeyException, InvalidAlgorithmParameterException;
/**
* Initialize the AsymmetricHybridCipher with a certain key for data
* encryption.
*
* @param key the key which has to be used to decrypt data
* @param params the algorithm parameters
* @throws InvalidKeyException if the given key is inappropriate for initializing this
* cipher
* @throws InvalidAlgorithmParameterException if the given parameters are inappropriate for
* initializing this cipher.
*/
protected abstract void initCipherDecrypt(Key key,
AlgorithmParameterSpec params)
throws InvalidKeyException,
InvalidAlgorithmParameterException;
}