Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'prov/src/main/java/org/spongycastle/pqc/jcajce/provider/util/AsymmetricBlockCipher.java')
-rw-r--r--prov/src/main/java/org/spongycastle/pqc/jcajce/provider/util/AsymmetricBlockCipher.java522
1 files changed, 522 insertions, 0 deletions
diff --git a/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/util/AsymmetricBlockCipher.java b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/util/AsymmetricBlockCipher.java
new file mode 100644
index 00000000..2e5678ad
--- /dev/null
+++ b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/util/AsymmetricBlockCipher.java
@@ -0,0 +1,522 @@
+package org.spongycastle.pqc.jcajce.provider.util;
+
+import java.io.ByteArrayOutputStream;
+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.IllegalBlockSizeException;
+import javax.crypto.ShortBufferException;
+
+
+/**
+ * The AsymmetricBlockCipher 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 AsymmetricBlockCipher
+ extends CipherSpiExt
+{
+
+ /**
+ * ParameterSpec used with this cipher
+ */
+ protected AlgorithmParameterSpec paramSpec;
+
+ /**
+ * Internal buffer
+ */
+ protected ByteArrayOutputStream buf;
+
+ /**
+ * The maximum number of bytes the cipher can decrypt.
+ */
+ protected int maxPlainTextSize;
+
+ /**
+ * The maximum number of bytes the cipher can encrypt.
+ */
+ protected int cipherTextSize;
+
+ /**
+ * The AsymmetricBlockCipher() constructor
+ */
+ public AsymmetricBlockCipher()
+ {
+ buf = new ByteArrayOutputStream();
+ }
+
+ /**
+ * Return the block size (in bytes). Note: although the ciphers extending
+ * this class are not block ciphers, the method was adopted to return the
+ * maximal plaintext and ciphertext sizes for non hybrid ciphers. If the
+ * cipher is hybrid, it returns 0.
+ *
+ * @return if the cipher is not a hybrid one the max plain/cipher text size
+ * is returned, otherwise 0 is returned
+ */
+ public final int getBlockSize()
+ {
+ return opMode == ENCRYPT_MODE ? maxPlainTextSize : cipherTextSize;
+ }
+
+ /**
+ * @return <tt>null</tt> since no initialization vector is used.
+ */
+ public final byte[] getIV()
+ {
+ return null;
+ }
+
+ /**
+ * 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.
+ * <p/>
+ * If the input length plus the length of the buffered data exceeds the
+ * maximum length, <tt>0</tt> is returned.
+ *
+ * @param inLen the length of the input
+ * @return the length of the ciphertext or <tt>0</tt> if the input is too
+ * long.
+ */
+ public final int getOutputSize(int inLen)
+ {
+
+ int totalLen = inLen + buf.size();
+
+ int maxLen = getBlockSize();
+
+ if (totalLen > maxLen)
+ {
+ // the length of the input exceeds the maximal supported length
+ return 0;
+ }
+
+ return maxLen;
+ }
+
+ /**
+ * <p/>
+ * Returns 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 null if this cipher does
+ * not use any parameters.
+ */
+ public final AlgorithmParameterSpec getParameters()
+ {
+ return paramSpec;
+ }
+
+ /**
+ * Initializes the cipher for encryption by forwarding it to
+ * initEncrypt(Key, FlexiSecureRandom).
+ * <p/>
+ * <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 engineGetParameters or
+ * engineGetIV (if the parameter is an IV).
+ *
+ * @param key the encryption or decryption key.
+ * @throws InvalidKeyException if the given key is inappropriate for initializing this
+ * cipher.
+ */
+ public final void initEncrypt(Key key)
+ throws InvalidKeyException
+ {
+ try
+ {
+ initEncrypt(key, null, new SecureRandom());
+ }
+ 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
+ * initEncrypt(Key, FlexiSecureRandom, AlgorithmParameterSpec).
+ * <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 engineGetParameters or
+ * engineGetIV (if the parameter is an IV).
+ *
+ * @param key the encryption or decryption key.
+ * @param random the source of randomness.
+ * @throws InvalidKeyException if the given key is inappropriate for initializing this
+ * cipher.
+ */
+ 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).");
+ }
+ }
+
+ /**
+ * Initializes the cipher for encryption by forwarding it to
+ * initEncrypt(Key, FlexiSecureRandom, AlgorithmParameterSpec).
+ *
+ * @param key the encryption or decryption key.
+ * @param params the algorithm parameters.
+ * @throws InvalidKeyException if the given key is inappropriate for initializing this
+ * cipher.
+ * @throws InvalidAlgorithmParameterException if the given algortihm parameters are inappropriate for
+ * this cipher, or if this cipher is being initialized for
+ * decryption and requires algorithm parameters and params
+ * is null.
+ */
+ public final void initEncrypt(Key key, AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ initEncrypt(key, params, new SecureRandom());
+ }
+
+ /**
+ * This method initializes the AsymmetricBlockCipher with a certain key for
+ * data encryption.
+ * <p/>
+ * 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.
+ * <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 key which has to be used to encrypt data.
+ * @param secureRandom 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 being initialized for
+ * decryption and requires algorithm parameters and params
+ * is null.
+ */
+ public final void initEncrypt(Key key, AlgorithmParameterSpec params,
+ SecureRandom secureRandom)
+ throws InvalidKeyException,
+ InvalidAlgorithmParameterException
+ {
+ opMode = ENCRYPT_MODE;
+ initCipherEncrypt(key, params, secureRandom);
+ }
+
+ /**
+ * Initialize the cipher for decryption by forwarding it to
+ * {@link #initDecrypt(Key, AlgorithmParameterSpec)}.
+ * <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 engineGetParameters or
+ * engineGetIV (if the parameter is an IV).
+ *
+ * @param key the encryption or 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).");
+ }
+ }
+
+ /**
+ * This method initializes the AsymmetricBlockCipher with a certain key for
+ * data decryption.
+ * <p/>
+ * 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.
+ * <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 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 algorithm parameters are inappropriate for
+ * this cipher, or if this cipher is being initialized for
+ * decryption and requires algorithm parameters and params
+ * is null.
+ */
+ 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. This method
+ * just writes the input into an internal buffer.
+ *
+ * @param input byte array containing the next part of the input
+ * @param inOff index in the array where the input starts
+ * @param inLen length of the input
+ * @return a new buffer with the result (always empty)
+ */
+ public final byte[] update(byte[] input, int inOff, int inLen)
+ {
+ if (inLen != 0)
+ {
+ buf.write(input, inOff, inLen);
+ }
+ return new byte[0];
+ }
+
+ /**
+ * 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 (always 0)
+ */
+ public final int update(byte[] input, int inOff, int inLen, byte[] output,
+ int outOff)
+ {
+ update(input, inOff, inLen);
+ return 0;
+ }
+
+ /**
+ * 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 IllegalBlockSizeException if the plaintext or ciphertext size is too large.
+ * @throws BadPaddingException if the ciphertext is invalid.
+ */
+ public final byte[] doFinal(byte[] input, int inOff, int inLen)
+ throws IllegalBlockSizeException, BadPaddingException
+ {
+
+ checkLength(inLen);
+ update(input, inOff, inLen);
+ byte[] mBytes = buf.toByteArray();
+ buf.reset();
+
+ switch (opMode)
+ {
+ case ENCRYPT_MODE:
+ return messageEncrypt(mBytes);
+
+ case DECRYPT_MODE:
+ return messageDecrypt(mBytes);
+
+ default:
+ return null;
+
+ }
+ }
+
+ /**
+ * 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 IllegalBlockSizeException if the plaintext or ciphertext size is too large.
+ * @throws BadPaddingException if the ciphertext is invalid.
+ */
+ public final int doFinal(byte[] input, int inOff, int inLen, byte[] output,
+ int outOff)
+ throws ShortBufferException, IllegalBlockSizeException,
+ 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;
+ }
+
+ /**
+ * Since asymmetric block ciphers do not support modes, this method does
+ * nothing.
+ *
+ * @param modeName the cipher mode (unused)
+ */
+ protected final void setMode(String modeName)
+ {
+ // empty
+ }
+
+ /**
+ * Since asymmetric block 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
+ }
+
+ /**
+ * Check if the message length plus the length of the input length can be
+ * en/decrypted. This method uses the specific values
+ * {@link #maxPlainTextSize} and {@link #cipherTextSize} which are set by
+ * the implementations. If the input length plus the length of the internal
+ * buffer is greater than {@link #maxPlainTextSize} for encryption or not
+ * equal to {@link #cipherTextSize} for decryption, an
+ * {@link IllegalBlockSizeException} will be thrown.
+ *
+ * @param inLen length of the input to check
+ * @throws IllegalBlockSizeException if the input length is invalid.
+ */
+ protected void checkLength(int inLen)
+ throws IllegalBlockSizeException
+ {
+
+ int inLength = inLen + buf.size();
+
+ if (opMode == ENCRYPT_MODE)
+ {
+ if (inLength > maxPlainTextSize)
+ {
+ throw new IllegalBlockSizeException(
+ "The length of the plaintext (" + inLength
+ + " bytes) is not supported by "
+ + "the cipher (max. " + maxPlainTextSize
+ + " bytes).");
+ }
+ }
+ else if (opMode == DECRYPT_MODE)
+ {
+ if (inLength != cipherTextSize)
+ {
+ throw new IllegalBlockSizeException(
+ "Illegal ciphertext length (expected " + cipherTextSize
+ + " bytes, was " + inLength + " bytes).");
+ }
+ }
+
+ }
+
+ /**
+ * Initialize the AsymmetricBlockCipher 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 AsymmetricBlockCipher 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;
+
+ /**
+ * Encrypt the message stored in input. The method should also perform an
+ * additional length check.
+ *
+ * @param input the message to be encrypted (usually the message length is
+ * less than or equal to maxPlainTextSize)
+ * @return the encrypted message (it has length equal to maxCipherTextSize_)
+ * @throws IllegalBlockSizeException if the input is inappropriate for this cipher.
+ * @throws BadPaddingException if the input format is invalid.
+ */
+ protected abstract byte[] messageEncrypt(byte[] input)
+ throws IllegalBlockSizeException, BadPaddingException;
+
+ /**
+ * Decrypt the ciphertext stored in input. The method should also perform an
+ * additional length check.
+ *
+ * @param input the ciphertext to be decrypted (the ciphertext length is
+ * less than or equal to maxCipherTextSize)
+ * @return the decrypted message
+ * @throws IllegalBlockSizeException if the input is inappropriate for this cipher.
+ * @throws BadPaddingException if the input format is invalid.
+ */
+ protected abstract byte[] messageDecrypt(byte[] input)
+ throws IllegalBlockSizeException, BadPaddingException;
+
+}