org.bouncycastle.crypto.engines.NoekeonEngine.java Source code

Java tutorial

Introduction

Here is the source code for org.bouncycastle.crypto.engines.NoekeonEngine.java

Source

package org.bouncycastle.crypto.engines;

import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.OutputLengthException;
import org.bouncycastle.crypto.params.KeyParameter;

/**
 * A Noekeon engine, using direct-key mode.
 */

public class NoekeonEngine implements BlockCipher {
    private static final int genericSize = 16; // Block and key size, as well as the amount of rounds.

    private static final int[] nullVector = { 0x00, 0x00, 0x00, 0x00 // Used in decryption
    },

            roundConstants = { 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97,
                    0x35, 0x6a, 0xd4 };

    private int[] state = new int[4], // a
            subKeys = new int[4], // k
            decryptKeys = new int[4];

    private boolean _initialised, _forEncryption;

    /**
     * Create an instance of the Noekeon encryption algorithm
     * and set some defaults
     */
    public NoekeonEngine() {
        _initialised = false;
    }

    public String getAlgorithmName() {
        return "Noekeon";
    }

    public int getBlockSize() {
        return genericSize;
    }

    /**
     * initialise
     *
     * @param forEncryption whether or not we are for encryption.
     * @param params the parameters required to set up the cipher.
     * @exception IllegalArgumentException if the params argument is
     * inappropriate.
     */
    public void init(boolean forEncryption, CipherParameters params) {
        if (!(params instanceof KeyParameter)) {
            throw new IllegalArgumentException(
                    "invalid parameter passed to Noekeon init - " + params.getClass().getName());
        }

        _forEncryption = forEncryption;
        _initialised = true;

        KeyParameter p = (KeyParameter) params;

        setKey(p.getKey());
    }

    public int processBlock(byte[] in, int inOff, byte[] out, int outOff) {
        if (!_initialised) {
            throw new IllegalStateException(getAlgorithmName() + " not initialised");
        }

        if ((inOff + genericSize) > in.length) {
            throw new DataLengthException("input buffer too short");
        }

        if ((outOff + genericSize) > out.length) {
            throw new OutputLengthException("output buffer too short");
        }

        return (_forEncryption) ? encryptBlock(in, inOff, out, outOff) : decryptBlock(in, inOff, out, outOff);
    }

    public void reset() {
    }

    /**
     * Re-key the cipher.
     * <p>
     * @param  key  the key to be used
     */
    private void setKey(byte[] key) {
        subKeys[0] = bytesToIntBig(key, 0);
        subKeys[1] = bytesToIntBig(key, 4);
        subKeys[2] = bytesToIntBig(key, 8);
        subKeys[3] = bytesToIntBig(key, 12);
    }

    private int encryptBlock(byte[] in, int inOff, byte[] out, int outOff) {
        state[0] = bytesToIntBig(in, inOff);
        state[1] = bytesToIntBig(in, inOff + 4);
        state[2] = bytesToIntBig(in, inOff + 8);
        state[3] = bytesToIntBig(in, inOff + 12);

        int i;
        for (i = 0; i < genericSize; i++) {
            state[0] ^= roundConstants[i];
            theta(state, subKeys);
            pi1(state);
            gamma(state);
            pi2(state);
        }

        state[0] ^= roundConstants[i];
        theta(state, subKeys);

        intToBytesBig(state[0], out, outOff);
        intToBytesBig(state[1], out, outOff + 4);
        intToBytesBig(state[2], out, outOff + 8);
        intToBytesBig(state[3], out, outOff + 12);

        return genericSize;
    }

    private int decryptBlock(byte[] in, int inOff, byte[] out, int outOff) {
        state[0] = bytesToIntBig(in, inOff);
        state[1] = bytesToIntBig(in, inOff + 4);
        state[2] = bytesToIntBig(in, inOff + 8);
        state[3] = bytesToIntBig(in, inOff + 12);

        System.arraycopy(subKeys, 0, decryptKeys, 0, subKeys.length);
        theta(decryptKeys, nullVector);

        int i;
        for (i = genericSize; i > 0; i--) {
            theta(state, decryptKeys);
            state[0] ^= roundConstants[i];
            pi1(state);
            gamma(state);
            pi2(state);
        }

        theta(state, decryptKeys);
        state[0] ^= roundConstants[i];

        intToBytesBig(state[0], out, outOff);
        intToBytesBig(state[1], out, outOff + 4);
        intToBytesBig(state[2], out, outOff + 8);
        intToBytesBig(state[3], out, outOff + 12);

        return genericSize;
    }

    private void gamma(int[] a) {
        a[1] ^= ~a[3] & ~a[2];
        a[0] ^= a[2] & a[1];

        int tmp = a[3];
        a[3] = a[0];
        a[0] = tmp;
        a[2] ^= a[0] ^ a[1] ^ a[3];

        a[1] ^= ~a[3] & ~a[2];
        a[0] ^= a[2] & a[1];
    }

    private void theta(int[] a, int[] k) {
        int tmp;

        tmp = a[0] ^ a[2];
        tmp ^= rotl(tmp, 8) ^ rotl(tmp, 24);
        a[1] ^= tmp;
        a[3] ^= tmp;

        for (int i = 0; i < 4; i++) {
            a[i] ^= k[i];
        }

        tmp = a[1] ^ a[3];
        tmp ^= rotl(tmp, 8) ^ rotl(tmp, 24);
        a[0] ^= tmp;
        a[2] ^= tmp;
    }

    private void pi1(int[] a) {
        a[1] = rotl(a[1], 1);
        a[2] = rotl(a[2], 5);
        a[3] = rotl(a[3], 2);
    }

    private void pi2(int[] a) {
        a[1] = rotl(a[1], 31);
        a[2] = rotl(a[2], 27);
        a[3] = rotl(a[3], 30);
    }

    // Helpers

    private int bytesToIntBig(byte[] in, int off) {
        return ((in[off++]) << 24) | ((in[off++] & 0xff) << 16) | ((in[off++] & 0xff) << 8) | (in[off] & 0xff);
    }

    private void intToBytesBig(int x, byte[] out, int off) {
        out[off++] = (byte) (x >>> 24);
        out[off++] = (byte) (x >>> 16);
        out[off++] = (byte) (x >>> 8);
        out[off] = (byte) x;
    }

    private int rotl(int x, int y) {
        return (x << y) | (x >>> (32 - y));
    }
}