PGPCFBBlockCipherpublic class PGPCFBBlockCipher extends Object implements org.bouncycastle.crypto.BlockCipherImplements OpenPGP's rather strange version of Cipher-FeedBack (CFB) mode on top of a simple cipher. 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 | private boolean | inlineIv |
Constructors Summary |
---|
public PGPCFBBlockCipher(org.bouncycastle.crypto.BlockCipher cipher, boolean inlineIv)Basic constructor.
this.cipher = cipher;
this.inlineIv = inlineIv;
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 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");
}
cipher.processBlock(FR, 0, FRE, 0);
for (int n = 0; n < blockSize; n++)
out[outOff + n] = encryptByte(in[inOff + n], n);
for (int n = 0; n < blockSize; n++)
FR[n] = in[inOff + n];
return blockSize;
| private int | decryptBlockWithIV(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 == 0)
{
for (int n = 0; n < blockSize; n++)
{
FR[n] = in[inOff + n];
}
cipher.processBlock(FR, 0, FRE, 0);
count += blockSize;
return 0;
}
else 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);
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 = 0; n < blockSize - 2; n++)
{
out[outOff + n] = encryptByte(tmp[n + 2], n);
}
System.arraycopy(tmp, 2, FR, 0, blockSize - 2);
count += 2;
return blockSize - 2;
}
else if (count >= blockSize + 2)
{
// 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 = 0; n < blockSize - 2; n++)
{
out[outOff + n + 2] = encryptByte(tmp[n + 2], n);
}
System.arraycopy(tmp, 2, FR, 0, blockSize - 2);
}
return blockSize;
| private int | encryptBlock(byte[] in, int inOff, byte[] out, int outOff)Do the appropriate processing for CFB 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");
}
cipher.processBlock(FR, 0, FRE, 0);
for (int n = 0; n < blockSize; n++)
out[outOff + n] = encryptByte(in[inOff + n], n);
for (int n = 0; n < blockSize; n++)
FR[n] = out[outOff + n];
return blockSize;
| private int | encryptBlockWithIV(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 == 0)
{
cipher.processBlock(FR, 0, FRE, 0);
for (int n = 0; n < blockSize; n++)
{
out[outOff + n] = encryptByte(IV[n], n);
}
System.arraycopy(out, outOff, FR, 0, blockSize);
cipher.processBlock(FR, 0, FRE, 0);
out[outOff + blockSize] = encryptByte(IV[blockSize - 2], 0);
out[outOff + blockSize + 1] = encryptByte(IV[blockSize - 1], 1);
System.arraycopy(out, outOff + 2, FR, 0, blockSize);
cipher.processBlock(FR, 0, FRE, 0);
for (int n = 0; n < blockSize; n++)
{
out[outOff + blockSize + 2 + n] = encryptByte(in[inOff + n], n);
}
System.arraycopy(out, outOff + blockSize + 2, FR, 0, blockSize);
count += 2 * blockSize + 2;
return 2 * blockSize + 2;
}
else if (count >= blockSize + 2)
{
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);
}
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.
if (inlineIv)
{
return cipher.getAlgorithmName() + "/PGPCFBwithIV";
}
else
{
return cipher.getAlgorithmName() + "/PGPCFB";
}
| 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;
if (params instanceof ParametersWithIV)
{
ParametersWithIV ivParam = (ParametersWithIV)params;
byte[] iv = ivParam.getIV();
if (iv.length < IV.length)
{
// prepend the supplied IV with zeros (per FIPS PUB 81)
System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length);
for (int i = 0; i < IV.length - iv.length; i++)
{
IV[i] = 0;
}
}
else
{
System.arraycopy(iv, 0, IV, 0, IV.length);
}
reset();
cipher.init(true, ivParam.getParameters());
}
else
{
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.
if (inlineIv)
{
return (forEncryption) ? encryptBlockWithIV(in, inOff, out, outOff) : decryptBlockWithIV(in, inOff, out, outOff);
}
else
{
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++)
{
if (inlineIv)
FR[i] = 0;
else
FR[i] = IV[i]; // if simple mode, key is IV (even if this is zero)
}
cipher.reset();
|
|