Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package org.bouncycastle.crypto.test;
  
  
Test vectors from RFC 7253 on The OCB Authenticated-Encryption Algorithm
 
 public class OCBTest
     extends SimpleTest
 {
     private static final String KEY_128 = "000102030405060708090A0B0C0D0E0F";
     private static final String KEY_96 = "0F0E0D0C0B0A09080706050403020100";
 
     /*
      * Test vectors from Appendix A of the specification, containing the strings N, A, P, C in order
      */
 
     private static final String[][] TEST_VECTORS_128 = new String[][]{
         { "BBAA99887766554433221100",
           "",
           "",
           "785407BFFFC8AD9EDCC5520AC9111EE6" },
         { "BBAA99887766554433221101",
           "0001020304050607",
           "0001020304050607",
           "6820B3657B6F615A5725BDA0D3B4EB3A257C9AF1F8F03009" },
         { "BBAA99887766554433221102",
           "0001020304050607",
           "",
           "81017F8203F081277152FADE694A0A00" },
         { "BBAA99887766554433221103",
           "",
           "0001020304050607",
           "45DD69F8F5AAE72414054CD1F35D82760B2CD00D2F99BFA9" },
         { "BBAA99887766554433221104",
           "000102030405060708090A0B0C0D0E0F",
           "000102030405060708090A0B0C0D0E0F",
           "571D535B60B277188BE5147170A9A22C3AD7A4FF3835B8C5701C1CCEC8FC3358" },
         { "BBAA99887766554433221105",
           "000102030405060708090A0B0C0D0E0F",
           "",
           "8CF761B6902EF764462AD86498CA6B97" },
         { "BBAA99887766554433221106",
           "",
           "000102030405060708090A0B0C0D0E0F",
           "5CE88EC2E0692706A915C00AEB8B2396F40E1C743F52436BDF06D8FA1ECA343D" },
         { "BBAA99887766554433221107",
           "000102030405060708090A0B0C0D0E0F1011121314151617",
           "000102030405060708090A0B0C0D0E0F1011121314151617",
           "1CA2207308C87C010756104D8840CE1952F09673A448A122C92C62241051F57356D7F3C90BB0E07F" },
         { "BBAA99887766554433221108",
           "000102030405060708090A0B0C0D0E0F1011121314151617",
           "",
           "6DC225A071FC1B9F7C69F93B0F1E10DE" },
         { "BBAA99887766554433221109",
           "",
           "000102030405060708090A0B0C0D0E0F1011121314151617",
           "221BD0DE7FA6FE993ECCD769460A0AF2D6CDED0C395B1C3CE725F32494B9F914D85C0B1EB38357FF" },
         { "BBAA9988776655443322110A",
           "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
           "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
           "BD6F6C496201C69296C11EFD138A467ABD3C707924B964DEAFFC40319AF5A48540FBBA186C5553C68AD9F592A79A4240" },
         { "BBAA9988776655443322110B",
           "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
           "",
           "FE80690BEE8A485D11F32965BC9D2A32" },
         { "BBAA9988776655443322110C",
           "",
           "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
           "2942BFC773BDA23CABC6ACFD9BFD5835BD300F0973792EF46040C53F1432BCDFB5E1DDE3BC18A5F840B52E653444D5DF" },
         { "BBAA9988776655443322110D",
           "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
           "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
           "D5CA91748410C1751FF8A2F618255B68A0A12E093FF454606E59F9C1D0DDC54B65E8628E568BAD7AED07BA06A4A69483A7035490C5769E60" },
         { "BBAA9988776655443322110E",
           "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
           "",
           "C5CD9D1850C141E358649994EE701B68" },
         { "BBAA9988776655443322110F",
           "",
           "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
           "4412923493C57D5DE0D700F753CCE0D1D2D95060122E9F15A5DDBFC5787E50B5CC55EE507BCB084E479AD363AC366B95A98CA5F3000B1479" },
     };
 
     private static final String[][] TEST_VECTORS_96 = new String[][]{
        { "BBAA9988776655443322110D",
          "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
          "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
          "1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1A0124B0A55BAE884ED93481529C76B6AD0C515F4D1CDD4FDAC4F02AA" },
    };
    public String getName()
    {
        return "OCB";
    }
    public void performTest()
        throws Exception
    {
        byte[] K128 = Hex.decode();
        for (int i = 0; i < .; ++i)
        {
            runTestCase("Test Case " + i[i], 128, K128);
        }
        byte[] K96 = Hex.decode();
        for (int i = 0; i < .; ++i)
        {
            runTestCase("Test Case " + i[i], 96, K96);
        }
        runLongerTestCase(128, 128, "67E944D23256C5E0B6C61FA22FDF1EA2");
        runLongerTestCase(192, 128, "F673F2C3E7174AAE7BAE986CA9F29E17");
        runLongerTestCase(256, 128, "D90EB8E9C977C88B79DD793D7FFA161C");
        runLongerTestCase(128, 96, "77A3D8E73589158D25D01209");
        runLongerTestCase(192, 96, "05D56EAD2752C86BE6932C5E");
        runLongerTestCase(256, 96, "5458359AC23B0CBA9E6330DD");
        runLongerTestCase(128, 64, "192C9B7BD90BA06A");
        runLongerTestCase(192, 64, "0066BC6E0EF34E24");
        runLongerTestCase(256, 64, "7D4EA5D445501CBE");
        randomTests();
        outputSizeTests();
        testExceptions();
    }
    private void testExceptions() throws InvalidCipherTextException
    {
        AEADBlockCipher ocb = createOCBCipher();
        try
        {
            ocb = new OCBBlockCipher(new DESEngine(), new DESEngine());
            fail("incorrect block size not picked up");
        }
        catch (IllegalArgumentException e)
        {
            // expected
        }
        try
        {
            ocb.init(falsenew KeyParameter(new byte[16]));
            fail("illegal argument not picked up");
        }
        catch (IllegalArgumentException e)
        {
            // expected
        }
        AEADTestUtil.testReset(thiscreateOCBCipher(), createOCBCipher(), new AEADParameters(new KeyParameter(new byte[16]), 128, new byte[15]));
        AEADTestUtil.testTampering(thisocbnew AEADParameters(new KeyParameter(new byte[16]), 128, new byte[15]));
        AEADTestUtil.testOutputSizes(thiscreateOCBCipher(), new AEADParameters(new KeyParameter(new byte[16]), 128,
                new byte[15]));
        AEADTestUtil.testBufferSizeChecks(thiscreateOCBCipher(), new AEADParameters(new KeyParameter(new byte[16]),
                128, new byte[15]));
    }
    private void runTestCase(String testNameString[] testVectorint macLengthBitsbyte[] K)
        throws InvalidCipherTextException
    {
        int pos = 0;
        byte[] N = Hex.decode(testVector[pos++]);
        byte[] A = Hex.decode(testVector[pos++]);
        byte[] P = Hex.decode(testVector[pos++]);
        byte[] C = Hex.decode(testVector[pos++]);
        int macLengthBytes = macLengthBits / 8;
        KeyParameter keyParameter = new KeyParameter(K);
        AEADParameters parameters = new AEADParameters(keyParametermacLengthBitsNA);
        AEADBlockCipher encCipher = initOCBCipher(trueparameters);
        AEADBlockCipher decCipher = initOCBCipher(falseparameters);
        checkTestCase(encCipherdecCiphertestNamemacLengthBytesPC);
        checkTestCase(encCipherdecCiphertestName + " (reused)"macLengthBytesPC);
        // Key reuse
        AEADParameters keyReuseParams = AEADTestUtil.reuseKey(parameters);
        encCipher.init(truekeyReuseParams);
        decCipher.init(falsekeyReuseParams);
        checkTestCase(encCipherdecCiphertestName + " (key reuse)"macLengthBytesPC);
    }
    {
        return new AESEngine();
    }
    {
    }
    private AEADBlockCipher initOCBCipher(boolean forEncryptionAEADParameters parameters)
    {
        AEADBlockCipher c = createOCBCipher();
        c.init(forEncryptionparameters);
        return c;
    }
    private void checkTestCase(AEADBlockCipher encCipherAEADBlockCipher decCipherString testName,
        int macLengthBytesbyte[] Pbyte[] C)
        throws InvalidCipherTextException
    {
        byte[] tag = Arrays.copyOfRange(CC.length - macLengthBytesC.length);
        {
            byte[] enc = new byte[encCipher.getOutputSize(P.length)];
            int len = encCipher.processBytes(P, 0, P.lengthenc, 0);
            len += encCipher.doFinal(enclen);
            if (enc.length != len)
            {
                fail("encryption reported incorrect length: " + testName);
            }
            if (!areEqual(Cenc))
            {
                fail("incorrect encrypt in: " + testName);
            }
            if (!areEqual(tagencCipher.getMac()))
            {
                fail("getMac() not the same as the appended tag: " + testName);
            }
        }
        {
            byte[] dec = new byte[decCipher.getOutputSize(C.length)];
            int len = decCipher.processBytes(C, 0, C.lengthdec, 0);
            len += decCipher.doFinal(declen);
            if (dec.length != len)
            {
                fail("decryption reported incorrect length: " + testName);
            }
            if (!areEqual(Pdec))
            {
                fail("incorrect decrypt in: " + testName);
            }
            if (!areEqual(tagdecCipher.getMac()))
            {
                fail("getMac() not the same as the appended tag: " + testName);
            }
        }
    }
    private void runLongerTestCase(int keyLenint tagLenString expectedOutputHex)
        throws InvalidCipherTextException
    {
        byte[] expectedOutput = Hex.decode(expectedOutputHex);
        byte[] keyBytes = new byte[keyLen / 8];
        keyBytes[keyBytes.length - 1] = (byte)tagLen;
        KeyParameter key = new KeyParameter(keyBytes);
        AEADBlockCipher c1 = initOCBCipher(truenew AEADParameters(keytagLencreateNonce(385)));
        AEADBlockCipher c2 = createOCBCipher();
        long total = 0;
        byte[] S = new byte[128];
        int n = 0;
        for (int i = 0; i < 128; ++i)
        {
            c2.init(truenew AEADParameters(keytagLencreateNonce(++n)));
            total += updateCiphers(c1c2Sitruetrue);
            c2.init(truenew AEADParameters(keytagLencreateNonce(++n)));
            total += updateCiphers(c1c2Sifalsetrue);
            c2.init(truenew AEADParameters(keytagLencreateNonce(++n)));
            total += updateCiphers(c1c2Sitruefalse);
        }
        long expectedTotal = 16256 + (48 * tagLen);
        if (total != expectedTotal)
        {
            fail("test generated the wrong amount of input: " + total);
        }
        byte[] output = new byte[c1.getOutputSize(0)];
        c1.doFinal(output, 0);
        if (!areEqual(expectedOutputoutput))
        {
            fail("incorrect encrypt in long-form test");
        }
    }
    private byte[] createNonce(int n)
    {
        return new byte[]{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte)(n >>> 8), (byte)n };
    }
    private int updateCiphers(AEADBlockCipher c1AEADBlockCipher c2byte[] Sint i,
        boolean includeAADboolean includePlaintext)
        throws InvalidCipherTextException
    {
        int inputLen = includePlaintext ? i : 0;
        int outputLen = c2.getOutputSize(inputLen);
        byte[] output = new byte[outputLen];
        int len = 0;
        if (includeAAD)
        {
            c2.processAADBytes(S, 0, i);
        }
        if (includePlaintext)
        {
            len += c2.processBytes(S, 0, ioutputlen);
        }
        len += c2.doFinal(outputlen);
        c1.processAADBytes(output, 0, len);
        return len;
    }
    private void randomTests()
        throws InvalidCipherTextException
    {
        SecureRandom srng = new SecureRandom();
        srng.setSeed(Times.nanoTime());
        for (int i = 0; i < 10; ++i)
        {
            randomTest(srng);
        }
    }
    private void randomTest(SecureRandom srng)
        throws InvalidCipherTextException
    {
        int kLength = 16 + 8 * (Math.abs(srng.nextInt()) % 3);
        byte[] K = new byte[kLength];
        srng.nextBytes(K);
        int pLength = srng.nextInt() >>> 16;
        byte[] P = new byte[pLength];
        srng.nextBytes(P);
        int aLength = srng.nextInt() >>> 24;
        byte[] A = new byte[aLength];
        srng.nextBytes(A);
        int saLength = srng.nextInt() >>> 24;
        byte[] SA = new byte[saLength];
        srng.nextBytes(SA);
        int ivLength = 1 + nextInt(srng, 15);
        byte[] IV = new byte[ivLength];
        srng.nextBytes(IV);
        AEADParameters parameters = new AEADParameters(new KeyParameter(K), 16 * 8, IVA);
        AEADBlockCipher cipher = initOCBCipher(trueparameters);
        byte[] C = new byte[cipher.getOutputSize(P.length)];
        int predicted = cipher.getUpdateOutputSize(P.length);
        int split = nextInt(srngSA.length + 1);
        cipher.processAADBytes(SA, 0, split);
        int len = cipher.processBytes(P, 0, P.lengthC, 0);
        cipher.processAADBytes(SAsplitSA.length - split);
        if (predicted != len)
        {
            fail("encryption reported incorrect update length in randomised test");
        }
        len += cipher.doFinal(Clen);
        if (C.length != len)
        {
            fail("encryption reported incorrect length in randomised test");
        }
        byte[] encT = cipher.getMac();
        byte[] tail = new byte[C.length - P.length];
        System.arraycopy(CP.lengthtail, 0, tail.length);
        if (!areEqual(encTtail))
        {
            fail("stream contained wrong mac in randomised test");
        }
        cipher.init(falseparameters);
        byte[] decP = new byte[cipher.getOutputSize(C.length)];
        predicted = cipher.getUpdateOutputSize(C.length);
        split = nextInt(srngSA.length + 1);
        cipher.processAADBytes(SA, 0, split);
        len = cipher.processBytes(C, 0, C.lengthdecP, 0);
        cipher.processAADBytes(SAsplitSA.length - split);
        if (predicted != len)
        {
            fail("decryption reported incorrect update length in randomised test");
        }
        len += cipher.doFinal(decPlen);
        if (!areEqual(PdecP))
        {
            fail("incorrect decrypt in randomised test");
        }
        byte[] decT = cipher.getMac();
        if (!areEqual(encTdecT))
        {
            fail("decryption produced different mac from encryption");
        }
        //
        // key reuse test
        //
        cipher.init(false, AEADTestUtil.reuseKey(parameters));
        decP = new byte[cipher.getOutputSize(C.length)];
        split = nextInt(srngSA.length + 1);
        cipher.processAADBytes(SA, 0, split);
        len = cipher.processBytes(C, 0, C.lengthdecP, 0);
        cipher.processAADBytes(SAsplitSA.length - split);
        len += cipher.doFinal(decPlen);
        if (!areEqual(PdecP))
        {
            fail("incorrect decrypt in randomised test");
        }
        decT = cipher.getMac();
        if (!areEqual(encTdecT))
        {
            fail("decryption produced different mac from encryption");
        }
    }
    private void outputSizeTests()
    {
        byte[] K = new byte[16];
        byte[] A = null;
        byte[] IV = new byte[15];
        AEADParameters parameters = new AEADParameters(new KeyParameter(K), 16 * 8, IVA);
        AEADBlockCipher cipher = initOCBCipher(trueparameters);
        if (cipher.getUpdateOutputSize(0) != 0)
        {
            fail("incorrect getUpdateOutputSize for initial 0 bytes encryption");
        }
        if (cipher.getOutputSize(0) != 16)
        {
            fail("incorrect getOutputSize for initial 0 bytes encryption");
        }
        cipher.init(falseparameters);
        if (cipher.getUpdateOutputSize(0) != 0)
        {
            fail("incorrect getUpdateOutputSize for initial 0 bytes decryption");
        }
        // NOTE: 0 bytes would be truncated data, but we want it to fail in the doFinal, not here
        if (cipher.getOutputSize(0) != 0)
        {
            fail("fragile getOutputSize for initial 0 bytes decryption");
        }
        if (cipher.getOutputSize(16) != 0)
        {
            fail("incorrect getOutputSize for initial MAC-size bytes decryption");
        }
    }
    private static int nextInt(SecureRandom randint n)
    {
        if ((n & -n) == n)  // i.e., n is a power of 2
        {
            return (int)((n * (long)(rand.nextInt() >>> 1)) >> 31);
        }
        int bitsvalue;
        do
        {
            bits = rand.nextInt() >>> 1;
            value = bits % n;
        }
        while (bits - value + (n - 1) < 0);
        return value;
    }
    public static void main(String[] args)
    {
        runTest(new OCBTest());
    }
New to GrepCode? Check out our FAQ X