Skip to content

Commit b4fbdac

Browse files
committed
Merge branch '1953-gcfb-large-data' into 'main'
1953 gcfb large data See merge request root/bc-java!63
2 parents 3b0be50 + 9412f85 commit b4fbdac

File tree

3 files changed

+97
-12
lines changed

3 files changed

+97
-12
lines changed

core/src/main/java/org/bouncycastle/crypto/modes/GCFBBlockCipher.java

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,16 @@ public class GCFBBlockCipher
2525

2626
private final CFBBlockCipher cfbEngine;
2727

28+
private ParametersWithIV initParams;
29+
2830
private KeyParameter key;
29-
private long counter = 0;
30-
private boolean forEncryption;
31+
private long counter = 0;
32+
private boolean forEncryption;
3133

3234
public GCFBBlockCipher(BlockCipher engine)
3335
{
3436
super(engine);
35-
37+
//TODO: Ensure the key size of the engine is 32 bits
3638
this.cfbEngine = new CFBBlockCipher(engine, engine.getBlockSize() * 8);
3739
}
3840

@@ -41,12 +43,15 @@ public void init(boolean forEncryption, CipherParameters params)
4143
{
4244
counter = 0;
4345
cfbEngine.init(forEncryption, params);
46+
byte[] iv = null;
4447

4548
this.forEncryption = forEncryption;
4649

4750
if (params instanceof ParametersWithIV)
4851
{
49-
params = ((ParametersWithIV)params).getParameters();
52+
ParametersWithIV ivParams = (ParametersWithIV)params;
53+
params = ivParams.getParameters();
54+
iv = ivParams.getIV();
5055
}
5156

5257
if (params instanceof ParametersWithRandom)
@@ -60,6 +65,23 @@ public void init(boolean forEncryption, CipherParameters params)
6065
}
6166

6267
key = (KeyParameter)params;
68+
69+
/* Pick up key/IV from parameters or most recent parameters */
70+
if (key == null && initParams != null)
71+
{
72+
key = (KeyParameter)initParams.getParameters();
73+
}
74+
if (iv == null && initParams != null)
75+
{
76+
iv = initParams.getIV();
77+
}
78+
else
79+
{
80+
iv = cfbEngine.getCurrentIV();
81+
}
82+
83+
/* Save the initParameters */
84+
initParams = new ParametersWithIV(key, iv);
6385
}
6486

6587
public String getAlgorithmName()
@@ -83,18 +105,19 @@ public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
83105

84106
protected byte calculateByte(byte b)
85107
{
86-
if (counter > 0 && counter % 1024 == 0)
108+
if (counter > 0 && (counter & 1023) == 0)
87109
{
88-
BlockCipher base = cfbEngine.getUnderlyingCipher();
110+
BlockCipher base = cfbEngine.getUnderlyingCipher();
89111

90112
base.init(false, key);
91113

92114
byte[] nextKey = new byte[32];
115+
int blockSize = base.getBlockSize();
93116

94-
base.processBlock(C, 0, nextKey, 0);
95-
base.processBlock(C, 8, nextKey, 8);
96-
base.processBlock(C, 16, nextKey, 16);
97-
base.processBlock(C, 24, nextKey, 24);
117+
for (int i = 0; i < nextKey.length; i += blockSize)
118+
{
119+
base.processBlock(C, i, nextKey, i);
120+
}
98121

99122
key = new KeyParameter(nextKey);
100123

@@ -115,6 +138,14 @@ protected byte calculateByte(byte b)
115138
public void reset()
116139
{
117140
counter = 0;
118-
cfbEngine.reset();
141+
if (initParams != null)
142+
{
143+
key = (KeyParameter)initParams.getParameters();
144+
cfbEngine.init(forEncryption, initParams);
145+
}
146+
else
147+
{
148+
cfbEngine.reset();
149+
}
119150
}
120151
}

core/src/test/java/org/bouncycastle/crypto/test/CipherTest.java

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
import java.security.SecureRandom;
44

55
import org.bouncycastle.crypto.BlockCipher;
6+
import org.bouncycastle.crypto.BufferedBlockCipher;
67
import org.bouncycastle.crypto.CipherKeyGenerator;
78
import org.bouncycastle.crypto.DataLengthException;
9+
import org.bouncycastle.crypto.DefaultBufferedBlockCipher;
810
import org.bouncycastle.crypto.InvalidCipherTextException;
911
import org.bouncycastle.crypto.KeyGenerationParameters;
1012
import org.bouncycastle.crypto.modes.AEADCipher;
@@ -14,6 +16,7 @@
1416
import org.bouncycastle.util.test.SimpleTest;
1517
import org.bouncycastle.util.test.SimpleTestResult;
1618
import org.bouncycastle.util.test.TestFailedException;
19+
import org.junit.Assert;
1720

1821
public abstract class CipherTest
1922
extends SimpleTest
@@ -251,4 +254,52 @@ static void isEqualTo(
251254
throw new TestFailedException(SimpleTestResult.failed(parent, "no message"));
252255
}
253256
}
257+
258+
static void checkCipher(final BlockCipher pCipher, final int datalen)
259+
throws Exception
260+
{
261+
final SecureRandom random = new SecureRandom();
262+
/* Create the data */
263+
final byte[] myData = new byte[datalen];
264+
random.nextBytes(myData);
265+
266+
/* Create the Key parameters */
267+
final CipherKeyGenerator myGenerator = new CipherKeyGenerator();
268+
final KeyGenerationParameters myGenParams = new KeyGenerationParameters(random, 256);
269+
myGenerator.init(myGenParams);
270+
final byte[] myKey = myGenerator.generateKey();
271+
final KeyParameter myKeyParams = new KeyParameter(myKey);
272+
273+
/* Create the IV */
274+
final byte[] myIV = new byte[16];
275+
random.nextBytes(myIV);
276+
277+
/* Create the initParams */
278+
final ParametersWithIV myParams = new ParametersWithIV(myKeyParams, myIV);
279+
280+
/* Wrap Block Cipher with buffered BlockCipher */
281+
final BufferedBlockCipher myCipher = new DefaultBufferedBlockCipher(pCipher);
282+
283+
/* Initialise the cipher for encryption */
284+
myCipher.init(true, myParams);
285+
286+
/* Encipher the text */
287+
final byte[] myOutput = new byte[myCipher.getOutputSize(datalen)];
288+
int myOutLen = myCipher.processBytes(myData, 0, datalen, myOutput, 0);
289+
myCipher.doFinal(myOutput, myOutLen);
290+
291+
/* Re-Encipher the text (after implicit reset) */
292+
final byte[] myOutput2 = new byte[myCipher.getOutputSize(datalen)];
293+
myOutLen = myCipher.processBytes(myData, 0, datalen, myOutput2, 0);
294+
myCipher.doFinal(myOutput2, myOutLen);
295+
296+
myCipher.init(false, myParams);
297+
final byte[] plaintext = new byte[myCipher.getOutputSize(myOutput.length)];
298+
myOutLen = myCipher.processBytes(myOutput2, 0, datalen, plaintext, 0);
299+
myCipher.doFinal(plaintext, myOutLen);
300+
301+
/* Check that the cipherTexts are identical */
302+
Assert.assertArrayEquals(myOutput, myOutput2);
303+
Assert.assertArrayEquals(myData, plaintext);
304+
}
254305
}

core/src/test/java/org/bouncycastle/crypto/test/GOST28147Test.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
import org.bouncycastle.crypto.CipherParameters;
55
import org.bouncycastle.crypto.CryptoException;
66
import org.bouncycastle.crypto.digests.GOST3411Digest;
7+
import org.bouncycastle.crypto.engines.AESEngine;
78
import org.bouncycastle.crypto.engines.GOST28147Engine;
89
import org.bouncycastle.crypto.modes.CBCBlockCipher;
910
import org.bouncycastle.crypto.modes.CFBBlockCipher;
11+
import org.bouncycastle.crypto.modes.GCFBBlockCipher;
1012
import org.bouncycastle.crypto.modes.GOFBBlockCipher;
1113
import org.bouncycastle.crypto.params.KeyParameter;
1214
import org.bouncycastle.crypto.params.ParametersWithIV;
@@ -197,7 +199,8 @@ public void performTest()
197199
throws Exception
198200
{
199201
super.performTest();
200-
202+
checkCipher(new GCFBBlockCipher(new GOST28147Engine()), 2049);
203+
checkCipher(new GCFBBlockCipher(AESEngine.newInstance()), 2049);
201204
//advanced tests with GOST28147KeyGenerator:
202205
//encrypt on hesh message; ECB mode:
203206
byte[] in = Hex.decode("4e6f77206973207468652074696d6520666f7220616c6c20");

0 commit comments

Comments
 (0)