Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package org.bouncycastle.crypto.engines;
  
Implementation of Martin Hell's, Thomas Johansson's and Willi Meier's stream cipher, Grain-128.
 
 public class Grain128Engine
     implements StreamCipher
 {

    
Constants
 
     private static final int STATE_SIZE = 4;

    
Variables to hold the state of the engine during encryption and decryption
 
     private byte[] workingKey;
     private byte[] workingIV;
     private byte[] out;
     private int[] lfsr;
     private int[] nfsr;
     private int output;
     private int index = 4;
 
     private boolean initialised = false;
 
     public String getAlgorithmName()
     {
         return "Grain-128";
     }

    
Initialize a Grain-128 cipher.

Parameters:
forEncryption Whether or not we are for encryption.
params The parameters required to set up the cipher.
Throws:
java.lang.IllegalArgumentException If the params argument is inappropriate.
 
     public void init(boolean forEncryptionCipherParameters params)
         throws IllegalArgumentException
     {
        
Grain encryption and decryption is completely symmetrical, so the 'forEncryption' is irrelevant.
 
         if (!(params instanceof ParametersWithIV))
         {
             throw new IllegalArgumentException(
                 "Grain-128 Init parameters must include an IV");
         }
 
         ParametersWithIV ivParams = (ParametersWithIV)params;
 
         byte[] iv = ivParams.getIV();
 
         if (iv == null || iv.length != 12)
         {
             throw new IllegalArgumentException(
                 "Grain-128  requires exactly 12 bytes of IV");
         }
 
         if (!(ivParams.getParameters() instanceof KeyParameter))
         {
             throw new IllegalArgumentException(
                 "Grain-128 Init parameters must include a key");
         }
 
         KeyParameter key = (KeyParameter)ivParams.getParameters();

        
Initialize variables.
 
          = new byte[key.getKey().length];
          = new byte[key.getKey().length];
          = new int[];
          = new int[];
          = new byte[4];
 
         System.arraycopy(iv, 0, , 0, iv.length);
         System.arraycopy(key.getKey(), 0, , 0, key.getKey().length);
 
         reset();
     }

    
256 clocks initialization phase.
 
     private void initGrain()
     {
        for (int i = 0; i < 8; i++)
        {
             = getOutput();
             = shift(getOutputNFSR() ^ [0] ^ );
             = shift(getOutputLFSR() ^ );
        }
         = true;
    }

    
Get output from non-linear function g(x).

Returns:
Output from NFSR.
    private int getOutputNFSR()
    {
        int b0 = [0];
        int b3 = [0] >>> 3 | [1] << 29;
        int b11 = [0] >>> 11 | [1] << 21;
        int b13 = [0] >>> 13 | [1] << 19;
        int b17 = [0] >>> 17 | [1] << 15;
        int b18 = [0] >>> 18 | [1] << 14;
        int b26 = [0] >>> 26 | [1] << 6;
        int b27 = [0] >>> 27 | [1] << 5;
        int b40 = [1] >>> 8 | [2] << 24;
        int b48 = [1] >>> 16 | [2] << 16;
        int b56 = [1] >>> 24 | [2] << 8;
        int b59 = [1] >>> 27 | [2] << 5;
        int b61 = [1] >>> 29 | [2] << 3;
        int b65 = [2] >>> 1 | [3] << 31;
        int b67 = [2] >>> 3 | [3] << 29;
        int b68 = [2] >>> 4 | [3] << 28;
        int b84 = [2] >>> 20 | [3] << 12;
        int b91 = [2] >>> 27 | [3] << 5;
        int b96 = [3];
        return b0 ^ b26 ^ b56 ^ b91 ^ b96 ^ b3 & b67 ^ b11 & b13 ^ b17 & b18
            ^ b27 & b59 ^ b40 & b48 ^ b61 & b65 ^ b68 & b84;
    }

    
Get output from linear function f(x).

Returns:
Output from LFSR.
    private int getOutputLFSR()
    {
        int s0 = [0];
        int s7 = [0] >>> 7 | [1] << 25;
        int s38 = [1] >>> 6 | [2] << 26;
        int s70 = [2] >>> 6 | [3] << 26;
        int s81 = [2] >>> 17 | [3] << 15;
        int s96 = [3];
        return s0 ^ s7 ^ s38 ^ s70 ^ s81 ^ s96;
    }

    
Get output from output function h(x).

Returns:
Output from h(x).
    private int getOutput()
    {
        int b2 = [0] >>> 2 | [1] << 30;
        int b12 = [0] >>> 12 | [1] << 20;
        int b15 = [0] >>> 15 | [1] << 17;
        int b36 = [1] >>> 4 | [2] << 28;
        int b45 = [1] >>> 13 | [2] << 19;
        int b64 = [2];
        int b73 = [2] >>> 9 | [3] << 23;
        int b89 = [2] >>> 25 | [3] << 7;
        int b95 = [2] >>> 31 | [3] << 1;
        int s8 = [0] >>> 8 | [1] << 24;
        int s13 = [0] >>> 13 | [1] << 19;
        int s20 = [0] >>> 20 | [1] << 12;
        int s42 = [1] >>> 10 | [2] << 22;
        int s60 = [1] >>> 28 | [2] << 4;
        int s79 = [2] >>> 15 | [3] << 17;
        int s93 = [2] >>> 29 | [3] << 3;
        int s95 = [2] >>> 31 | [3] << 1;
        return b12 & s8 ^ s13 & s20 ^ b95 & s42 ^ s60 & s79 ^ b12 & b95 & s95 ^ s93
            ^ b2 ^ b15 ^ b36 ^ b45 ^ b64 ^ b73 ^ b89;
    }

    
Shift array 32 bits and add val to index.length - 1.

Parameters:
array The array to shift.
val The value to shift in.
Returns:
The shifted array with val added to index.length - 1.
    private int[] shift(int[] arrayint val)
    {
        array[0] = array[1];
        array[1] = array[2];
        array[2] = array[3];
        array[3] = val;
        return array;
    }

    
Set keys, reset cipher.

Parameters:
keyBytes The key.
ivBytes The IV.
    private void setKey(byte[] keyBytesbyte[] ivBytes)
    {
        ivBytes[12] = (byte)0xFF;
        ivBytes[13] = (byte)0xFF;
        ivBytes[14] = (byte)0xFF;
        ivBytes[15] = (byte)0xFF;
         = keyBytes;
         = ivBytes;

        
Load NFSR and LFSR
        int j = 0;
        for (int i = 0; i < .i++)
        {
            [i] = (([j + 3]) << 24) | (([j + 2]) << 16)
                & 0x00FF0000 | (([j + 1]) << 8) & 0x0000FF00
                | (([j]) & 0x000000FF);
            [i] = (([j + 3]) << 24) | (([j + 2]) << 16)
                & 0x00FF0000 | (([j + 1]) << 8) & 0x0000FF00
                | (([j]) & 0x000000FF);
            j += 4;
        }
    }
    public int processBytes(byte[] inint inOffint lenbyte[] out,
                             int outOff)
        throws DataLengthException
    {
        if (!)
        {
            throw new IllegalStateException(getAlgorithmName()
                + " not initialised");
        }
        if ((inOff + len) > in.length)
        {
            throw new DataLengthException("input buffer too short");
        }
        if ((outOff + len) > out.length)
        {
            throw new OutputLengthException("output buffer too short");
        }
        for (int i = 0; i < leni++)
        {
            out[outOff + i] = (byte)(in[inOff + i] ^ getKeyStream());
        }
        return len;
    }
    public void reset()
    {
         = 4;
        setKey();
        initGrain();
    }

    
Run Grain one round(i.e. 32 bits).
    private void oneRound()
    {
         = getOutput();
        [0] = (byte);
        [1] = (byte)( >> 8);
        [2] = (byte)( >> 16);
        [3] = (byte)( >> 24);
         = shift(getOutputNFSR() ^ [0]);
         = shift(getOutputLFSR());
    }
    public byte returnByte(byte in)
    {
        if (!)
        {
            throw new IllegalStateException(getAlgorithmName()
                + " not initialised");
        }
        return (byte)(in ^ getKeyStream());
    }
    private byte getKeyStream()
    {
        if ( > 3)
        {
            oneRound();
             = 0;
        }
        return [++];
    }
New to GrepCode? Check out our FAQ X