BufferedBlockCipherpublic class BufferedBlockCipher extends Object A wrapper class that allows block ciphers to be used to process data in
a piecemeal fashion. The BufferedBlockCipher outputs a block only when the
buffer is full and more data is being added, or on a doFinal.
Note: in the case where the underlying cipher is either a CFB cipher or an
OFB one the last block may not be a multiple of the block size. |
Fields Summary |
---|
protected byte[] | buf | protected int | bufOff | protected boolean | forEncryption | protected BlockCipher | cipher | protected boolean | partialBlockOkay | protected boolean | pgpCFB |
Constructors Summary |
---|
protected BufferedBlockCipher()constructor for subclasses
| public BufferedBlockCipher(BlockCipher cipher)Create a buffered block cipher without padding.
this.cipher = cipher;
buf = new byte[cipher.getBlockSize()];
bufOff = 0;
//
// check if we can handle partial blocks on doFinal.
//
String name = cipher.getAlgorithmName();
int idx = name.indexOf('/") + 1;
pgpCFB = (idx > 0 && name.startsWith("PGP", idx));
if (pgpCFB)
{
partialBlockOkay = true;
}
else
{
partialBlockOkay = (idx > 0 && (name.startsWith("CFB", idx) || name.startsWith("OFB", idx) || name.startsWith("OpenPGP", idx) || name.startsWith("SIC", idx) || name.startsWith("GCTR", idx)));
}
|
Methods Summary |
---|
public int | doFinal(byte[] out, int outOff)Process the last block in the buffer.
int resultLen = 0;
if (outOff + bufOff > out.length)
{
throw new DataLengthException("output buffer too short for doFinal()");
}
if (bufOff != 0 && partialBlockOkay)
{
cipher.processBlock(buf, 0, buf, 0);
resultLen = bufOff;
bufOff = 0;
System.arraycopy(buf, 0, out, outOff, resultLen);
}
else if (bufOff != 0)
{
throw new DataLengthException("data not block size aligned");
}
reset();
return resultLen;
| public int | getBlockSize()return the blocksize for the underlying cipher.
return cipher.getBlockSize();
| public int | getOutputSize(int len)return the size of the output buffer required for an update plus a
doFinal with an input of len bytes.
int total = len + bufOff;
int leftOver;
if (pgpCFB)
{
leftOver = total % buf.length - (cipher.getBlockSize() + 2);
}
else
{
leftOver = total % buf.length;
if (leftOver == 0)
{
return total;
}
}
return total - leftOver + buf.length;
| public BlockCipher | getUnderlyingCipher()return the cipher this object wraps.
return cipher;
| public int | getUpdateOutputSize(int len)return the size of the output buffer required for an update
an input of len bytes.
int total = len + bufOff;
int leftOver;
if (pgpCFB)
{
leftOver = total % buf.length - (cipher.getBlockSize() + 2);
}
else
{
leftOver = total % buf.length;
}
return total - leftOver;
| public void | init(boolean forEncryption, CipherParameters params)initialise the cipher.
this.forEncryption = forEncryption;
reset();
cipher.init(forEncryption, params);
| public int | processByte(byte in, byte[] out, int outOff)process a single byte, producing an output block if neccessary.
int resultLen = 0;
buf[bufOff++] = in;
if (bufOff == buf.length)
{
resultLen = cipher.processBlock(buf, 0, out, outOff);
bufOff = 0;
}
return resultLen;
| public int | processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)process an array of bytes, producing output if necessary.
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 DataLengthException("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;
if (bufOff == buf.length)
{
resultLen += cipher.processBlock(buf, 0, out, outOff + resultLen);
bufOff = 0;
}
return resultLen;
| public void | reset()Reset the buffer and cipher. After resetting the object is in the same
state as it was after the last init (if there was one).
//
// clean the buffer.
//
for (int i = 0; i < buf.length; i++)
{
buf[i] = 0;
}
bufOff = 0;
//
// reset the underlying cipher.
//
cipher.reset();
|
|