blob: c63b539e6b6980c72732a5eccf4018288064bcdb [file] [log] [blame]
package org.bouncycastle.crypto.test;
import java.util.Random;
import junit.framework.TestCase;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.SkippingStreamCipher;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.engines.ChaChaEngine;
import org.bouncycastle.crypto.engines.Salsa20Engine;
import org.bouncycastle.crypto.modes.SICBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.encoders.Hex;
public class BigSkippingCipherTest
extends TestCase
{
public void testAESCTR()
throws Exception
{
CipherParameters externalCounterParams = new ParametersWithIV(new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917")), Hex.decode("00000000000000000000000000000000"));
CipherParameters internalCounterParams = new ParametersWithIV(new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917")), Hex.decode("00000000000000000000"));
SICBlockCipher linearEngine = new SICBlockCipher(new AESEngine());
SICBlockCipher skippingEngine = new SICBlockCipher(new AESEngine());
Random random = new Random();
linearEngine.init(true, externalCounterParams);
skippingEngine.init(false, internalCounterParams);
testCipher(random, linearEngine, skippingEngine);
byte[] in = Base64.decode("pzVbCyj5JntIYN2Kvzf64/po+gTu/jvnZwU33F7UsfxpWRUDEGIQbArxqCQzEkGAwa4omXJ28WJveJNUQbQ5cBxS2aTt3sV0mrP+cneJ3OZkzo5Lhz0vuXs7Mav9uUzQFrU0DuMyGr1QJnKO0BUal0gLJ0v6YAo2SObDS5A4CTrsAgo0C2UXQmnuGzyYlhm4VoSNotD8auqyQXUrT8c2B/tLIcjyyl8ug1BabL2gAxN7oKbpvW5j2z3IZNZh+AKR4OR47RfjtYglOfgGQB1L5yiL9reuWEsRjbZmcEFfLmAAK0gtcP+0KDXV/DS4NxRx0sC7NkBzSC3uq2RbQOdjygFZ5qrmvwQZgLqlXs2cGiNzqx5CRjAvl83aAWAAerR5T2sHadRckW01oE2ivQixpgdPCGFHLeXoPMlkZ/r1cECYFAGPjMGSG2qnQZ/ZJbStEAZye/11r/dyoUgP+XTc6FDCCQHSdmyQljPHDQm7ioMTTkCf15YWv0kSuKOd4nBlLrGjSl9dsJsVU9TDRCqNExmk+lN3f0p8vr8TVNnir+OtEabOXzjOv6i3PHQZP27ML3Hy9TU1MHx1Q0bLdgi6yIw8lmzzBzok8j5VrCpNf2HmBqtRm1WDeTO9R62OWyaMT/dCT7AzEzP8ClBSq57p69OrlEDoaLXrYvNS3hEw1Lo=");
byte[] exp = Base64.decode("JD0KPwMaKvqYZnDgI0rFTCbexg+RRj3UbEPtsf5IDeM3lb5OJ5EMLHXrfknu//XNLE6dV/Jaoz3LuylkfRlMg2/Vvgo6KwXNV3VsUgkEmTpy74NAd9DCh+1EgJYCNbHkT/haaKpPWLqHEIp1/LVKZZgRXc+C4kH02GzqwYkjUZCSrE8GBpiILlHhN+2A14Ltmxe7XZrlnOQx62sBoh+QR2ZCSAhQjMayhnkrIC1qpM8S4vcZbAYOGuVRcmBhGZdvQg+YXUKrx3FS6XS+xF3yMld5iVx2aEzjkmXuDoULLzrppD/5Ed0I2CCFZigBZ3ZFsOGIZw1yTBXLRVroM/xksYaGgQs9arKB3rEBpUV4yUMuYokqz9A4k7jg/6loTFU8SntBzXptrPuKPbEMT/FvJqEsI3yKCndYiRAkTRmHWhNmdjLH9Pw32VYlpbjYzQjPP6Iy055VujucBofsP3/ENK32XNs1I6PzcVrjjRJaBy3dbAB0e7/P7cqnUvKu+dSR7N92VnuDtCaS5ksVMWJOlfLhqLq8umz8+3aIsTj20bfNGzf4aeqkUzv+AezQedVY3gmYBgwv/1ZR3Y9bUATE4ieIwK+gkZBgtANOs2abY+8+of5sQhyfYiWpUrSb+L/7MjaFgBz+b69bD5xl0kes/ySVGBqaqG4jcOr01qGfaLw=");
byte[] buf = new byte[512];
skippingEngine.seekTo(1L << 38);
skippingEngine.processBytes(in, 0, in.length, buf, 0);
if (!Arrays.areEqual(buf, exp))
{
fail("long seek failed");
}
skippingEngine.skip(-(1L << 38) - 512);
if (skippingEngine.getPosition() != 0)
{
fail("zero position came back as: " + skippingEngine.getPosition());
}
random.nextBytes(buf);
byte[] linOut = new byte[512];
byte[] skipOut = new byte[512];
linearEngine.init(true, internalCounterParams);
linearEngine.processBytes(buf, 0, buf.length, linOut, 0);
skippingEngine.processBytes(buf, 0, buf.length, skipOut, 0);
if (!Arrays.areEqual(linOut, skipOut))
{
fail("long output mismatch");
}
}
public void testSalsa20()
throws Exception
{
CipherParameters params = new ParametersWithIV(new KeyParameter(Hex.decode("0053A6F94C9FF24598EB3E91E4378ADD3083D6297CCF2275C81B6EC11467BA0D")), Hex.decode("0D74DB42A91077DE"));
Salsa20Engine linearEngine = new Salsa20Engine();
Salsa20Engine skippingEngine = new Salsa20Engine();
Random random = new Random();
linearEngine.init(true, params);
skippingEngine.init(false, params);
testCipher(random, linearEngine, skippingEngine);
byte[] in = Base64.decode("pzVbCyj5JntIYN2Kvzf64/po+gTu/jvnZwU33F7UsfxpWRUDEGIQbArxqCQzEkGAwa4omXJ28WJveJNUQbQ5cBxS2aTt3sV0mrP+cneJ3OZkzo5Lhz0vuXs7Mav9uUzQFrU0DuMyGr1QJnKO0BUal0gLJ0v6YAo2SObDS5A4CTrsAgo0C2UXQmnuGzyYlhm4VoSNotD8auqyQXUrT8c2B/tLIcjyyl8ug1BabL2gAxN7oKbpvW5j2z3IZNZh+AKR4OR47RfjtYglOfgGQB1L5yiL9reuWEsRjbZmcEFfLmAAK0gtcP+0KDXV/DS4NxRx0sC7NkBzSC3uq2RbQOdjygFZ5qrmvwQZgLqlXs2cGiNzqx5CRjAvl83aAWAAerR5T2sHadRckW01oE2ivQixpgdPCGFHLeXoPMlkZ/r1cECYFAGPjMGSG2qnQZ/ZJbStEAZye/11r/dyoUgP+XTc6FDCCQHSdmyQljPHDQm7ioMTTkCf15YWv0kSuKOd4nBlLrGjSl9dsJsVU9TDRCqNExmk+lN3f0p8vr8TVNnir+OtEabOXzjOv6i3PHQZP27ML3Hy9TU1MHx1Q0bLdgi6yIw8lmzzBzok8j5VrCpNf2HmBqtRm1WDeTO9R62OWyaMT/dCT7AzEzP8ClBSq57p69OrlEDoaLXrYvNS3hEw1Lo=");
byte[] exp = Base64.decode("e0bdyXVHsxzA9pZ/htVVPAsAgief6pEyLmdayG09N3GkBZFulTze/He524ETzTGtV7c1yGypTwjwVr+rNWmZs9YeXtYljySAQUbv1il5spmn7+iiwN6H21Keg6r4ciwzR7jhm7Wc0A1GGkh8OLmb2ZAh/fNDXHyL8mbEmLYh5C9n+DCTruTEjtS5TwueaRsUSNkexUgemqOVHxeOD0nZcVARr2AzMW6btNrQycol3+WTvLmbCeAZwcZnfPvZeU3r2UF73o8lP0vOUrOi095H2WZkJIVrAiV/+i4Sb76XXRgFlvWP6RbX9mYApIBhs69+yxp8lmVI0AABAwwV7PNXo+1UK6kzNi5spa32MRDMogP+wDHMyu8nHzLpIv9OTx0CmkZ0XO4Lla3d3UsPGq8g50a6gfrSOa9JHYFjfMzqIY/6SdZxr39Z8jVYiCfWGYplMTSDvfj3whk2J0DnSSdf6k6JstCjIXeMagKjwpcf9r0kq1Q9mAGhdJLqkM2LYHz3CP6GiWbGy5477GKnrhFDOeG1PtLv4YaTLrrjnNngIeeMK0tgkwBhsobVCD1hSs26I9/V+rdFhFb3/a/ob37cfnPmflbC0oOpSKoY6tZEaDp9u2ulNCpLYV6zrn3k9soP4q+sfsmXKMuWU2+rJGvBOEPh9Jo8Z+u7r+1PG+8VgAs=");
byte[] buf = new byte[512];
skippingEngine.seekTo(1L << 38);
skippingEngine.processBytes(in, 0, in.length, buf, 0);
if (!Arrays.areEqual(buf, exp))
{
fail("long seek failed");
}
skippingEngine.skip(-(1L << 38) - 512);
if (skippingEngine.getPosition() != 0)
{
fail("zero position came back as: " + skippingEngine.getPosition());
}
random.nextBytes(buf);
byte[] linOut = new byte[512];
byte[] skipOut = new byte[512];
linearEngine.init(true, params);
linearEngine.processBytes(buf, 0, buf.length, linOut, 0);
skippingEngine.processBytes(buf, 0, buf.length, skipOut, 0);
if (!Arrays.areEqual(linOut, skipOut))
{
fail("long output mismatch");
}
}
public void testChaCha()
throws Exception
{
CipherParameters params = new ParametersWithIV(new KeyParameter(Hex.decode("0053A6F94C9FF24598EB3E91E4378ADD3083D6297CCF2275C81B6EC11467BA0D")), Hex.decode("0D74DB42A91077DE"));
ChaChaEngine linearEngine = new ChaChaEngine();
ChaChaEngine skippingEngine = new ChaChaEngine();
Random random = new Random();
linearEngine.init(true, params);
skippingEngine.init(false, params);
testCipher(random, linearEngine, skippingEngine);
byte[] in = Base64.decode("pzVbCyj5JntIYN2Kvzf64/po+gTu/jvnZwU33F7UsfxpWRUDEGIQbArxqCQzEkGAwa4omXJ28WJveJNUQbQ5cBxS2aTt3sV0mrP+cneJ3OZkzo5Lhz0vuXs7Mav9uUzQFrU0DuMyGr1QJnKO0BUal0gLJ0v6YAo2SObDS5A4CTrsAgo0C2UXQmnuGzyYlhm4VoSNotD8auqyQXUrT8c2B/tLIcjyyl8ug1BabL2gAxN7oKbpvW5j2z3IZNZh+AKR4OR47RfjtYglOfgGQB1L5yiL9reuWEsRjbZmcEFfLmAAK0gtcP+0KDXV/DS4NxRx0sC7NkBzSC3uq2RbQOdjygFZ5qrmvwQZgLqlXs2cGiNzqx5CRjAvl83aAWAAerR5T2sHadRckW01oE2ivQixpgdPCGFHLeXoPMlkZ/r1cECYFAGPjMGSG2qnQZ/ZJbStEAZye/11r/dyoUgP+XTc6FDCCQHSdmyQljPHDQm7ioMTTkCf15YWv0kSuKOd4nBlLrGjSl9dsJsVU9TDRCqNExmk+lN3f0p8vr8TVNnir+OtEabOXzjOv6i3PHQZP27ML3Hy9TU1MHx1Q0bLdgi6yIw8lmzzBzok8j5VrCpNf2HmBqtRm1WDeTO9R62OWyaMT/dCT7AzEzP8ClBSq57p69OrlEDoaLXrYvNS3hEw1Lo=");
byte[] exp = Base64.decode("FACFDKSYxFYEOknCBPdfy5elbrDu8FzOImwpczlIk1HWlcbBPHXwHEnVaKrGtmthC7gA1DQJSeobO83KW3YZVkT8fcGnMFbeee6ISs9R4KqekE+Fs8uNWYlqsgT5xrErOC/cmz4B5envQx7EZK5h+fJupYO3vHqVk5/Q6c/v8ndDeBKSDTKA6eyybOwFVIjwJKPfuliu4mJGHphUIsp/OgRPs+VhlMrWXMVwsGzGHy9xZvTz6Xv6GJvrIoONMHh24YGOSt+83cFTepU7ur8anyDaoWzMz/n04eopnQd9TlREwYOZWdF0ZAJ0VZQYEixopmH+mlEZ/Nyw6IDswvyX3Zf/7lyDsM8bv2kz1gXvmQgUMqr6wXrOuJtxaH8aUvLVswCeNZEGFl17FHgwdD2MRzkmhfPRFlTgicd02D/ateBs5B0ORu5CKu3p/RGjU4YE68ONPNEkwkBRm5uGzdezTJmUzdJAEtoIxv1XfE1tytP7U+BpWdP5LY5NlEUo6sNR4O2nlSQJkAOzhoz821hnn1IL6r9DLDHIW40IhStDqc5Hy/8rEZgnnFhIE6pAD1PAGV5oJk/Z/V64bFvGkpD7xuhN5U2Eic7UheB8D227JtQQWTc8GhynlOWbmkYm/koKw+ieraN5IWE/KD2HFqJhxasB9lb3lMGh3zfgBKck5Lo=");
byte[] buf = new byte[512];
skippingEngine.seekTo(1L << 38);
skippingEngine.processBytes(in, 0, in.length, buf, 0);
if (!Arrays.areEqual(buf, exp))
{
fail("long seek failed");
}
skippingEngine.skip(-(1L << 38) - 512);
if (skippingEngine.getPosition() != 0)
{
fail("zero position came back as: " + skippingEngine.getPosition());
}
random.nextBytes(buf);
byte[] linOut = new byte[512];
byte[] skipOut = new byte[512];
linearEngine.init(true, params);
linearEngine.processBytes(buf, 0, buf.length, linOut, 0);
skippingEngine.processBytes(buf, 0, buf.length, skipOut, 0);
if (!Arrays.areEqual(linOut, skipOut))
{
fail("long output mismatch");
}
}
public void testCipher(Random random, SkippingStreamCipher linearEngine, SkippingStreamCipher skippingEngine)
throws Exception
{
byte[] startDataBuf = new byte[1 << 16];
byte[] startEncBuf = new byte[1 << 16];
byte[] startSeekBuf = new byte[1 << 16];
random.nextBytes(startDataBuf);
linearEngine.processBytes(startDataBuf, 0, startDataBuf.length, startEncBuf, 0);
byte[] incBuf = new byte[1 << 12];
byte[] linearOutBuf = new byte[1 << 12];
byte[] seekOutBuf = new byte[1 << 12];
for (long i = 0; i != 1L << 20; i++)
{
random.nextBytes(incBuf);
linearEngine.processBytes(incBuf, 0, incBuf.length, linearOutBuf, 0);
skippingEngine.seekTo(startDataBuf.length + i * incBuf.length);
if (skippingEngine.getPosition() != startDataBuf.length + i * incBuf.length)
{
fail(i + "th position came back as: " + skippingEngine.getPosition());
}
skippingEngine.processBytes(incBuf, 0, incBuf.length, seekOutBuf, 0);
if (!Arrays.areEqual(linearOutBuf, seekOutBuf))
{
fail("output mismatch");
}
if (skippingEngine.getPosition() != startDataBuf.length + (i + 1) * incBuf.length)
{
fail(i + "th + 1 position came back as: " + skippingEngine.getPosition());
}
skippingEngine.skip(-skippingEngine.getPosition());
if (skippingEngine.getPosition() != 0)
{
fail("zero position came back as: " + skippingEngine.getPosition());
}
skippingEngine.processBytes(startEncBuf, 0, startEncBuf.length, startSeekBuf, 0);
if (!Arrays.areEqual(startDataBuf, startSeekBuf))
{
fail("output mismatch");
}
}
}
}