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 'core/src/main/java/org/bouncycastle/crypto/paddings')
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/paddings/BlockCipherPadding.java48
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/paddings/ISO10126d2Padding.java79
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/paddings/ISO7816d4Padding.java77
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/paddings/PKCS7Padding.java76
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher.java299
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/paddings/TBCPadding.java89
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/paddings/X923Padding.java80
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/paddings/ZeroBytePadding.java73
8 files changed, 821 insertions, 0 deletions
diff --git a/core/src/main/java/org/bouncycastle/crypto/paddings/BlockCipherPadding.java b/core/src/main/java/org/bouncycastle/crypto/paddings/BlockCipherPadding.java
new file mode 100644
index 00000000..7c4f0aee
--- /dev/null
+++ b/core/src/main/java/org/bouncycastle/crypto/paddings/BlockCipherPadding.java
@@ -0,0 +1,48 @@
+package org.bouncycastle.crypto.paddings;
+
+import java.security.SecureRandom;
+
+import org.bouncycastle.crypto.InvalidCipherTextException;
+
+/**
+ * Block cipher padders are expected to conform to this interface
+ */
+public interface BlockCipherPadding
+{
+ /**
+ * Initialise the padder.
+ *
+ * @param random the source of randomness for the padding, if required.
+ */
+ public void init(SecureRandom random)
+ throws IllegalArgumentException;
+
+ /**
+ * Return the name of the algorithm the cipher implements.
+ *
+ * @return the name of the algorithm the cipher implements.
+ */
+ public String getPaddingName();
+
+ /**
+ * add the pad bytes to the passed in block, returning the
+ * number of bytes added.
+ * <p>
+ * Note: this assumes that the last block of plain text is always
+ * passed to it inside in. i.e. if inOff is zero, indicating the
+ * entire block is to be overwritten with padding the value of in
+ * should be the same as the last block of plain text. The reason
+ * for this is that some modes such as "trailing bit compliment"
+ * base the padding on the last byte of plain text.
+ * </p>
+ */
+ public int addPadding(byte[] in, int inOff);
+
+ /**
+ * return the number of pad bytes present in the block.
+ * @exception InvalidCipherTextException if the padding is badly formed
+ * or invalid.
+ */
+ public int padCount(byte[] in)
+ throws InvalidCipherTextException;
+}
diff --git a/core/src/main/java/org/bouncycastle/crypto/paddings/ISO10126d2Padding.java b/core/src/main/java/org/bouncycastle/crypto/paddings/ISO10126d2Padding.java
new file mode 100644
index 00000000..63e29d84
--- /dev/null
+++ b/core/src/main/java/org/bouncycastle/crypto/paddings/ISO10126d2Padding.java
@@ -0,0 +1,79 @@
+package org.bouncycastle.crypto.paddings;
+
+import java.security.SecureRandom;
+
+import org.bouncycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A padder that adds ISO10126-2 padding to a block.
+ */
+public class ISO10126d2Padding
+ implements BlockCipherPadding
+{
+ SecureRandom random;
+
+ /**
+ * Initialise the padder.
+ *
+ * @param random a SecureRandom if available.
+ */
+ public void init(SecureRandom random)
+ throws IllegalArgumentException
+ {
+ if (random != null)
+ {
+ this.random = random;
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ }
+ }
+
+ /**
+ * Return the name of the algorithm the padder implements.
+ *
+ * @return the name of the algorithm the padder implements.
+ */
+ public String getPaddingName()
+ {
+ return "ISO10126-2";
+ }
+
+ /**
+ * add the pad bytes to the passed in block, returning the
+ * number of bytes added.
+ */
+ public int addPadding(
+ byte[] in,
+ int inOff)
+ {
+ byte code = (byte)(in.length - inOff);
+
+ while (inOff < (in.length - 1))
+ {
+ in[inOff] = (byte)random.nextInt();
+ inOff++;
+ }
+
+ in[inOff] = code;
+
+ return code;
+ }
+
+ /**
+ * return the number of pad bytes present in the block.
+ */
+ public int padCount(byte[] in)
+ throws InvalidCipherTextException
+ {
+ int count = in[in.length - 1] & 0xff;
+
+ if (count > in.length)
+ {
+ throw new InvalidCipherTextException("pad block corrupted");
+ }
+
+ return count;
+ }
+}
diff --git a/core/src/main/java/org/bouncycastle/crypto/paddings/ISO7816d4Padding.java b/core/src/main/java/org/bouncycastle/crypto/paddings/ISO7816d4Padding.java
new file mode 100644
index 00000000..54c31a9b
--- /dev/null
+++ b/core/src/main/java/org/bouncycastle/crypto/paddings/ISO7816d4Padding.java
@@ -0,0 +1,77 @@
+package org.bouncycastle.crypto.paddings;
+
+import java.security.SecureRandom;
+
+import org.bouncycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A padder that adds the padding according to the scheme referenced in
+ * ISO 7814-4 - scheme 2 from ISO 9797-1. The first byte is 0x80, rest is 0x00
+ */
+public class ISO7816d4Padding
+ implements BlockCipherPadding
+{
+ /**
+ * Initialise the padder.
+ *
+ * @param random - a SecureRandom if available.
+ */
+ public void init(SecureRandom random)
+ throws IllegalArgumentException
+ {
+ // nothing to do.
+ }
+
+ /**
+ * Return the name of the algorithm the padder implements.
+ *
+ * @return the name of the algorithm the padder implements.
+ */
+ public String getPaddingName()
+ {
+ return "ISO7816-4";
+ }
+
+ /**
+ * add the pad bytes to the passed in block, returning the
+ * number of bytes added.
+ */
+ public int addPadding(
+ byte[] in,
+ int inOff)
+ {
+ int added = (in.length - inOff);
+
+ in [inOff]= (byte) 0x80;
+ inOff ++;
+
+ while (inOff < in.length)
+ {
+ in[inOff] = (byte) 0;
+ inOff++;
+ }
+
+ return added;
+ }
+
+ /**
+ * return the number of pad bytes present in the block.
+ */
+ public int padCount(byte[] in)
+ throws InvalidCipherTextException
+ {
+ int count = in.length - 1;
+
+ while (count > 0 && in[count] == 0)
+ {
+ count--;
+ }
+
+ if (in[count] != (byte)0x80)
+ {
+ throw new InvalidCipherTextException("pad block corrupted");
+ }
+
+ return in.length - count;
+ }
+}
diff --git a/core/src/main/java/org/bouncycastle/crypto/paddings/PKCS7Padding.java b/core/src/main/java/org/bouncycastle/crypto/paddings/PKCS7Padding.java
new file mode 100644
index 00000000..93b149fa
--- /dev/null
+++ b/core/src/main/java/org/bouncycastle/crypto/paddings/PKCS7Padding.java
@@ -0,0 +1,76 @@
+package org.bouncycastle.crypto.paddings;
+
+import java.security.SecureRandom;
+
+import org.bouncycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A padder that adds PKCS7/PKCS5 padding to a block.
+ */
+public class PKCS7Padding
+ implements BlockCipherPadding
+{
+ /**
+ * Initialise the padder.
+ *
+ * @param random - a SecureRandom if available.
+ */
+ public void init(SecureRandom random)
+ throws IllegalArgumentException
+ {
+ // nothing to do.
+ }
+
+ /**
+ * Return the name of the algorithm the padder implements.
+ *
+ * @return the name of the algorithm the padder implements.
+ */
+ public String getPaddingName()
+ {
+ return "PKCS7";
+ }
+
+ /**
+ * add the pad bytes to the passed in block, returning the
+ * number of bytes added.
+ */
+ public int addPadding(
+ byte[] in,
+ int inOff)
+ {
+ byte code = (byte)(in.length - inOff);
+
+ while (inOff < in.length)
+ {
+ in[inOff] = code;
+ inOff++;
+ }
+
+ return code;
+ }
+
+ /**
+ * return the number of pad bytes present in the block.
+ */
+ public int padCount(byte[] in)
+ throws InvalidCipherTextException
+ {
+ int count = in[in.length - 1] & 0xff;
+
+ if (count > in.length || count == 0)
+ {
+ throw new InvalidCipherTextException("pad block corrupted");
+ }
+
+ for (int i = 1; i <= count; i++)
+ {
+ if (in[in.length - i] != count)
+ {
+ throw new InvalidCipherTextException("pad block corrupted");
+ }
+ }
+
+ return count;
+ }
+}
diff --git a/core/src/main/java/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher.java
new file mode 100644
index 00000000..ee3fd60e
--- /dev/null
+++ b/core/src/main/java/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher.java
@@ -0,0 +1,299 @@
+package org.bouncycastle.crypto.paddings;
+
+import org.bouncycastle.crypto.BlockCipher;
+import org.bouncycastle.crypto.BufferedBlockCipher;
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.InvalidCipherTextException;
+import org.bouncycastle.crypto.OutputLengthException;
+import org.bouncycastle.crypto.params.ParametersWithRandom;
+
+/**
+ * A wrapper class that allows block ciphers to be used to process data in
+ * a piecemeal fashion with padding. The PaddedBufferedBlockCipher
+ * outputs a block only when the buffer is full and more data is being added,
+ * or on a doFinal (unless the current block in the buffer is a pad block).
+ * The default padding mechanism used is the one outlined in PKCS5/PKCS7.
+ */
+public class PaddedBufferedBlockCipher
+ extends BufferedBlockCipher
+{
+ BlockCipherPadding padding;
+
+ /**
+ * Create a buffered block cipher with the desired padding.
+ *
+ * @param cipher the underlying block cipher this buffering object wraps.
+ * @param padding the padding type.
+ */
+ public PaddedBufferedBlockCipher(
+ BlockCipher cipher,
+ BlockCipherPadding padding)
+ {
+ this.cipher = cipher;
+ this.padding = padding;
+
+ buf = new byte[cipher.getBlockSize()];
+ bufOff = 0;
+ }
+
+ /**
+ * Create a buffered block cipher PKCS7 padding
+ *
+ * @param cipher the underlying block cipher this buffering object wraps.
+ */
+ public PaddedBufferedBlockCipher(
+ BlockCipher cipher)
+ {
+ this(cipher, new PKCS7Padding());
+ }
+
+ /**
+ * initialise the cipher.
+ *
+ * @param forEncryption if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ this.forEncryption = forEncryption;
+
+ reset();
+
+ if (params instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom p = (ParametersWithRandom)params;
+
+ padding.init(p.getRandom());
+
+ cipher.init(forEncryption, p.getParameters());
+ }
+ else
+ {
+ padding.init(null);
+
+ cipher.init(forEncryption, params);
+ }
+ }
+
+ /**
+ * return the minimum size of the output buffer required for an update
+ * plus a doFinal with an input of len bytes.
+ *
+ * @param len the length of the input.
+ * @return the space required to accommodate a call to update and doFinal
+ * with len bytes of input.
+ */
+ public int getOutputSize(
+ int len)
+ {
+ int total = len + bufOff;
+ int leftOver = total % buf.length;
+
+ if (leftOver == 0)
+ {
+ if (forEncryption)
+ {
+ return total + buf.length;
+ }
+
+ return total;
+ }
+
+ return total - leftOver + buf.length;
+ }
+
+ /**
+ * return the size of the output buffer required for an update
+ * an input of len bytes.
+ *
+ * @param len the length of the input.
+ * @return the space required to accommodate a call to update
+ * with len bytes of input.
+ */
+ public int getUpdateOutputSize(
+ int len)
+ {
+ int total = len + bufOff;
+ int leftOver = total % buf.length;
+
+ if (leftOver == 0)
+ {
+ return total - buf.length;
+ }
+
+ return total - leftOver;
+ }
+
+ /**
+ * process a single byte, producing an output block if neccessary.
+ *
+ * @param in the input byte.
+ * @param out the space for any output that might be produced.
+ * @param outOff the offset from which the output will be copied.
+ * @return the number of output bytes copied to out.
+ * @exception DataLengthException if there isn't enough space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ */
+ public int processByte(
+ byte in,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ int resultLen = 0;
+
+ if (bufOff == buf.length)
+ {
+ resultLen = cipher.processBlock(buf, 0, out, outOff);
+ bufOff = 0;
+ }
+
+ buf[bufOff++] = in;
+
+ return resultLen;
+ }
+
+ /**
+ * process an array of bytes, producing output if necessary.
+ *
+ * @param in the input byte array.
+ * @param inOff the offset at which the input data starts.
+ * @param len the number of bytes to be copied out of the input array.
+ * @param out the space for any output that might be produced.
+ * @param outOff the offset from which the output will be copied.
+ * @return the number of output bytes copied to out.
+ * @exception DataLengthException if there isn't enough space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ */
+ public int processBytes(
+ byte[] in,
+ int inOff,
+ int len,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if (len < 0)
+ {
+ throw new IllegalArgumentException("Can't have a negative input length!");
+ }
+
+ int blockSize = getBlockSize();
+ int length = getUpdateOutputSize(len);
+
+ if (length > 0)
+ {
+ if ((outOff + length) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+ }
+
+ int resultLen = 0;
+ int gapLen = buf.length - bufOff;
+
+ if (len > gapLen)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, gapLen);
+
+ resultLen += cipher.processBlock(buf, 0, out, outOff);
+
+ bufOff = 0;
+ len -= gapLen;
+ inOff += gapLen;
+
+ while (len > buf.length)
+ {
+ resultLen += cipher.processBlock(in, inOff, out, outOff + resultLen);
+
+ len -= blockSize;
+ inOff += blockSize;
+ }
+ }
+
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+
+ return resultLen;
+ }
+
+ /**
+ * Process the last block in the buffer. If the buffer is currently
+ * full and padding needs to be added a call to doFinal will produce
+ * 2 * getBlockSize() bytes.
+ *
+ * @param out the array the block currently being held is copied into.
+ * @param outOff the offset at which the copying starts.
+ * @return the number of output bytes copied to out.
+ * @exception DataLengthException if there is insufficient space in out for
+ * the output or we are decrypting and the input is not block size aligned.
+ * @exception IllegalStateException if the underlying cipher is not
+ * initialised.
+ * @exception InvalidCipherTextException if padding is expected and not found.
+ */
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException, InvalidCipherTextException
+ {
+ int blockSize = cipher.getBlockSize();
+ int resultLen = 0;
+
+ if (forEncryption)
+ {
+ if (bufOff == blockSize)
+ {
+ if ((outOff + 2 * blockSize) > out.length)
+ {
+ reset();
+
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ resultLen = cipher.processBlock(buf, 0, out, outOff);
+ bufOff = 0;
+ }
+
+ padding.addPadding(buf, bufOff);
+
+ resultLen += cipher.processBlock(buf, 0, out, outOff + resultLen);
+
+ reset();
+ }
+ else
+ {
+ if (bufOff == blockSize)
+ {
+ resultLen = cipher.processBlock(buf, 0, buf, 0);
+ bufOff = 0;
+ }
+ else
+ {
+ reset();
+
+ throw new DataLengthException("last block incomplete in decryption");
+ }
+
+ try
+ {
+ resultLen -= padding.padCount(buf);
+
+ System.arraycopy(buf, 0, out, outOff, resultLen);
+ }
+ finally
+ {
+ reset();
+ }
+ }
+
+ return resultLen;
+ }
+}
diff --git a/core/src/main/java/org/bouncycastle/crypto/paddings/TBCPadding.java b/core/src/main/java/org/bouncycastle/crypto/paddings/TBCPadding.java
new file mode 100644
index 00000000..219912fe
--- /dev/null
+++ b/core/src/main/java/org/bouncycastle/crypto/paddings/TBCPadding.java
@@ -0,0 +1,89 @@
+package org.bouncycastle.crypto.paddings;
+
+import java.security.SecureRandom;
+
+import org.bouncycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A padder that adds Trailing-Bit-Compliment padding to a block.
+ * <p>
+ * This padding pads the block out with the compliment of the last bit
+ * of the plain text.
+ * </p>
+ */
+public class TBCPadding
+ implements BlockCipherPadding
+{
+ /**
+ * Initialise the padder.
+ *
+ * @param random - a SecureRandom if available.
+ */
+ public void init(SecureRandom random)
+ throws IllegalArgumentException
+ {
+ // nothing to do.
+ }
+
+ /**
+ * Return the name of the algorithm the padder implements.
+ *
+ * @return the name of the algorithm the padder implements.
+ */
+ public String getPaddingName()
+ {
+ return "TBC";
+ }
+
+ /**
+ * add the pad bytes to the passed in block, returning the
+ * number of bytes added.
+ * <p>
+ * Note: this assumes that the last block of plain text is always
+ * passed to it inside in. i.e. if inOff is zero, indicating the
+ * entire block is to be overwritten with padding the value of in
+ * should be the same as the last block of plain text.
+ * </p>
+ */
+ public int addPadding(
+ byte[] in,
+ int inOff)
+ {
+ int count = in.length - inOff;
+ byte code;
+
+ if (inOff > 0)
+ {
+ code = (byte)((in[inOff - 1] & 0x01) == 0 ? 0xff : 0x00);
+ }
+ else
+ {
+ code = (byte)((in[in.length - 1] & 0x01) == 0 ? 0xff : 0x00);
+ }
+
+ while (inOff < in.length)
+ {
+ in[inOff] = code;
+ inOff++;
+ }
+
+ return count;
+ }
+
+ /**
+ * return the number of pad bytes present in the block.
+ */
+ public int padCount(byte[] in)
+ throws InvalidCipherTextException
+ {
+ byte code = in[in.length - 1];
+
+ int index = in.length - 1;
+ while (index > 0 && in[index - 1] == code)
+ {
+ index--;
+ }
+
+ return in.length - index;
+ }
+}
diff --git a/core/src/main/java/org/bouncycastle/crypto/paddings/X923Padding.java b/core/src/main/java/org/bouncycastle/crypto/paddings/X923Padding.java
new file mode 100644
index 00000000..d4d34aad
--- /dev/null
+++ b/core/src/main/java/org/bouncycastle/crypto/paddings/X923Padding.java
@@ -0,0 +1,80 @@
+package org.bouncycastle.crypto.paddings;
+
+import java.security.SecureRandom;
+
+import org.bouncycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A padder that adds X9.23 padding to a block - if a SecureRandom is
+ * passed in random padding is assumed, otherwise padding with zeros is used.
+ */
+public class X923Padding
+ implements BlockCipherPadding
+{
+ SecureRandom random = null;
+
+ /**
+ * Initialise the padder.
+ *
+ * @param random a SecureRandom if one is available.
+ */
+ public void init(SecureRandom random)
+ throws IllegalArgumentException
+ {
+ this.random = random;
+ }
+
+ /**
+ * Return the name of the algorithm the padder implements.
+ *
+ * @return the name of the algorithm the padder implements.
+ */
+ public String getPaddingName()
+ {
+ return "X9.23";
+ }
+
+ /**
+ * add the pad bytes to the passed in block, returning the
+ * number of bytes added.
+ */
+ public int addPadding(
+ byte[] in,
+ int inOff)
+ {
+ byte code = (byte)(in.length - inOff);
+
+ while (inOff < in.length - 1)
+ {
+ if (random == null)
+ {
+ in[inOff] = 0;
+ }
+ else
+ {
+ in[inOff] = (byte)random.nextInt();
+ }
+ inOff++;
+ }
+
+ in[inOff] = code;
+
+ return code;
+ }
+
+ /**
+ * return the number of pad bytes present in the block.
+ */
+ public int padCount(byte[] in)
+ throws InvalidCipherTextException
+ {
+ int count = in[in.length - 1] & 0xff;
+
+ if (count > in.length)
+ {
+ throw new InvalidCipherTextException("pad block corrupted");
+ }
+
+ return count;
+ }
+}
diff --git a/core/src/main/java/org/bouncycastle/crypto/paddings/ZeroBytePadding.java b/core/src/main/java/org/bouncycastle/crypto/paddings/ZeroBytePadding.java
new file mode 100644
index 00000000..c7560286
--- /dev/null
+++ b/core/src/main/java/org/bouncycastle/crypto/paddings/ZeroBytePadding.java
@@ -0,0 +1,73 @@
+package org.bouncycastle.crypto.paddings;
+
+import java.security.SecureRandom;
+
+import org.bouncycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A padder that adds NULL byte padding to a block.
+ */
+public class ZeroBytePadding
+ implements BlockCipherPadding
+{
+ /**
+ * Initialise the padder.
+ *
+ * @param random - a SecureRandom if available.
+ */
+ public void init(SecureRandom random)
+ throws IllegalArgumentException
+ {
+ // nothing to do.
+ }
+
+ /**
+ * Return the name of the algorithm the padder implements.
+ *
+ * @return the name of the algorithm the padder implements.
+ */
+ public String getPaddingName()
+ {
+ return "ZeroByte";
+ }
+
+ /**
+ * add the pad bytes to the passed in block, returning the
+ * number of bytes added.
+ */
+ public int addPadding(
+ byte[] in,
+ int inOff)
+ {
+ int added = (in.length - inOff);
+
+ while (inOff < in.length)
+ {
+ in[inOff] = (byte) 0;
+ inOff++;
+ }
+
+ return added;
+ }
+
+ /**
+ * return the number of pad bytes present in the block.
+ */
+ public int padCount(byte[] in)
+ throws InvalidCipherTextException
+ {
+ int count = in.length;
+
+ while (count > 0)
+ {
+ if (in[count - 1] != 0)
+ {
+ break;
+ }
+
+ count--;
+ }
+
+ return in.length - count;
+ }
+}