Skip to content

Commit

Permalink
Fix the bug if block size of base in GCFBBlockCipher is not equal to 8.
Browse files Browse the repository at this point in the history
  • Loading branch information
gefeili committed Jan 2, 2025
1 parent 2c9faf6 commit e6fc301
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ public class GCFBBlockCipher
private ParametersWithIV initParams;

private KeyParameter key;
private long counter = 0;
private boolean forEncryption;
private long counter = 0;
private boolean forEncryption;

public GCFBBlockCipher(BlockCipher engine)
{
Expand All @@ -43,13 +43,13 @@ public void init(boolean forEncryption, CipherParameters params)
{
counter = 0;
cfbEngine.init(forEncryption, params);
byte[] iv = null;
byte[] iv = null;

this.forEncryption = forEncryption;

if (params instanceof ParametersWithIV)
{
ParametersWithIV ivParams = (ParametersWithIV) params;
ParametersWithIV ivParams = (ParametersWithIV)params;
params = ivParams.getParameters();
iv = ivParams.getIV();
}
Expand All @@ -65,14 +65,14 @@ public void init(boolean forEncryption, CipherParameters params)
}

key = (KeyParameter)params;
/* Pick up key/IV from parameters or most recent parameters */
if (key == null && initParams != null)
{
key = (KeyParameter) initParams.getParameters();

/* Pick up key/IV from parameters or most recent parameters */
if (key == null && initParams != null)
{
key = (KeyParameter)initParams.getParameters();
}
if (iv == null && initParams != null)
{
{
iv = initParams.getIV();
}
else
Expand Down Expand Up @@ -105,18 +105,20 @@ public int processBlock(byte[] in, int inOff, byte[] out, int outOff)

protected byte calculateByte(byte b)
{
if (counter > 0 && counter % 1024 == 0)
if (counter > 0 && (counter & 1023) == 0)
{
BlockCipher base = cfbEngine.getUnderlyingCipher();
BlockCipher base = cfbEngine.getUnderlyingCipher();

base.init(false, key);

byte[] nextKey = new byte[32];

base.processBlock(C, 0, nextKey, 0);
base.processBlock(C, 8, nextKey, 8);
base.processBlock(C, 16, nextKey, 16);
base.processBlock(C, 24, nextKey, 24);
int blockSize = base.getBlockSize();
//TODO: The for-loop will not function correctly if 32 is not evenly divisible by blocksize
// (i.e., 32 % blocksize != 0), So it's not working for DSTU7624Engine(512), RijndaelEngine(except 256), etc.
for (int i = 0; i < nextKey.length; i += blockSize)
{
base.processBlock(C, i, nextKey, i);
}

key = new KeyParameter(nextKey);

Expand All @@ -137,13 +139,13 @@ protected byte calculateByte(byte b)
public void reset()
{
counter = 0;
if (initParams != null)
{
key = (KeyParameter) initParams.getParameters();
if (initParams != null)
{
key = (KeyParameter)initParams.getParameters();
cfbEngine.init(forEncryption, initParams);
}
else
{
}
else
{
cfbEngine.reset();
}
}
Expand Down
51 changes: 51 additions & 0 deletions core/src/test/java/org/bouncycastle/crypto/test/CipherTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
import java.security.SecureRandom;

import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.CipherKeyGenerator;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.DefaultBufferedBlockCipher;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.KeyGenerationParameters;
import org.bouncycastle.crypto.modes.AEADCipher;
Expand All @@ -14,6 +16,7 @@
import org.bouncycastle.util.test.SimpleTest;
import org.bouncycastle.util.test.SimpleTestResult;
import org.bouncycastle.util.test.TestFailedException;
import org.junit.Assert;

public abstract class CipherTest
extends SimpleTest
Expand Down Expand Up @@ -251,4 +254,52 @@ static void isEqualTo(
throw new TestFailedException(SimpleTestResult.failed(parent, "no message"));
}
}

static void checkCipher(final BlockCipher pCipher, final int datalen)
throws Exception
{
final SecureRandom random = new SecureRandom();
/* Create the data */
final byte[] myData = new byte[datalen];
random.nextBytes(myData);

/* Create the Key parameters */
final CipherKeyGenerator myGenerator = new CipherKeyGenerator();
final KeyGenerationParameters myGenParams = new KeyGenerationParameters(random, 256);
myGenerator.init(myGenParams);
final byte[] myKey = myGenerator.generateKey();
final KeyParameter myKeyParams = new KeyParameter(myKey);

/* Create the IV */
final byte[] myIV = new byte[16];
random.nextBytes(myIV);

/* Create the initParams */
final ParametersWithIV myParams = new ParametersWithIV(myKeyParams, myIV);

/* Wrap Block Cipher with buffered BlockCipher */
final BufferedBlockCipher myCipher = new DefaultBufferedBlockCipher(pCipher);

/* Initialise the cipher for encryption */
myCipher.init(true, myParams);

/* Encipher the text */
final byte[] myOutput = new byte[myCipher.getOutputSize(datalen)];
int myOutLen = myCipher.processBytes(myData, 0, datalen, myOutput, 0);
myCipher.doFinal(myOutput, myOutLen);

/* Re-Encipher the text (after implicit reset) */
final byte[] myOutput2 = new byte[myCipher.getOutputSize(datalen)];
myOutLen = myCipher.processBytes(myData, 0, datalen, myOutput2, 0);
myCipher.doFinal(myOutput2, myOutLen);

myCipher.init(false, myParams);
final byte[] plaintext = new byte[myCipher.getOutputSize(myOutput.length)];
myOutLen = myCipher.processBytes(myOutput2, 0, datalen, plaintext, 0);
myCipher.doFinal(plaintext, myOutLen);

/* Check that the cipherTexts are identical */
Assert.assertArrayEquals(myOutput, myOutput2);
Assert.assertArrayEquals(myData, plaintext);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.digests.GOST3411Digest;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.engines.GOST28147Engine;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.modes.CFBBlockCipher;
import org.bouncycastle.crypto.modes.GCFBBlockCipher;
import org.bouncycastle.crypto.modes.GOFBBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
Expand Down Expand Up @@ -197,7 +199,8 @@ public void performTest()
throws Exception
{
super.performTest();

checkCipher(new GCFBBlockCipher(new GOST28147Engine()), 2049);
checkCipher(new GCFBBlockCipher(AESEngine.newInstance()), 2049);
//advanced tests with GOST28147KeyGenerator:
//encrypt on hesh message; ECB mode:
byte[] in = Hex.decode("4e6f77206973207468652074696d6520666f7220616c6c20");
Expand Down

0 comments on commit e6fc301

Please sign in to comment.