OpenPGPCFBBlockCipherpublic class OpenPGPCFBBlockCipher extends Object implements org.bouncycastle.crypto.BlockCipherImplements OpenPGP's rather strange version of Cipher-FeedBack (CFB) mode
on top of a simple cipher. This class assumes the IV has been prepended
to the data stream already, and just accomodates the reset after
(blockSize + 2) bytes have been read.
For further info see RFC 2440. |
Fields Summary |
---|
private byte[] | IV | private byte[] | FR | private byte[] | FRE | private byte[] | tmp | private org.bouncycastle.crypto.BlockCipher | cipher | private int | count | private int | blockSize | private boolean | forEncryption |
Constructors Summary |
---|
public OpenPGPCFBBlockCipher(org.bouncycastle.crypto.BlockCipher cipher)Basic constructor.
this.cipher = cipher;
this.blockSize = cipher.getBlockSize();
this.IV = new byte[blockSize];
this.FR = new byte[blockSize];
this.FRE = new byte[blockSize];
this.tmp = new byte[blockSize];
|
Methods Summary |
---|
private int | decryptBlock(byte[] in, int inOff, byte[] out, int outOff)Do the appropriate processing for CFB IV mode decryption.
if ((inOff + blockSize) > in.length)
{
throw new DataLengthException("input buffer too short");
}
if ((outOff + blockSize) > out.length)
{
throw new DataLengthException("output buffer too short");
}
if (count > blockSize)
{
// copy in buffer so that this mode works if in and out are the same
System.arraycopy(in, inOff, tmp, 0, blockSize);
out[outOff + 0] = encryptByte(tmp[0], blockSize - 2);
out[outOff + 1] = encryptByte(tmp[1], blockSize - 1);
System.arraycopy(tmp, 0, FR, blockSize - 2, 2);
cipher.processBlock(FR, 0, FRE, 0);
for (int n = 2; n < blockSize; n++)
{
out[outOff + n] = encryptByte(tmp[n], n - 2);
}
System.arraycopy(tmp, 2, FR, 0, blockSize - 2);
}
else if (count == 0)
{
cipher.processBlock(FR, 0, FRE, 0);
for (int n = 0; n < blockSize; n++)
{
FR[n] = in[inOff + n];
out[n] = encryptByte(in[inOff + n], n);
}
count += blockSize;
}
else if (count == blockSize)
{
System.arraycopy(in, inOff, tmp, 0, blockSize);
cipher.processBlock(FR, 0, FRE, 0);
out[outOff + 0] = encryptByte(tmp[0], 0);
out[outOff + 1] = encryptByte(tmp[1], 1);
System.arraycopy(FR, 2, FR, 0, blockSize - 2);
FR[blockSize - 2] = tmp[0];
FR[blockSize - 1] = tmp[1];
cipher.processBlock(FR, 0, FRE, 0);
for (int n = 2; n < blockSize; n++)
{
FR[n - 2] = in[inOff + n];
out[outOff + n] = encryptByte(in[inOff + n], n - 2);
}
count += blockSize;;
}
return blockSize;
| private int | encryptBlock(byte[] in, int inOff, byte[] out, int outOff)Do the appropriate processing for CFB IV mode encryption.
if ((inOff + blockSize) > in.length)
{
throw new DataLengthException("input buffer too short");
}
if ((outOff + blockSize) > out.length)
{
throw new DataLengthException("output buffer too short");
}
if (count > blockSize)
{
FR[blockSize - 2] = out[outOff] = encryptByte(in[inOff], blockSize - 2);
FR[blockSize - 1] = out[outOff + 1] = encryptByte(in[inOff + 1], blockSize - 1);
cipher.processBlock(FR, 0, FRE, 0);
for (int n = 2; n < blockSize; n++)
{
out[outOff + n] = encryptByte(in[inOff + n], n - 2);
}
System.arraycopy(out, outOff + 2, FR, 0, blockSize - 2);
}
else if (count == 0)
{
cipher.processBlock(FR, 0, FRE, 0);
for (int n = 0; n < blockSize; n++)
{
out[outOff + n] = encryptByte(in[inOff + n], n);
}
System.arraycopy(out, outOff, FR, 0, blockSize);
count += blockSize;
}
else if (count == blockSize)
{
cipher.processBlock(FR, 0, FRE, 0);
out[outOff] = encryptByte(in[inOff], 0);
out[outOff + 1] = encryptByte(in[inOff + 1], 1);
//
// do reset
//
System.arraycopy(FR, 2, FR, 0, blockSize - 2);
System.arraycopy(out, outOff, FR, blockSize - 2, 2);
cipher.processBlock(FR, 0, FRE, 0);
for (int n = 2; n < blockSize; n++)
{
out[outOff + n] = encryptByte(in[inOff + n], n - 2);
}
System.arraycopy(out, outOff + 2, FR, 0, blockSize - 2);
count += blockSize;
}
return blockSize;
| private byte | encryptByte(byte data, int blockOff)Encrypt one byte of data according to CFB mode.
return (byte)(FRE[blockOff] ^ data);
| public java.lang.String | getAlgorithmName()return the algorithm name and mode.
return cipher.getAlgorithmName() + "/OpenPGPCFB";
| public int | getBlockSize()return the block size we are operating at.
return cipher.getBlockSize();
| public org.bouncycastle.crypto.BlockCipher | getUnderlyingCipher()return the underlying block cipher that we are wrapping.
return cipher;
| public void | init(boolean forEncryption, org.bouncycastle.crypto.CipherParameters params)Initialise the cipher and, possibly, the initialisation vector (IV).
If an IV isn't passed as part of the parameter, the IV will be all zeros.
An IV which is too short is handled in FIPS compliant fashion.
this.forEncryption = forEncryption;
reset();
cipher.init(true, params);
| public int | processBlock(byte[] in, int inOff, byte[] out, int outOff)Process one block of input from the array in and write it to
the out array.
return (forEncryption) ? encryptBlock(in, inOff, out, outOff) : decryptBlock(in, inOff, out, outOff);
| public void | reset()reset the chaining vector back to the IV and reset the underlying
cipher.
count = 0;
for (int i = 0; i != FR.length; i++)
{
FR[i] = IV[i];
}
cipher.reset();
|
|