package org.bouncycastle.crypto.test;
import java.security.SecureRandom;
import org.bouncycastle.crypto.engines.DESEngine;
import org.bouncycastle.crypto.paddings.BlockCipherPadding;
import org.bouncycastle.crypto.paddings.ISO10126d2Padding;
import org.bouncycastle.crypto.paddings.ISO7816d4Padding;
import org.bouncycastle.crypto.paddings.PKCS7Padding;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.paddings.TBCPadding;
import org.bouncycastle.crypto.paddings.X923Padding;
import org.bouncycastle.crypto.paddings.ZeroBytePadding;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.util.encoders.Hex;
import org.bouncycastle.util.test.SimpleTest;
public class PaddingTest
extends SimpleTest
{
public PaddingTest()
{
}
private void blockCheck(
PaddedBufferedBlockCipher cipher,
BlockCipherPadding padding,
KeyParameter key,
byte[] data)
{
byte[] out = new byte[data.length + 8];
byte[] dec = new byte[data.length];
try
{
cipher.init(true, key);
int len = cipher.processBytes(data, 0, data.length, out, 0);
len += cipher.doFinal(out, len);
cipher.init(false, key);
int decLen = cipher.processBytes(out, 0, len, dec, 0);
decLen += cipher.doFinal(dec, decLen);
if (!areEqual(data, dec))
{
fail("failed to decrypt - i = " + data.length + ", padding = " + padding.getPaddingName());
}
}
catch (Exception e)
{
fail("Exception - " + e.toString(), e);
}
}
public void testPadding(
BlockCipherPadding padding,
SecureRandom rand,
byte[] ffVector,
byte[] ZeroVector)
{
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new DESEngine(), padding);
KeyParameter key = new KeyParameter(Hex.decode("0011223344556677"));
byte[] data = { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0 };
if (ffVector != null)
{
padding.addPadding(data, 3);
if (!areEqual(data, ffVector))
{
fail("failed ff test for " + padding.getPaddingName());
}
}
if (ZeroVector != null)
{
data = new byte[8];
padding.addPadding(data, 4);
if (!areEqual(data, ZeroVector))
{
fail("failed zero test for " + padding.getPaddingName());
}
}
for (int i = 1; i != 200; i++)
{
data = new byte[i];
rand.nextBytes(data);
blockCheck(cipher, padding, key, data);
}
}
private void testOutputSizes()
{
PaddedBufferedBlockCipher bc = new PaddedBufferedBlockCipher(new DESEngine(), new PKCS7Padding());
KeyParameter key = new KeyParameter(Hex.decode("0011223344556677"));
for (int i = 0; i < bc.getBlockSize() * 2; i++)
{
bc.init(true, key);
if (bc.getUpdateOutputSize(i) < 0)
{
fail("Padded cipher encrypt negative update output size for input size " + i);
}
if (bc.getOutputSize(i) < 0)
{
fail("Padded cipher encrypt negative output size for input size " + i);
}
bc.init(false, key);
if (bc.getUpdateOutputSize(i) < 0)
{
fail("Padded cipher decrypt negative update output size for input size " + i);
}
if (bc.getOutputSize(i) < 0)
{
fail("Padded cipher decrypt negative output size for input size " + i);
}
}
}
public void performTest()
{
SecureRandom rand = new SecureRandom(new byte[20]);
rand.setSeed(System.currentTimeMillis());
testPadding(new PKCS7Padding(), rand,
Hex.decode("ffffff0505050505"),
Hex.decode("0000000004040404"));
PKCS7Padding padder = new PKCS7Padding();
try
{
padder.padCount(new byte[8]);
fail("invalid padding not detected");
}
catch (InvalidCipherTextException e)
{
if (!"pad block corrupted".equals(e.getMessage()))
{
fail("wrong exception for corrupt padding: " + e);
}
}
testPadding(new ISO10126d2Padding(), rand,
null,
null);
testPadding(new X923Padding(), rand,
null,
null);
testPadding(new TBCPadding(), rand,
Hex.decode("ffffff0000000000"),
Hex.decode("00000000ffffffff"));
testPadding(new ZeroBytePadding(), rand,
Hex.decode("ffffff0000000000"),
null);
testPadding(new ISO7816d4Padding(), rand,
Hex.decode("ffffff8000000000"),
Hex.decode("0000000080000000"));
testOutputSizes();
}
public String getName()
{
return "PaddingTest";
}
public static void main(
String[] args)
{
runTest(new PaddingTest());
}
}