All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nl.open.jwtdependency.org.bouncycastle.crypto.test.CCMTest Maven / Gradle / Ivy

Go to download

This is a drop in replacement for the auth0 java-jwt library (see https://github.com/auth0/java-jwt). This jar makes sure there are no external dependencies (e.g. fasterXml, Apacha Commons) needed. This is useful when deploying to an application server (e.g. tomcat with Alfreso or Pega).

The newest version!
package org.bouncycastle.crypto.test;

import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.engines.DESEngine;
import org.bouncycastle.crypto.modes.CCMBlockCipher;
import org.bouncycastle.crypto.params.AEADParameters;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.util.Strings;
import org.bouncycastle.util.encoders.Hex;
import org.bouncycastle.util.test.SimpleTest;

/**
 * First four test vectors from
 * NIST Special Publication 800-38C.
 */
public class CCMTest
    extends SimpleTest
{
    private byte[] K1 = Hex.decode("404142434445464748494a4b4c4d4e4f");
    private byte[] N1 = Hex.decode("10111213141516");
    private byte[] A1 = Hex.decode("0001020304050607");
    private byte[] P1 = Hex.decode("20212223");
    private byte[] C1 = Hex.decode("7162015b4dac255d");
    private byte[] T1 = Hex.decode("6084341b");

    private byte[] K2 = Hex.decode("404142434445464748494a4b4c4d4e4f");
    private byte[] N2 = Hex.decode("1011121314151617");
    private byte[] A2 = Hex.decode("000102030405060708090a0b0c0d0e0f");
    private byte[] P2 = Hex.decode("202122232425262728292a2b2c2d2e2f");
    private byte[] C2 = Hex.decode("d2a1f0e051ea5f62081a7792073d593d1fc64fbfaccd");
    private byte[] T2 = Hex.decode("7f479ffca464");

    private byte[] K3 = Hex.decode("404142434445464748494a4b4c4d4e4f");
    private byte[] N3 = Hex.decode("101112131415161718191a1b");
    private byte[] A3 = Hex.decode("000102030405060708090a0b0c0d0e0f10111213");
    private byte[] P3 = Hex.decode("202122232425262728292a2b2c2d2e2f3031323334353637");
    private byte[] C3 = Hex.decode("e3b201a9f5b71a7a9b1ceaeccd97e70b6176aad9a4428aa5484392fbc1b09951");
    private byte[] T3 = Hex.decode("67c99240c7d51048");

    private byte[] K4 = Hex.decode("404142434445464748494a4b4c4d4e4f");
    private byte[] N4 = Hex.decode("101112131415161718191a1b1c");
    private byte[] A4 = Hex.decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
    private byte[] P4 = Hex.decode("202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f");
    private byte[] C4 = Hex.decode("69915dad1e84c6376a68c2967e4dab615ae0fd1faec44cc484828529463ccf72b4ac6bec93e8598e7f0dadbcea5b");
    private byte[] T4 = Hex.decode("f4dd5d0ee404617225ffe34fce91");

    //
    // long data vector
    //
    private byte[] C5 = Hex.decode("49b17d8d3ea4e6174a48e2b65e6d8b417ac0dd3f8ee46ce4a4a2a509661cef52528c1cd9805333a5cfd482fa3f095a3c2fdd1cc47771c5e55fddd60b5c8d6d3fa5c8dd79d08b16242b6642106e7c0c28bd1064b31e6d7c9800c8397dbc3fa8071e6a38278b386c18d65d39c6ad1ef9501a5c8f68d38eb6474799f3cc898b4b9b97e87f9c95ce5c51bc9d758f17119586663a5684e0a0daf6520ec572b87473eb141d10471e4799ded9e607655402eca5176bbf792ef39dd135ac8d710da8e9e854fd3b95c681023f36b5ebe2fb213d0b62dd6e9e3cfe190b792ccb20c53423b2dca128f861a61d306910e1af418839467e466f0ec361d2539eedd99d4724f1b51c07beb40e875a87491ec8b27cd1");
    private byte[] T5 = Hex.decode("5c768856796b627b13ec8641581b");

    public void performTest()
        throws Exception
    {
        CCMBlockCipher ccm = new CCMBlockCipher(new AESEngine());

        checkVectors(0, ccm, K1, 32, N1, A1, P1, T1, C1);
        checkVectors(1, ccm, K2, 48, N2, A2, P2, T2, C2);
        checkVectors(2, ccm, K3, 64, N3, A3, P3, T3, C3);

        ivParamTest(0, ccm, K1, N1);

        //
        // 4 has a reduced associated text which needs to be replicated
        //
        byte[] a4 = new byte[65536]; // 524288 / 8

        for (int i = 0; i < a4.length; i += A4.length)
        {
            System.arraycopy(A4, 0, a4, i, A4.length);
        }

        checkVectors(3, ccm, K4, 112, N4, a4, P4, T4, C4);

        //
        // long data test
        //
        checkVectors(4, ccm, K4, 112, N4, A4, A4, T5, C5);

        // decryption with output specified, non-zero offset.
        ccm.init(false, new AEADParameters(new KeyParameter(K2), 48, N2, A2));

        byte[] inBuf = new byte[C2.length + 10];
        byte[] outBuf = new byte[ccm.getOutputSize(C2.length) + 10];

        System.arraycopy(C2, 0, inBuf, 10, C2.length);

        int len = ccm.processPacket(inBuf, 10, C2.length, outBuf, 10);
        byte[] out = ccm.processPacket(C2, 0, C2.length);

        if (len != out.length || !isEqual(out, outBuf, 10))
        {
            fail("decryption output incorrect");
        }

        // encryption with output specified, non-zero offset.
        ccm.init(true, new AEADParameters(new KeyParameter(K2), 48, N2, A2));

        int inLen = len;
        inBuf = outBuf;
        outBuf = new byte[ccm.getOutputSize(inLen) + 10];

        len = ccm.processPacket(inBuf, 10, inLen, outBuf, 10);
        out = ccm.processPacket(inBuf, 10, inLen);

        if (len != out.length || !isEqual(out, outBuf, 10))
        {
            fail("encryption output incorrect");
        }

        //
        // exception tests
        //

        try
        {
            ccm.init(false, new AEADParameters(new KeyParameter(K1), 32, N2, A2));

            ccm.processPacket(C2, 0, C2.length);

            fail("invalid cipher text not picked up");
        }
        catch (InvalidCipherTextException e)
        {
            // expected
        }

        try
        {
            ccm = new CCMBlockCipher(new DESEngine());

            fail("incorrect block size not picked up");
        }
        catch (IllegalArgumentException e)
        {
            // expected
        }

        try
        {
            ccm.init(false, new KeyParameter(K1));

            fail("illegal argument not picked up");
        }
        catch (IllegalArgumentException e)
        {
            // expected
        }

        AEADTestUtil.testReset(this, new CCMBlockCipher(new AESEngine()), new CCMBlockCipher(new AESEngine()), new AEADParameters(new KeyParameter(K1), 32, N2));
        AEADTestUtil.testTampering(this, ccm, new AEADParameters(new KeyParameter(K1), 32, N2));
        AEADTestUtil.testOutputSizes(this, new CCMBlockCipher(new AESEngine()), new AEADParameters(
                new KeyParameter(K1), 32, N2));
        AEADTestUtil.testBufferSizeChecks(this, new CCMBlockCipher(new AESEngine()), new AEADParameters(
                new KeyParameter(K1), 32, N2));
    }

    private boolean isEqual(byte[] exp, byte[] other, int off)
    {
        for (int i = 0; i != exp.length; i++)
        {
            if (exp[i] != other[off + i])
            {
                return false;
            }
        }

        return true;
    }

    private void checkVectors(
        int count,
        CCMBlockCipher ccm,
        byte[] k,
        int macSize,
        byte[] n,
        byte[] a,
        byte[] p,
        byte[] t,
        byte[] c)
        throws InvalidCipherTextException
    {
        byte[] fa = new byte[a.length / 2];
        byte[] la = new byte[a.length - (a.length / 2)];
        System.arraycopy(a, 0, fa, 0, fa.length);
        System.arraycopy(a, fa.length, la, 0, la.length);

        checkVectors(count, ccm, "all initial associated data", k, macSize, n, a, null, p, t, c);
        checkVectors(count, ccm, "subsequent associated data", k, macSize, n, null, a, p, t, c);
        checkVectors(count, ccm, "split associated data", k, macSize, n, fa, la, p, t, c);
        checkVectors(count, ccm, "reuse key", null, macSize, n, fa, la, p, t, c);
    }

    private void checkVectors(
        int count,
        CCMBlockCipher ccm,
        String additionalDataType,
        byte[] k,
        int macSize,
        byte[] n,
        byte[] a,
        byte[] sa,
        byte[] p,
        byte[] t,
        byte[] c)
        throws InvalidCipherTextException
    {
        KeyParameter keyParam = (k == null) ? null : new KeyParameter(k);

        ccm.init(true, new AEADParameters(keyParam, macSize, n, a));

        byte[] enc = new byte[c.length];

        if (sa != null)
        {
            ccm.processAADBytes(sa, 0, sa.length);
        }

        int len = ccm.processBytes(p, 0, p.length, enc, 0);

        len += ccm.doFinal(enc, len);

        if (!areEqual(c, enc))
        {
            fail("encrypted stream fails to match in test " + count + " with " + additionalDataType);
        }

        ccm.init(false, new AEADParameters(keyParam, macSize, n, a));

        byte[] tmp = new byte[enc.length];

        if (sa != null)
        {
            ccm.processAADBytes(sa, 0, sa.length);
        }

        len = ccm.processBytes(enc, 0, enc.length, tmp, 0);

        len += ccm.doFinal(tmp, len);

        byte[] dec = new byte[len];

        System.arraycopy(tmp, 0, dec, 0, len);

        if (!areEqual(p, dec))
        {
            fail("decrypted stream fails to match in test " + count + " with " + additionalDataType,
                    new String(Hex.encode(p)), new String(Hex.encode(dec)));
        }

        if (!areEqual(t, ccm.getMac()))
        {
            fail("MAC fails to match in test " + count + " with " + additionalDataType);
        }
    }

    private void ivParamTest(
        int count,
        CCMBlockCipher ccm,
        byte[] k,
        byte[] n)
        throws InvalidCipherTextException
    {
        byte[] p = Strings.toByteArray("hello world!!");

        ccm.init(true, new ParametersWithIV(new KeyParameter(k), n));

        byte[] enc = new byte[p.length + 8];

        int len = ccm.processBytes(p, 0, p.length, enc, 0);

        len += ccm.doFinal(enc, len);

        ccm.init(false, new ParametersWithIV(new KeyParameter(k), n));

        byte[] tmp = new byte[enc.length];

        len = ccm.processBytes(enc, 0, enc.length, tmp, 0);

        len += ccm.doFinal(tmp, len);

        byte[] dec = new byte[len];

        System.arraycopy(tmp, 0, dec, 0, len);

        if (!areEqual(p, dec))
        {
            fail("decrypted stream fails to match in test " + count);
        }
    }

    public String getName()
    {
        return "CCM";
    }

    public static void main(
        String[]    args)
    {
        runTest(new CCMTest());
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy