bc-java
bc-java copied to clipboard
Elephant cipher fails decrypt on large messages
The lightweight Elephant Cipher fails when processing large messages where the message is larger than the BlockSize. The decryption fails with error Mac does not match.
It should also be noted that the doFinal() call incorrectly returns the full message outputLength rather than the actual dataLength (ie the macLength) output by the call.
Sample code to produce the error is below
` /** * Data length. */ private static final int DATALEN = 40;
/**
* AEAD length.
*/
private static final int AEADLEN = 10;
/**
* Main.
* @params pArgs the arguments
*/
public static void main(final String[] pArgs) {
checkCipher(new ElephantEngine(ElephantParameters.elephant160));
}
/**
* Check cipher.
* @param pCipher the cipher
*/
private static void checkCipher(final AEADCipher pCipher) {
try {
/* Obtain some random data */
final byte[] myData = new byte[DATALEN];
final SecureRandom myRandom = new SecureRandom();
myRandom.nextBytes(myData);
/* Obtain some random AEAD */
final byte[] myAEAD = new byte[AEADLEN];
myRandom.nextBytes(myAEAD);
/* Create the Key parameters */
final CipherKeyGenerator myGenerator = new CipherKeyGenerator();
final KeyGenerationParameters myGenParams = new KeyGenerationParameters(myRandom, 128);
myGenerator.init(myGenParams);
final byte[] myKey = myGenerator.generateKey();
final KeyParameter myKeyParams = new KeyParameter(myKey);
/* Create the nonce */
final byte[] myNonce = new byte[12];
myRandom.nextBytes(myNonce);
final ParametersWithIV myParams = new ParametersWithIV(myKeyParams, myNonce);
/* Initialise the cipher for encryption */
pCipher.init(true, myParams);
final int myMaxOutLen = pCipher.getOutputSize(DATALEN);
final byte[] myEncrypted = new byte[myMaxOutLen];
pCipher.processAADBytes(myAEAD, 0, AEADLEN);
int myOutLen = pCipher.processBytes(myData, 0, DATALEN, myEncrypted, 0);
myOutLen += pCipher.doFinal(myEncrypted, myOutLen);
/* Note that myOutLen is too large by DATALEN */
/* Initialise the cipher for decryption */
pCipher.init(false, myParams);
final int myMaxClearLen = pCipher.getOutputSize(myOutLen);
final byte[] myDecrypted = new byte[myMaxClearLen];
pCipher2.processAADBytes(myAEAD, 0, AEADLEN);
int myClearLen = pCipher2.processBytes(myEncrypted, 0, myEncrypted.length, myDecrypted, 0);
myClearLen += pCipher2.doFinal(myDecrypted, myClearLen);
final byte[] myResult = Arrays.copyOf(myDecrypted, DATALEN);
/* Check that we have the same result */
if (!Arrays.equals(myData, myResult)) {
System.out.println("Cipher " + pCipher.getAlgorithmName() + " failed");
}
} catch (InvalidCipherTextException e) {
throw new RuntimeException(e);
}
}
`