long seed = mt.nextLong();
if (TEST_JCA) {
SecretKeySpec k = new SecretKeySpec(key, "AES");
Cipher c = Cipher.getInstance("AES/CTR/NOPADDING", Rijndael.AesCtrProvider);
c.init(Cipher.ENCRYPT_MODE, k, new IvParameterSpec(iv));
MersenneTwister random = new MersenneTwister(seed);
byte[] output = new byte[plaintext.length];
int inputPtr = 0;
int outputPtr = 0;
// Odd API designed for block ciphers etc.
// For CTR it should be able to return immediately each time.
// ... Actually, no. BouncyCastle's CTR breaks this assumption.
// You must handle when update() produce less than was in input.
while (inputPtr < plaintext.length) {
int max = plaintext.length - inputPtr;
int count = (max == 1) ? 1 : (random.nextInt(max - 1) + 1);
int moved = c.update(plaintext, inputPtr, count, output,
outputPtr);
outputPtr += moved;
inputPtr += count;
}
c.doFinal(plaintext, 0, plaintext.length - inputPtr, output,
outputPtr);
assertTrue(Arrays.equals(output, ciphertext));
}
Rijndael cipher = new Rijndael(bits, 128);
cipher.initialize(key);
CTRBlockCipher ctr = new CTRBlockCipher(cipher);
ctr.init(iv);
byte[] output = new byte[plaintext.length];
MersenneTwister random = new MersenneTwister(seed);
int ptr = 0;
while (ptr < plaintext.length) {
int max = plaintext.length - ptr;
int count = (max == 1) ? 1 : (random.nextInt(max - 1) + 1);
ctr.processBytes(plaintext, ptr, count, output, ptr);
ptr += count;
}
assertTrue(Arrays.equals(output, ciphertext));
}