Skip to content

Instantly share code, notes, and snippets.

@Demonslay335
Created July 23, 2020 16:52
Show Gist options
  • Save Demonslay335/1d8979072f8b53a002dab1ecb41c787a to your computer and use it in GitHub Desktop.
Save Demonslay335/1d8979072f8b53a002dab1ecb41c787a to your computer and use it in GitHub Desktop.
Sosemanuk cryptographic algorithm in C#.
// Adapted from https://www.seanet.com/~bugbee/crypto/sosemanuk/
public class Sosemanuk
{
public Sosemanuk(byte[] key, byte[] iv)
{
BuildAlphas();
SetKey(key);
SetIV(iv);
}
/*
* Internal cipher state.
*/
private int lfsr0, lfsr1, lfsr2, lfsr3, lfsr4;
private int lfsr5, lfsr6, lfsr7, lfsr8, lfsr9;
private int fsmR1, fsmR2;
/*
* The code internals for the SERPENT-derived functions have been
* semi-automatically generated, using a mixture of C, C
* preprocessor, vi macros and Forth. The base circuits for
* the SERPENT S-boxes have been published by Dag Arne Osvik
* ("Speeding up Serpent", at the 3rd AES Candidate Conference).
*/
/**
* Decode a 32-bit value from a buffer (little-endian).
*
* @param buf the input buffer
* @param off the input offset
* @return the decoded value
*/
private static int Decode32le(byte[] buf, int off)
{
return (buf[off] & 0xFF)
| ((buf[off + 1] & 0xFF) << 8)
| ((buf[off + 2] & 0xFF) << 16)
| ((buf[off + 3] & 0xFF) << 24);
}
/**
* Encode a 32-bit value into a buffer (little-endian).
*
* @param val the value to encode
* @param buf the output buffer
* @param off the output offset
*/
private static void Encode32le(int val, byte[] buf, int off)
{
buf[off] = (byte)val;
buf[off + 1] = (byte)(val >> 8);
buf[off + 2] = (byte)(val >> 16);
buf[off + 3] = (byte)(val >> 24);
}
/**
* Left-rotate a 32-bit value by some bit.
*
* @param val the value to rotate
* @param n the rotation count (between 1 and 31)
*/
private static int RotateLeft(int val, int n)
{
uint v = (uint)val;
return (int)((v << n) | (v >> (32 - n)));
}
/** Subkeys for Serpent24: 100 32-bit words. */
private int[] serpent24SubKeys = new int[100];
/**
* Set the private key. The key length must be between 1
* and 32 bytes.
*
* @param key the private key
*/
public void SetKey(byte[] key)
{
unchecked
{
if (key.Length < 1 || key.Length > 32)
throw new CryptographicException("bad key length: " + key.Length);
byte[] lkey;
if (key.Length == 32)
{
lkey = key;
}
else
{
lkey = new byte[32];
Buffer.BlockCopy(key, 0, lkey, 0, key.Length);
lkey[key.Length] = 0x01;
for (int j = key.Length + 1; j < lkey.Length; j++)
lkey[j] = 0x00;
}
int w0, w1, w2, w3, w4, w5, w6, w7;
int r0, r1, r2, r3, r4, tt;
int i = 0;
w0 = Decode32le(lkey, 0);
w1 = Decode32le(lkey, 4);
w2 = Decode32le(lkey, 8);
w3 = Decode32le(lkey, 12);
w4 = Decode32le(lkey, 16);
w5 = Decode32le(lkey, 20);
w6 = Decode32le(lkey, 24);
w7 = Decode32le(lkey, 28);
tt = w0 ^ w3 ^ w5 ^ w7 ^ ((int)0x9E3779B9 ^ (0));
w0 = RotateLeft(tt, 11);
tt = w1 ^ w4 ^ w6 ^ w0 ^ ((int)0x9E3779B9 ^ (0 + 1));
w1 = RotateLeft(tt, 11);
tt = w2 ^ w5 ^ w7 ^ w1 ^ ((int)0x9E3779B9 ^ (0 + 2));
w2 = RotateLeft(tt, 11);
tt = w3 ^ w6 ^ w0 ^ w2 ^ ((int)0x9E3779B9 ^ (0 + 3));
w3 = RotateLeft(tt, 11);
r0 = w0;
r1 = w1;
r2 = w2;
r3 = w3;
r4 = r0;
r0 |= r3;
r3 ^= r1;
r1 &= r4;
r4 ^= r2;
r2 ^= r3;
r3 &= r0;
r4 |= r1;
r3 ^= r4;
r0 ^= r1;
r4 &= r0;
r1 ^= r3;
r4 ^= r2;
r1 |= r0;
r1 ^= r2;
r0 ^= r3;
r2 = r1;
r1 |= r3;
r1 ^= r0;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r2;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r4;
tt = w4 ^ w7 ^ w1 ^ w3 ^ ((int)0x9E3779B9 ^ (4));
w4 = RotateLeft(tt, 11);
tt = w5 ^ w0 ^ w2 ^ w4 ^ ((int)0x9E3779B9 ^ (4 + 1));
w5 = RotateLeft(tt, 11);
tt = w6 ^ w1 ^ w3 ^ w5 ^ ((int)0x9E3779B9 ^ (4 + 2));
w6 = RotateLeft(tt, 11);
tt = w7 ^ w2 ^ w4 ^ w6 ^ ((int)0x9E3779B9 ^ (4 + 3));
w7 = RotateLeft(tt, 11);
r0 = w4;
r1 = w5;
r2 = w6;
r3 = w7;
r4 = r0;
r0 &= r2;
r0 ^= r3;
r2 ^= r1;
r2 ^= r0;
r3 |= r4;
r3 ^= r1;
r4 ^= r2;
r1 = r3;
r3 |= r4;
r3 ^= r0;
r0 &= r1;
r4 ^= r0;
r1 ^= r3;
r1 ^= r4;
r4 = ~r4;
serpent24SubKeys[i++] = r2;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r4;
tt = w0 ^ w3 ^ w5 ^ w7 ^ ((int)0x9E3779B9 ^ (8));
w0 = RotateLeft(tt, 11);
tt = w1 ^ w4 ^ w6 ^ w0 ^ ((int)0x9E3779B9 ^ (8 + 1));
w1 = RotateLeft(tt, 11);
tt = w2 ^ w5 ^ w7 ^ w1 ^ ((int)0x9E3779B9 ^ (8 + 2));
w2 = RotateLeft(tt, 11);
tt = w3 ^ w6 ^ w0 ^ w2 ^ ((int)0x9E3779B9 ^ (8 + 3));
w3 = RotateLeft(tt, 11);
r0 = w0;
r1 = w1;
r2 = w2;
r3 = w3;
r0 = ~r0;
r2 = ~r2;
r4 = r0;
r0 &= r1;
r2 ^= r0;
r0 |= r3;
r3 ^= r2;
r1 ^= r0;
r0 ^= r4;
r4 |= r1;
r1 ^= r3;
r2 |= r0;
r2 &= r4;
r0 ^= r1;
r1 &= r2;
r1 ^= r0;
r0 &= r2;
r0 ^= r4;
serpent24SubKeys[i++] = r2;
serpent24SubKeys[i++] = r0;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r1;
tt = w4 ^ w7 ^ w1 ^ w3 ^ ((int)0x9E3779B9 ^ (12));
w4 = RotateLeft(tt, 11);
tt = w5 ^ w0 ^ w2 ^ w4 ^ ((int)0x9E3779B9 ^ (12 + 1));
w5 = RotateLeft(tt, 11);
tt = w6 ^ w1 ^ w3 ^ w5 ^ ((int)0x9E3779B9 ^ (12 + 2));
w6 = RotateLeft(tt, 11);
tt = w7 ^ w2 ^ w4 ^ w6 ^ ((int)0x9E3779B9 ^ (12 + 3));
w7 = RotateLeft(tt, 11);
r0 = w4;
r1 = w5;
r2 = w6;
r3 = w7;
r3 ^= r0;
r4 = r1;
r1 &= r3;
r4 ^= r2;
r1 ^= r0;
r0 |= r3;
r0 ^= r4;
r4 ^= r3;
r3 ^= r2;
r2 |= r1;
r2 ^= r4;
r4 = ~r4;
r4 |= r1;
r1 ^= r3;
r1 ^= r4;
r3 |= r0;
r1 ^= r3;
r4 ^= r3;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r4;
serpent24SubKeys[i++] = r2;
serpent24SubKeys[i++] = r0;
tt = w0 ^ w3 ^ w5 ^ w7 ^ ((int)0x9E3779B9 ^ (16));
w0 = RotateLeft(tt, 11);
tt = w1 ^ w4 ^ w6 ^ w0 ^ ((int)0x9E3779B9 ^ (16 + 1));
w1 = RotateLeft(tt, 11);
tt = w2 ^ w5 ^ w7 ^ w1 ^ ((int)0x9E3779B9 ^ (16 + 2));
w2 = RotateLeft(tt, 11);
tt = w3 ^ w6 ^ w0 ^ w2 ^ ((int)0x9E3779B9 ^ (16 + 3));
w3 = RotateLeft(tt, 11);
r0 = w0;
r1 = w1;
r2 = w2;
r3 = w3;
r4 = r1;
r1 |= r2;
r1 ^= r3;
r4 ^= r2;
r2 ^= r1;
r3 |= r4;
r3 &= r0;
r4 ^= r2;
r3 ^= r1;
r1 |= r4;
r1 ^= r0;
r0 |= r4;
r0 ^= r2;
r1 ^= r4;
r2 ^= r1;
r1 &= r0;
r1 ^= r4;
r2 = ~r2;
r2 |= r0;
r4 ^= r2;
serpent24SubKeys[i++] = r4;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r0;
tt = w4 ^ w7 ^ w1 ^ w3 ^ ((int)0x9E3779B9 ^ (20));
w4 = RotateLeft(tt, 11);
tt = w5 ^ w0 ^ w2 ^ w4 ^ ((int)0x9E3779B9 ^ (20 + 1));
w5 = RotateLeft(tt, 11);
tt = w6 ^ w1 ^ w3 ^ w5 ^ ((int)0x9E3779B9 ^ (20 + 2));
w6 = RotateLeft(tt, 11);
tt = w7 ^ w2 ^ w4 ^ w6 ^ ((int)0x9E3779B9 ^ (20 + 3));
w7 = RotateLeft(tt, 11);
r0 = w4;
r1 = w5;
r2 = w6;
r3 = w7;
r2 = ~r2;
r4 = r3;
r3 &= r0;
r0 ^= r4;
r3 ^= r2;
r2 |= r4;
r1 ^= r3;
r2 ^= r0;
r0 |= r1;
r2 ^= r1;
r4 ^= r0;
r0 |= r3;
r0 ^= r2;
r4 ^= r3;
r4 ^= r0;
r3 = ~r3;
r2 &= r4;
r2 ^= r3;
serpent24SubKeys[i++] = r0;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r4;
serpent24SubKeys[i++] = r2;
tt = w0 ^ w3 ^ w5 ^ w7 ^ ((int)0x9E3779B9 ^ (24));
w0 = RotateLeft(tt, 11);
tt = w1 ^ w4 ^ w6 ^ w0 ^ ((int)0x9E3779B9 ^ (24 + 1));
w1 = RotateLeft(tt, 11);
tt = w2 ^ w5 ^ w7 ^ w1 ^ ((int)0x9E3779B9 ^ (24 + 2));
w2 = RotateLeft(tt, 11);
tt = w3 ^ w6 ^ w0 ^ w2 ^ ((int)0x9E3779B9 ^ (24 + 3));
w3 = RotateLeft(tt, 11);
r0 = w0;
r1 = w1;
r2 = w2;
r3 = w3;
r0 ^= r1;
r1 ^= r3;
r3 = ~r3;
r4 = r1;
r1 &= r0;
r2 ^= r3;
r1 ^= r2;
r2 |= r4;
r4 ^= r3;
r3 &= r1;
r3 ^= r0;
r4 ^= r1;
r4 ^= r2;
r2 ^= r0;
r0 &= r3;
r2 = ~r2;
r0 ^= r4;
r4 |= r3;
r2 ^= r4;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r0;
serpent24SubKeys[i++] = r2;
tt = w4 ^ w7 ^ w1 ^ w3 ^ ((int)0x9E3779B9 ^ (28));
w4 = RotateLeft(tt, 11);
tt = w5 ^ w0 ^ w2 ^ w4 ^ ((int)0x9E3779B9 ^ (28 + 1));
w5 = RotateLeft(tt, 11);
tt = w6 ^ w1 ^ w3 ^ w5 ^ ((int)0x9E3779B9 ^ (28 + 2));
w6 = RotateLeft(tt, 11);
tt = w7 ^ w2 ^ w4 ^ w6 ^ ((int)0x9E3779B9 ^ (28 + 3));
w7 = RotateLeft(tt, 11);
r0 = w4;
r1 = w5;
r2 = w6;
r3 = w7;
r1 ^= r3;
r3 = ~r3;
r2 ^= r3;
r3 ^= r0;
r4 = r1;
r1 &= r3;
r1 ^= r2;
r4 ^= r3;
r0 ^= r4;
r2 &= r4;
r2 ^= r0;
r0 &= r1;
r3 ^= r0;
r4 |= r1;
r4 ^= r0;
r0 |= r3;
r0 ^= r2;
r2 &= r3;
r0 = ~r0;
r4 ^= r2;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r4;
serpent24SubKeys[i++] = r0;
serpent24SubKeys[i++] = r3;
tt = w0 ^ w3 ^ w5 ^ w7 ^ ((int)0x9E3779B9 ^ (32));
w0 = RotateLeft(tt, 11);
tt = w1 ^ w4 ^ w6 ^ w0 ^ ((int)0x9E3779B9 ^ (32 + 1));
w1 = RotateLeft(tt, 11);
tt = w2 ^ w5 ^ w7 ^ w1 ^ ((int)0x9E3779B9 ^ (32 + 2));
w2 = RotateLeft(tt, 11);
tt = w3 ^ w6 ^ w0 ^ w2 ^ ((int)0x9E3779B9 ^ (32 + 3));
w3 = RotateLeft(tt, 11);
r0 = w0;
r1 = w1;
r2 = w2;
r3 = w3;
r4 = r0;
r0 |= r3;
r3 ^= r1;
r1 &= r4;
r4 ^= r2;
r2 ^= r3;
r3 &= r0;
r4 |= r1;
r3 ^= r4;
r0 ^= r1;
r4 &= r0;
r1 ^= r3;
r4 ^= r2;
r1 |= r0;
r1 ^= r2;
r0 ^= r3;
r2 = r1;
r1 |= r3;
r1 ^= r0;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r2;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r4;
tt = w4 ^ w7 ^ w1 ^ w3 ^ ((int)0x9E3779B9 ^ (36));
w4 = RotateLeft(tt, 11);
tt = w5 ^ w0 ^ w2 ^ w4 ^ ((int)0x9E3779B9 ^ (36 + 1));
w5 = RotateLeft(tt, 11);
tt = w6 ^ w1 ^ w3 ^ w5 ^ ((int)0x9E3779B9 ^ (36 + 2));
w6 = RotateLeft(tt, 11);
tt = w7 ^ w2 ^ w4 ^ w6 ^ ((int)0x9E3779B9 ^ (36 + 3));
w7 = RotateLeft(tt, 11);
r0 = w4;
r1 = w5;
r2 = w6;
r3 = w7;
r4 = r0;
r0 &= r2;
r0 ^= r3;
r2 ^= r1;
r2 ^= r0;
r3 |= r4;
r3 ^= r1;
r4 ^= r2;
r1 = r3;
r3 |= r4;
r3 ^= r0;
r0 &= r1;
r4 ^= r0;
r1 ^= r3;
r1 ^= r4;
r4 = ~r4;
serpent24SubKeys[i++] = r2;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r4;
tt = w0 ^ w3 ^ w5 ^ w7 ^ ((int)0x9E3779B9 ^ (40));
w0 = RotateLeft(tt, 11);
tt = w1 ^ w4 ^ w6 ^ w0 ^ ((int)0x9E3779B9 ^ (40 + 1));
w1 = RotateLeft(tt, 11);
tt = w2 ^ w5 ^ w7 ^ w1 ^ ((int)0x9E3779B9 ^ (40 + 2));
w2 = RotateLeft(tt, 11);
tt = w3 ^ w6 ^ w0 ^ w2 ^ ((int)0x9E3779B9 ^ (40 + 3));
w3 = RotateLeft(tt, 11);
r0 = w0;
r1 = w1;
r2 = w2;
r3 = w3;
r0 = ~r0;
r2 = ~r2;
r4 = r0;
r0 &= r1;
r2 ^= r0;
r0 |= r3;
r3 ^= r2;
r1 ^= r0;
r0 ^= r4;
r4 |= r1;
r1 ^= r3;
r2 |= r0;
r2 &= r4;
r0 ^= r1;
r1 &= r2;
r1 ^= r0;
r0 &= r2;
r0 ^= r4;
serpent24SubKeys[i++] = r2;
serpent24SubKeys[i++] = r0;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r1;
tt = w4 ^ w7 ^ w1 ^ w3 ^ ((int)0x9E3779B9 ^ (44));
w4 = RotateLeft(tt, 11);
tt = w5 ^ w0 ^ w2 ^ w4 ^ ((int)0x9E3779B9 ^ (44 + 1));
w5 = RotateLeft(tt, 11);
tt = w6 ^ w1 ^ w3 ^ w5 ^ ((int)0x9E3779B9 ^ (44 + 2));
w6 = RotateLeft(tt, 11);
tt = w7 ^ w2 ^ w4 ^ w6 ^ ((int)0x9E3779B9 ^ (44 + 3));
w7 = RotateLeft(tt, 11);
r0 = w4;
r1 = w5;
r2 = w6;
r3 = w7;
r3 ^= r0;
r4 = r1;
r1 &= r3;
r4 ^= r2;
r1 ^= r0;
r0 |= r3;
r0 ^= r4;
r4 ^= r3;
r3 ^= r2;
r2 |= r1;
r2 ^= r4;
r4 = ~r4;
r4 |= r1;
r1 ^= r3;
r1 ^= r4;
r3 |= r0;
r1 ^= r3;
r4 ^= r3;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r4;
serpent24SubKeys[i++] = r2;
serpent24SubKeys[i++] = r0;
tt = w0 ^ w3 ^ w5 ^ w7 ^ ((int)0x9E3779B9 ^ (48));
w0 = RotateLeft(tt, 11);
tt = w1 ^ w4 ^ w6 ^ w0 ^ ((int)0x9E3779B9 ^ (48 + 1));
w1 = RotateLeft(tt, 11);
tt = w2 ^ w5 ^ w7 ^ w1 ^ ((int)0x9E3779B9 ^ (48 + 2));
w2 = RotateLeft(tt, 11);
tt = w3 ^ w6 ^ w0 ^ w2 ^ ((int)0x9E3779B9 ^ (48 + 3));
w3 = RotateLeft(tt, 11);
r0 = w0;
r1 = w1;
r2 = w2;
r3 = w3;
r4 = r1;
r1 |= r2;
r1 ^= r3;
r4 ^= r2;
r2 ^= r1;
r3 |= r4;
r3 &= r0;
r4 ^= r2;
r3 ^= r1;
r1 |= r4;
r1 ^= r0;
r0 |= r4;
r0 ^= r2;
r1 ^= r4;
r2 ^= r1;
r1 &= r0;
r1 ^= r4;
r2 = ~r2;
r2 |= r0;
r4 ^= r2;
serpent24SubKeys[i++] = r4;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r0;
tt = w4 ^ w7 ^ w1 ^ w3 ^ ((int)0x9E3779B9 ^ (52));
w4 = RotateLeft(tt, 11);
tt = w5 ^ w0 ^ w2 ^ w4 ^ ((int)0x9E3779B9 ^ (52 + 1));
w5 = RotateLeft(tt, 11);
tt = w6 ^ w1 ^ w3 ^ w5 ^ ((int)0x9E3779B9 ^ (52 + 2));
w6 = RotateLeft(tt, 11);
tt = w7 ^ w2 ^ w4 ^ w6 ^ ((int)0x9E3779B9 ^ (52 + 3));
w7 = RotateLeft(tt, 11);
r0 = w4;
r1 = w5;
r2 = w6;
r3 = w7;
r2 = ~r2;
r4 = r3;
r3 &= r0;
r0 ^= r4;
r3 ^= r2;
r2 |= r4;
r1 ^= r3;
r2 ^= r0;
r0 |= r1;
r2 ^= r1;
r4 ^= r0;
r0 |= r3;
r0 ^= r2;
r4 ^= r3;
r4 ^= r0;
r3 = ~r3;
r2 &= r4;
r2 ^= r3;
serpent24SubKeys[i++] = r0;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r4;
serpent24SubKeys[i++] = r2;
tt = w0 ^ w3 ^ w5 ^ w7 ^ ((int)0x9E3779B9 ^ (56));
w0 = RotateLeft(tt, 11);
tt = w1 ^ w4 ^ w6 ^ w0 ^ ((int)0x9E3779B9 ^ (56 + 1));
w1 = RotateLeft(tt, 11);
tt = w2 ^ w5 ^ w7 ^ w1 ^ ((int)0x9E3779B9 ^ (56 + 2));
w2 = RotateLeft(tt, 11);
tt = w3 ^ w6 ^ w0 ^ w2 ^ ((int)0x9E3779B9 ^ (56 + 3));
w3 = RotateLeft(tt, 11);
r0 = w0;
r1 = w1;
r2 = w2;
r3 = w3;
r0 ^= r1;
r1 ^= r3;
r3 = ~r3;
r4 = r1;
r1 &= r0;
r2 ^= r3;
r1 ^= r2;
r2 |= r4;
r4 ^= r3;
r3 &= r1;
r3 ^= r0;
r4 ^= r1;
r4 ^= r2;
r2 ^= r0;
r0 &= r3;
r2 = ~r2;
r0 ^= r4;
r4 |= r3;
r2 ^= r4;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r0;
serpent24SubKeys[i++] = r2;
tt = w4 ^ w7 ^ w1 ^ w3 ^ ((int)0x9E3779B9 ^ (60));
w4 = RotateLeft(tt, 11);
tt = w5 ^ w0 ^ w2 ^ w4 ^ ((int)0x9E3779B9 ^ (60 + 1));
w5 = RotateLeft(tt, 11);
tt = w6 ^ w1 ^ w3 ^ w5 ^ ((int)0x9E3779B9 ^ (60 + 2));
w6 = RotateLeft(tt, 11);
tt = w7 ^ w2 ^ w4 ^ w6 ^ ((int)0x9E3779B9 ^ (60 + 3));
w7 = RotateLeft(tt, 11);
r0 = w4;
r1 = w5;
r2 = w6;
r3 = w7;
r1 ^= r3;
r3 = ~r3;
r2 ^= r3;
r3 ^= r0;
r4 = r1;
r1 &= r3;
r1 ^= r2;
r4 ^= r3;
r0 ^= r4;
r2 &= r4;
r2 ^= r0;
r0 &= r1;
r3 ^= r0;
r4 |= r1;
r4 ^= r0;
r0 |= r3;
r0 ^= r2;
r2 &= r3;
r0 = ~r0;
r4 ^= r2;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r4;
serpent24SubKeys[i++] = r0;
serpent24SubKeys[i++] = r3;
tt = w0 ^ w3 ^ w5 ^ w7 ^ ((int)0x9E3779B9 ^ (64));
w0 = RotateLeft(tt, 11);
tt = w1 ^ w4 ^ w6 ^ w0 ^ ((int)0x9E3779B9 ^ (64 + 1));
w1 = RotateLeft(tt, 11);
tt = w2 ^ w5 ^ w7 ^ w1 ^ ((int)0x9E3779B9 ^ (64 + 2));
w2 = RotateLeft(tt, 11);
tt = w3 ^ w6 ^ w0 ^ w2 ^ ((int)0x9E3779B9 ^ (64 + 3));
w3 = RotateLeft(tt, 11);
r0 = w0;
r1 = w1;
r2 = w2;
r3 = w3;
r4 = r0;
r0 |= r3;
r3 ^= r1;
r1 &= r4;
r4 ^= r2;
r2 ^= r3;
r3 &= r0;
r4 |= r1;
r3 ^= r4;
r0 ^= r1;
r4 &= r0;
r1 ^= r3;
r4 ^= r2;
r1 |= r0;
r1 ^= r2;
r0 ^= r3;
r2 = r1;
r1 |= r3;
r1 ^= r0;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r2;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r4;
tt = w4 ^ w7 ^ w1 ^ w3 ^ ((int)0x9E3779B9 ^ (68));
w4 = RotateLeft(tt, 11);
tt = w5 ^ w0 ^ w2 ^ w4 ^ ((int)0x9E3779B9 ^ (68 + 1));
w5 = RotateLeft(tt, 11);
tt = w6 ^ w1 ^ w3 ^ w5 ^ ((int)0x9E3779B9 ^ (68 + 2));
w6 = RotateLeft(tt, 11);
tt = w7 ^ w2 ^ w4 ^ w6 ^ ((int)0x9E3779B9 ^ (68 + 3));
w7 = RotateLeft(tt, 11);
r0 = w4;
r1 = w5;
r2 = w6;
r3 = w7;
r4 = r0;
r0 &= r2;
r0 ^= r3;
r2 ^= r1;
r2 ^= r0;
r3 |= r4;
r3 ^= r1;
r4 ^= r2;
r1 = r3;
r3 |= r4;
r3 ^= r0;
r0 &= r1;
r4 ^= r0;
r1 ^= r3;
r1 ^= r4;
r4 = ~r4;
serpent24SubKeys[i++] = r2;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r4;
tt = w0 ^ w3 ^ w5 ^ w7 ^ ((int)0x9E3779B9 ^ (72));
w0 = RotateLeft(tt, 11);
tt = w1 ^ w4 ^ w6 ^ w0 ^ ((int)0x9E3779B9 ^ (72 + 1));
w1 = RotateLeft(tt, 11);
tt = w2 ^ w5 ^ w7 ^ w1 ^ ((int)0x9E3779B9 ^ (72 + 2));
w2 = RotateLeft(tt, 11);
tt = w3 ^ w6 ^ w0 ^ w2 ^ ((int)0x9E3779B9 ^ (72 + 3));
w3 = RotateLeft(tt, 11);
r0 = w0;
r1 = w1;
r2 = w2;
r3 = w3;
r0 = ~r0;
r2 = ~r2;
r4 = r0;
r0 &= r1;
r2 ^= r0;
r0 |= r3;
r3 ^= r2;
r1 ^= r0;
r0 ^= r4;
r4 |= r1;
r1 ^= r3;
r2 |= r0;
r2 &= r4;
r0 ^= r1;
r1 &= r2;
r1 ^= r0;
r0 &= r2;
r0 ^= r4;
serpent24SubKeys[i++] = r2;
serpent24SubKeys[i++] = r0;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r1;
tt = w4 ^ w7 ^ w1 ^ w3 ^ ((int)0x9E3779B9 ^ (76));
w4 = RotateLeft(tt, 11);
tt = w5 ^ w0 ^ w2 ^ w4 ^ ((int)0x9E3779B9 ^ (76 + 1));
w5 = RotateLeft(tt, 11);
tt = w6 ^ w1 ^ w3 ^ w5 ^ ((int)0x9E3779B9 ^ (76 + 2));
w6 = RotateLeft(tt, 11);
tt = w7 ^ w2 ^ w4 ^ w6 ^ ((int)0x9E3779B9 ^ (76 + 3));
w7 = RotateLeft(tt, 11);
r0 = w4;
r1 = w5;
r2 = w6;
r3 = w7;
r3 ^= r0;
r4 = r1;
r1 &= r3;
r4 ^= r2;
r1 ^= r0;
r0 |= r3;
r0 ^= r4;
r4 ^= r3;
r3 ^= r2;
r2 |= r1;
r2 ^= r4;
r4 = ~r4;
r4 |= r1;
r1 ^= r3;
r1 ^= r4;
r3 |= r0;
r1 ^= r3;
r4 ^= r3;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r4;
serpent24SubKeys[i++] = r2;
serpent24SubKeys[i++] = r0;
tt = w0 ^ w3 ^ w5 ^ w7 ^ ((int)0x9E3779B9 ^ (80));
w0 = RotateLeft(tt, 11);
tt = w1 ^ w4 ^ w6 ^ w0 ^ ((int)0x9E3779B9 ^ (80 + 1));
w1 = RotateLeft(tt, 11);
tt = w2 ^ w5 ^ w7 ^ w1 ^ ((int)0x9E3779B9 ^ (80 + 2));
w2 = RotateLeft(tt, 11);
tt = w3 ^ w6 ^ w0 ^ w2 ^ ((int)0x9E3779B9 ^ (80 + 3));
w3 = RotateLeft(tt, 11);
r0 = w0;
r1 = w1;
r2 = w2;
r3 = w3;
r4 = r1;
r1 |= r2;
r1 ^= r3;
r4 ^= r2;
r2 ^= r1;
r3 |= r4;
r3 &= r0;
r4 ^= r2;
r3 ^= r1;
r1 |= r4;
r1 ^= r0;
r0 |= r4;
r0 ^= r2;
r1 ^= r4;
r2 ^= r1;
r1 &= r0;
r1 ^= r4;
r2 = ~r2;
r2 |= r0;
r4 ^= r2;
serpent24SubKeys[i++] = r4;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r0;
tt = w4 ^ w7 ^ w1 ^ w3 ^ ((int)0x9E3779B9 ^ (84));
w4 = RotateLeft(tt, 11);
tt = w5 ^ w0 ^ w2 ^ w4 ^ ((int)0x9E3779B9 ^ (84 + 1));
w5 = RotateLeft(tt, 11);
tt = w6 ^ w1 ^ w3 ^ w5 ^ ((int)0x9E3779B9 ^ (84 + 2));
w6 = RotateLeft(tt, 11);
tt = w7 ^ w2 ^ w4 ^ w6 ^ ((int)0x9E3779B9 ^ (84 + 3));
w7 = RotateLeft(tt, 11);
r0 = w4;
r1 = w5;
r2 = w6;
r3 = w7;
r2 = ~r2;
r4 = r3;
r3 &= r0;
r0 ^= r4;
r3 ^= r2;
r2 |= r4;
r1 ^= r3;
r2 ^= r0;
r0 |= r1;
r2 ^= r1;
r4 ^= r0;
r0 |= r3;
r0 ^= r2;
r4 ^= r3;
r4 ^= r0;
r3 = ~r3;
r2 &= r4;
r2 ^= r3;
serpent24SubKeys[i++] = r0;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r4;
serpent24SubKeys[i++] = r2;
tt = w0 ^ w3 ^ w5 ^ w7 ^ ((int)0x9E3779B9 ^ (88));
w0 = RotateLeft(tt, 11);
tt = w1 ^ w4 ^ w6 ^ w0 ^ ((int)0x9E3779B9 ^ (88 + 1));
w1 = RotateLeft(tt, 11);
tt = w2 ^ w5 ^ w7 ^ w1 ^ ((int)0x9E3779B9 ^ (88 + 2));
w2 = RotateLeft(tt, 11);
tt = w3 ^ w6 ^ w0 ^ w2 ^ ((int)0x9E3779B9 ^ (88 + 3));
w3 = RotateLeft(tt, 11);
r0 = w0;
r1 = w1;
r2 = w2;
r3 = w3;
r0 ^= r1;
r1 ^= r3;
r3 = ~r3;
r4 = r1;
r1 &= r0;
r2 ^= r3;
r1 ^= r2;
r2 |= r4;
r4 ^= r3;
r3 &= r1;
r3 ^= r0;
r4 ^= r1;
r4 ^= r2;
r2 ^= r0;
r0 &= r3;
r2 = ~r2;
r0 ^= r4;
r4 |= r3;
r2 ^= r4;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r0;
serpent24SubKeys[i++] = r2;
tt = w4 ^ w7 ^ w1 ^ w3 ^ ((int)0x9E3779B9 ^ (92));
w4 = RotateLeft(tt, 11);
tt = w5 ^ w0 ^ w2 ^ w4 ^ ((int)0x9E3779B9 ^ (92 + 1));
w5 = RotateLeft(tt, 11);
tt = w6 ^ w1 ^ w3 ^ w5 ^ ((int)0x9E3779B9 ^ (92 + 2));
w6 = RotateLeft(tt, 11);
tt = w7 ^ w2 ^ w4 ^ w6 ^ ((int)0x9E3779B9 ^ (92 + 3));
w7 = RotateLeft(tt, 11);
r0 = w4;
r1 = w5;
r2 = w6;
r3 = w7;
r1 ^= r3;
r3 = ~r3;
r2 ^= r3;
r3 ^= r0;
r4 = r1;
r1 &= r3;
r1 ^= r2;
r4 ^= r3;
r0 ^= r4;
r2 &= r4;
r2 ^= r0;
r0 &= r1;
r3 ^= r0;
r4 |= r1;
r4 ^= r0;
r0 |= r3;
r0 ^= r2;
r2 &= r3;
r0 = ~r0;
r4 ^= r2;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r4;
serpent24SubKeys[i++] = r0;
serpent24SubKeys[i++] = r3;
tt = w0 ^ w3 ^ w5 ^ w7 ^ ((int)0x9E3779B9 ^ (96));
w0 = RotateLeft(tt, 11);
tt = w1 ^ w4 ^ w6 ^ w0 ^ ((int)0x9E3779B9 ^ (96 + 1));
w1 = RotateLeft(tt, 11);
tt = w2 ^ w5 ^ w7 ^ w1 ^ ((int)0x9E3779B9 ^ (96 + 2));
w2 = RotateLeft(tt, 11);
tt = w3 ^ w6 ^ w0 ^ w2 ^ ((int)0x9E3779B9 ^ (96 + 3));
w3 = RotateLeft(tt, 11);
r0 = w0;
r1 = w1;
r2 = w2;
r3 = w3;
r4 = r0;
r0 |= r3;
r3 ^= r1;
r1 &= r4;
r4 ^= r2;
r2 ^= r3;
r3 &= r0;
r4 |= r1;
r3 ^= r4;
r0 ^= r1;
r4 &= r0;
r1 ^= r3;
r4 ^= r2;
r1 |= r0;
r1 ^= r2;
r0 ^= r3;
r2 = r1;
r1 |= r3;
r1 ^= r0;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r2;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r4;
}
}
/**
* Set the IV. The IV length must lie between 0 and 16 (inclusive).
* <code>null</code> is accepted, and yields the same result
* than an IV of length 0.
*
* @param iv the IV (or <code>null</code>)
*/
public void SetIV(byte[] iv)
{
if (iv == null)
iv = new byte[0];
if (iv.Length > 16)
throw new CryptographicException("bad IV length: " + iv.Length);
byte[] piv;
if (iv.Length == 16)
{
piv = iv;
}
else
{
piv = new byte[16];
Buffer.BlockCopy(iv, 0, piv, 0, iv.Length);
for (int i = iv.Length; i < piv.Length; i++)
piv[i] = 0x00;
}
int r0, r1, r2, r3, r4;
r0 = Decode32le(piv, 0);
r1 = Decode32le(piv, 4);
r2 = Decode32le(piv, 8);
r3 = Decode32le(piv, 12);
r0 ^= serpent24SubKeys[0];
r1 ^= serpent24SubKeys[0 + 1];
r2 ^= serpent24SubKeys[0 + 2];
r3 ^= serpent24SubKeys[0 + 3];
r3 ^= r0;
r4 = r1;
r1 &= r3;
r4 ^= r2;
r1 ^= r0;
r0 |= r3;
r0 ^= r4;
r4 ^= r3;
r3 ^= r2;
r2 |= r1;
r2 ^= r4;
r4 = ~r4;
r4 |= r1;
r1 ^= r3;
r1 ^= r4;
r3 |= r0;
r1 ^= r3;
r4 ^= r3;
r1 = RotateLeft(r1, 13);
r2 = RotateLeft(r2, 3);
r4 = r4 ^ r1 ^ r2;
r0 = r0 ^ r2 ^ (r1 << 3);
r4 = RotateLeft(r4, 1);
r0 = RotateLeft(r0, 7);
r1 = r1 ^ r4 ^ r0;
r2 = r2 ^ r0 ^ (r4 << 7);
r1 = RotateLeft(r1, 5);
r2 = RotateLeft(r2, 22);
r1 ^= serpent24SubKeys[4];
r4 ^= serpent24SubKeys[4 + 1];
r2 ^= serpent24SubKeys[4 + 2];
r0 ^= serpent24SubKeys[4 + 3];
r1 = ~r1;
r2 = ~r2;
r3 = r1;
r1 &= r4;
r2 ^= r1;
r1 |= r0;
r0 ^= r2;
r4 ^= r1;
r1 ^= r3;
r3 |= r4;
r4 ^= r0;
r2 |= r1;
r2 &= r3;
r1 ^= r4;
r4 &= r2;
r4 ^= r1;
r1 &= r2;
r1 ^= r3;
r2 = RotateLeft(r2, 13);
r0 = RotateLeft(r0, 3);
r1 = r1 ^ r2 ^ r0;
r4 = r4 ^ r0 ^ (r2 << 3);
r1 = RotateLeft(r1, 1);
r4 = RotateLeft(r4, 7);
r2 = r2 ^ r1 ^ r4;
r0 = r0 ^ r4 ^ (r1 << 7);
r2 = RotateLeft(r2, 5);
r0 = RotateLeft(r0, 22);
r2 ^= serpent24SubKeys[8];
r1 ^= serpent24SubKeys[8 + 1];
r0 ^= serpent24SubKeys[8 + 2];
r4 ^= serpent24SubKeys[8 + 3];
r3 = r2;
r2 &= r0;
r2 ^= r4;
r0 ^= r1;
r0 ^= r2;
r4 |= r3;
r4 ^= r1;
r3 ^= r0;
r1 = r4;
r4 |= r3;
r4 ^= r2;
r2 &= r1;
r3 ^= r2;
r1 ^= r4;
r1 ^= r3;
r3 = ~r3;
r0 = RotateLeft(r0, 13);
r1 = RotateLeft(r1, 3);
r4 = r4 ^ r0 ^ r1;
r3 = r3 ^ r1 ^ (r0 << 3);
r4 = RotateLeft(r4, 1);
r3 = RotateLeft(r3, 7);
r0 = r0 ^ r4 ^ r3;
r1 = r1 ^ r3 ^ (r4 << 7);
r0 = RotateLeft(r0, 5);
r1 = RotateLeft(r1, 22);
r0 ^= serpent24SubKeys[12];
r4 ^= serpent24SubKeys[12 + 1];
r1 ^= serpent24SubKeys[12 + 2];
r3 ^= serpent24SubKeys[12 + 3];
r2 = r0;
r0 |= r3;
r3 ^= r4;
r4 &= r2;
r2 ^= r1;
r1 ^= r3;
r3 &= r0;
r2 |= r4;
r3 ^= r2;
r0 ^= r4;
r2 &= r0;
r4 ^= r3;
r2 ^= r1;
r4 |= r0;
r4 ^= r1;
r0 ^= r3;
r1 = r4;
r4 |= r3;
r4 ^= r0;
r4 = RotateLeft(r4, 13);
r3 = RotateLeft(r3, 3);
r1 = r1 ^ r4 ^ r3;
r2 = r2 ^ r3 ^ (r4 << 3);
r1 = RotateLeft(r1, 1);
r2 = RotateLeft(r2, 7);
r4 = r4 ^ r1 ^ r2;
r3 = r3 ^ r2 ^ (r1 << 7);
r4 = RotateLeft(r4, 5);
r3 = RotateLeft(r3, 22);
r4 ^= serpent24SubKeys[16];
r1 ^= serpent24SubKeys[16 + 1];
r3 ^= serpent24SubKeys[16 + 2];
r2 ^= serpent24SubKeys[16 + 3];
r1 ^= r2;
r2 = ~r2;
r3 ^= r2;
r2 ^= r4;
r0 = r1;
r1 &= r2;
r1 ^= r3;
r0 ^= r2;
r4 ^= r0;
r3 &= r0;
r3 ^= r4;
r4 &= r1;
r2 ^= r4;
r0 |= r1;
r0 ^= r4;
r4 |= r2;
r4 ^= r3;
r3 &= r2;
r4 = ~r4;
r0 ^= r3;
r1 = RotateLeft(r1, 13);
r4 = RotateLeft(r4, 3);
r0 = r0 ^ r1 ^ r4;
r2 = r2 ^ r4 ^ (r1 << 3);
r0 = RotateLeft(r0, 1);
r2 = RotateLeft(r2, 7);
r1 = r1 ^ r0 ^ r2;
r4 = r4 ^ r2 ^ (r0 << 7);
r1 = RotateLeft(r1, 5);
r4 = RotateLeft(r4, 22);
r1 ^= serpent24SubKeys[20];
r0 ^= serpent24SubKeys[20 + 1];
r4 ^= serpent24SubKeys[20 + 2];
r2 ^= serpent24SubKeys[20 + 3];
r1 ^= r0;
r0 ^= r2;
r2 = ~r2;
r3 = r0;
r0 &= r1;
r4 ^= r2;
r0 ^= r4;
r4 |= r3;
r3 ^= r2;
r2 &= r0;
r2 ^= r1;
r3 ^= r0;
r3 ^= r4;
r4 ^= r1;
r1 &= r2;
r4 = ~r4;
r1 ^= r3;
r3 |= r2;
r4 ^= r3;
r0 = RotateLeft(r0, 13);
r1 = RotateLeft(r1, 3);
r2 = r2 ^ r0 ^ r1;
r4 = r4 ^ r1 ^ (r0 << 3);
r2 = RotateLeft(r2, 1);
r4 = RotateLeft(r4, 7);
r0 = r0 ^ r2 ^ r4;
r1 = r1 ^ r4 ^ (r2 << 7);
r0 = RotateLeft(r0, 5);
r1 = RotateLeft(r1, 22);
r0 ^= serpent24SubKeys[24];
r2 ^= serpent24SubKeys[24 + 1];
r1 ^= serpent24SubKeys[24 + 2];
r4 ^= serpent24SubKeys[24 + 3];
r1 = ~r1;
r3 = r4;
r4 &= r0;
r0 ^= r3;
r4 ^= r1;
r1 |= r3;
r2 ^= r4;
r1 ^= r0;
r0 |= r2;
r1 ^= r2;
r3 ^= r0;
r0 |= r4;
r0 ^= r1;
r3 ^= r4;
r3 ^= r0;
r4 = ~r4;
r1 &= r3;
r1 ^= r4;
r0 = RotateLeft(r0, 13);
r3 = RotateLeft(r3, 3);
r2 = r2 ^ r0 ^ r3;
r1 = r1 ^ r3 ^ (r0 << 3);
r2 = RotateLeft(r2, 1);
r1 = RotateLeft(r1, 7);
r0 = r0 ^ r2 ^ r1;
r3 = r3 ^ r1 ^ (r2 << 7);
r0 = RotateLeft(r0, 5);
r3 = RotateLeft(r3, 22);
r0 ^= serpent24SubKeys[28];
r2 ^= serpent24SubKeys[28 + 1];
r3 ^= serpent24SubKeys[28 + 2];
r1 ^= serpent24SubKeys[28 + 3];
r4 = r2;
r2 |= r3;
r2 ^= r1;
r4 ^= r3;
r3 ^= r2;
r1 |= r4;
r1 &= r0;
r4 ^= r3;
r1 ^= r2;
r2 |= r4;
r2 ^= r0;
r0 |= r4;
r0 ^= r3;
r2 ^= r4;
r3 ^= r2;
r2 &= r0;
r2 ^= r4;
r3 = ~r3;
r3 |= r0;
r4 ^= r3;
r4 = RotateLeft(r4, 13);
r2 = RotateLeft(r2, 3);
r1 = r1 ^ r4 ^ r2;
r0 = r0 ^ r2 ^ (r4 << 3);
r1 = RotateLeft(r1, 1);
r0 = RotateLeft(r0, 7);
r4 = r4 ^ r1 ^ r0;
r2 = r2 ^ r0 ^ (r1 << 7);
r4 = RotateLeft(r4, 5);
r2 = RotateLeft(r2, 22);
r4 ^= serpent24SubKeys[32];
r1 ^= serpent24SubKeys[32 + 1];
r2 ^= serpent24SubKeys[32 + 2];
r0 ^= serpent24SubKeys[32 + 3];
r0 ^= r4;
r3 = r1;
r1 &= r0;
r3 ^= r2;
r1 ^= r4;
r4 |= r0;
r4 ^= r3;
r3 ^= r0;
r0 ^= r2;
r2 |= r1;
r2 ^= r3;
r3 = ~r3;
r3 |= r1;
r1 ^= r0;
r1 ^= r3;
r0 |= r4;
r1 ^= r0;
r3 ^= r0;
r1 = RotateLeft(r1, 13);
r2 = RotateLeft(r2, 3);
r3 = r3 ^ r1 ^ r2;
r4 = r4 ^ r2 ^ (r1 << 3);
r3 = RotateLeft(r3, 1);
r4 = RotateLeft(r4, 7);
r1 = r1 ^ r3 ^ r4;
r2 = r2 ^ r4 ^ (r3 << 7);
r1 = RotateLeft(r1, 5);
r2 = RotateLeft(r2, 22);
r1 ^= serpent24SubKeys[36];
r3 ^= serpent24SubKeys[36 + 1];
r2 ^= serpent24SubKeys[36 + 2];
r4 ^= serpent24SubKeys[36 + 3];
r1 = ~r1;
r2 = ~r2;
r0 = r1;
r1 &= r3;
r2 ^= r1;
r1 |= r4;
r4 ^= r2;
r3 ^= r1;
r1 ^= r0;
r0 |= r3;
r3 ^= r4;
r2 |= r1;
r2 &= r0;
r1 ^= r3;
r3 &= r2;
r3 ^= r1;
r1 &= r2;
r1 ^= r0;
r2 = RotateLeft(r2, 13);
r4 = RotateLeft(r4, 3);
r1 = r1 ^ r2 ^ r4;
r3 = r3 ^ r4 ^ (r2 << 3);
r1 = RotateLeft(r1, 1);
r3 = RotateLeft(r3, 7);
r2 = r2 ^ r1 ^ r3;
r4 = r4 ^ r3 ^ (r1 << 7);
r2 = RotateLeft(r2, 5);
r4 = RotateLeft(r4, 22);
r2 ^= serpent24SubKeys[40];
r1 ^= serpent24SubKeys[40 + 1];
r4 ^= serpent24SubKeys[40 + 2];
r3 ^= serpent24SubKeys[40 + 3];
r0 = r2;
r2 &= r4;
r2 ^= r3;
r4 ^= r1;
r4 ^= r2;
r3 |= r0;
r3 ^= r1;
r0 ^= r4;
r1 = r3;
r3 |= r0;
r3 ^= r2;
r2 &= r1;
r0 ^= r2;
r1 ^= r3;
r1 ^= r0;
r0 = ~r0;
r4 = RotateLeft(r4, 13);
r1 = RotateLeft(r1, 3);
r3 = r3 ^ r4 ^ r1;
r0 = r0 ^ r1 ^ (r4 << 3);
r3 = RotateLeft(r3, 1);
r0 = RotateLeft(r0, 7);
r4 = r4 ^ r3 ^ r0;
r1 = r1 ^ r0 ^ (r3 << 7);
r4 = RotateLeft(r4, 5);
r1 = RotateLeft(r1, 22);
r4 ^= serpent24SubKeys[44];
r3 ^= serpent24SubKeys[44 + 1];
r1 ^= serpent24SubKeys[44 + 2];
r0 ^= serpent24SubKeys[44 + 3];
r2 = r4;
r4 |= r0;
r0 ^= r3;
r3 &= r2;
r2 ^= r1;
r1 ^= r0;
r0 &= r4;
r2 |= r3;
r0 ^= r2;
r4 ^= r3;
r2 &= r4;
r3 ^= r0;
r2 ^= r1;
r3 |= r4;
r3 ^= r1;
r4 ^= r0;
r1 = r3;
r3 |= r0;
r3 ^= r4;
r3 = RotateLeft(r3, 13);
r0 = RotateLeft(r0, 3);
r1 = r1 ^ r3 ^ r0;
r2 = r2 ^ r0 ^ (r3 << 3);
r1 = RotateLeft(r1, 1);
r2 = RotateLeft(r2, 7);
r3 = r3 ^ r1 ^ r2;
r0 = r0 ^ r2 ^ (r1 << 7);
r3 = RotateLeft(r3, 5);
r0 = RotateLeft(r0, 22);
lfsr9 = r3;
lfsr8 = r1;
lfsr7 = r0;
lfsr6 = r2;
r3 ^= serpent24SubKeys[48];
r1 ^= serpent24SubKeys[48 + 1];
r0 ^= serpent24SubKeys[48 + 2];
r2 ^= serpent24SubKeys[48 + 3];
r1 ^= r2;
r2 = ~r2;
r0 ^= r2;
r2 ^= r3;
r4 = r1;
r1 &= r2;
r1 ^= r0;
r4 ^= r2;
r3 ^= r4;
r0 &= r4;
r0 ^= r3;
r3 &= r1;
r2 ^= r3;
r4 |= r1;
r4 ^= r3;
r3 |= r2;
r3 ^= r0;
r0 &= r2;
r3 = ~r3;
r4 ^= r0;
r1 = RotateLeft(r1, 13);
r3 = RotateLeft(r3, 3);
r4 = r4 ^ r1 ^ r3;
r2 = r2 ^ r3 ^ (r1 << 3);
r4 = RotateLeft(r4, 1);
r2 = RotateLeft(r2, 7);
r1 = r1 ^ r4 ^ r2;
r3 = r3 ^ r2 ^ (r4 << 7);
r1 = RotateLeft(r1, 5);
r3 = RotateLeft(r3, 22);
r1 ^= serpent24SubKeys[52];
r4 ^= serpent24SubKeys[52 + 1];
r3 ^= serpent24SubKeys[52 + 2];
r2 ^= serpent24SubKeys[52 + 3];
r1 ^= r4;
r4 ^= r2;
r2 = ~r2;
r0 = r4;
r4 &= r1;
r3 ^= r2;
r4 ^= r3;
r3 |= r0;
r0 ^= r2;
r2 &= r4;
r2 ^= r1;
r0 ^= r4;
r0 ^= r3;
r3 ^= r1;
r1 &= r2;
r3 = ~r3;
r1 ^= r0;
r0 |= r2;
r3 ^= r0;
r4 = RotateLeft(r4, 13);
r1 = RotateLeft(r1, 3);
r2 = r2 ^ r4 ^ r1;
r3 = r3 ^ r1 ^ (r4 << 3);
r2 = RotateLeft(r2, 1);
r3 = RotateLeft(r3, 7);
r4 = r4 ^ r2 ^ r3;
r1 = r1 ^ r3 ^ (r2 << 7);
r4 = RotateLeft(r4, 5);
r1 = RotateLeft(r1, 22);
r4 ^= serpent24SubKeys[56];
r2 ^= serpent24SubKeys[56 + 1];
r1 ^= serpent24SubKeys[56 + 2];
r3 ^= serpent24SubKeys[56 + 3];
r1 = ~r1;
r0 = r3;
r3 &= r4;
r4 ^= r0;
r3 ^= r1;
r1 |= r0;
r2 ^= r3;
r1 ^= r4;
r4 |= r2;
r1 ^= r2;
r0 ^= r4;
r4 |= r3;
r4 ^= r1;
r0 ^= r3;
r0 ^= r4;
r3 = ~r3;
r1 &= r0;
r1 ^= r3;
r4 = RotateLeft(r4, 13);
r0 = RotateLeft(r0, 3);
r2 = r2 ^ r4 ^ r0;
r1 = r1 ^ r0 ^ (r4 << 3);
r2 = RotateLeft(r2, 1);
r1 = RotateLeft(r1, 7);
r4 = r4 ^ r2 ^ r1;
r0 = r0 ^ r1 ^ (r2 << 7);
r4 = RotateLeft(r4, 5);
r0 = RotateLeft(r0, 22);
r4 ^= serpent24SubKeys[60];
r2 ^= serpent24SubKeys[60 + 1];
r0 ^= serpent24SubKeys[60 + 2];
r1 ^= serpent24SubKeys[60 + 3];
r3 = r2;
r2 |= r0;
r2 ^= r1;
r3 ^= r0;
r0 ^= r2;
r1 |= r3;
r1 &= r4;
r3 ^= r0;
r1 ^= r2;
r2 |= r3;
r2 ^= r4;
r4 |= r3;
r4 ^= r0;
r2 ^= r3;
r0 ^= r2;
r2 &= r4;
r2 ^= r3;
r0 = ~r0;
r0 |= r4;
r3 ^= r0;
r3 = RotateLeft(r3, 13);
r2 = RotateLeft(r2, 3);
r1 = r1 ^ r3 ^ r2;
r4 = r4 ^ r2 ^ (r3 << 3);
r1 = RotateLeft(r1, 1);
r4 = RotateLeft(r4, 7);
r3 = r3 ^ r1 ^ r4;
r2 = r2 ^ r4 ^ (r1 << 7);
r3 = RotateLeft(r3, 5);
r2 = RotateLeft(r2, 22);
r3 ^= serpent24SubKeys[64];
r1 ^= serpent24SubKeys[64 + 1];
r2 ^= serpent24SubKeys[64 + 2];
r4 ^= serpent24SubKeys[64 + 3];
r4 ^= r3;
r0 = r1;
r1 &= r4;
r0 ^= r2;
r1 ^= r3;
r3 |= r4;
r3 ^= r0;
r0 ^= r4;
r4 ^= r2;
r2 |= r1;
r2 ^= r0;
r0 = ~r0;
r0 |= r1;
r1 ^= r4;
r1 ^= r0;
r4 |= r3;
r1 ^= r4;
r0 ^= r4;
r1 = RotateLeft(r1, 13);
r2 = RotateLeft(r2, 3);
r0 = r0 ^ r1 ^ r2;
r3 = r3 ^ r2 ^ (r1 << 3);
r0 = RotateLeft(r0, 1);
r3 = RotateLeft(r3, 7);
r1 = r1 ^ r0 ^ r3;
r2 = r2 ^ r3 ^ (r0 << 7);
r1 = RotateLeft(r1, 5);
r2 = RotateLeft(r2, 22);
r1 ^= serpent24SubKeys[68];
r0 ^= serpent24SubKeys[68 + 1];
r2 ^= serpent24SubKeys[68 + 2];
r3 ^= serpent24SubKeys[68 + 3];
r1 = ~r1;
r2 = ~r2;
r4 = r1;
r1 &= r0;
r2 ^= r1;
r1 |= r3;
r3 ^= r2;
r0 ^= r1;
r1 ^= r4;
r4 |= r0;
r0 ^= r3;
r2 |= r1;
r2 &= r4;
r1 ^= r0;
r0 &= r2;
r0 ^= r1;
r1 &= r2;
r1 ^= r4;
r2 = RotateLeft(r2, 13);
r3 = RotateLeft(r3, 3);
r1 = r1 ^ r2 ^ r3;
r0 = r0 ^ r3 ^ (r2 << 3);
r1 = RotateLeft(r1, 1);
r0 = RotateLeft(r0, 7);
r2 = r2 ^ r1 ^ r0;
r3 = r3 ^ r0 ^ (r1 << 7);
r2 = RotateLeft(r2, 5);
r3 = RotateLeft(r3, 22);
fsmR1 = r2;
lfsr4 = r1;
fsmR2 = r3;
lfsr5 = r0;
r2 ^= serpent24SubKeys[72];
r1 ^= serpent24SubKeys[72 + 1];
r3 ^= serpent24SubKeys[72 + 2];
r0 ^= serpent24SubKeys[72 + 3];
r4 = r2;
r2 &= r3;
r2 ^= r0;
r3 ^= r1;
r3 ^= r2;
r0 |= r4;
r0 ^= r1;
r4 ^= r3;
r1 = r0;
r0 |= r4;
r0 ^= r2;
r2 &= r1;
r4 ^= r2;
r1 ^= r0;
r1 ^= r4;
r4 = ~r4;
r3 = RotateLeft(r3, 13);
r1 = RotateLeft(r1, 3);
r0 = r0 ^ r3 ^ r1;
r4 = r4 ^ r1 ^ (r3 << 3);
r0 = RotateLeft(r0, 1);
r4 = RotateLeft(r4, 7);
r3 = r3 ^ r0 ^ r4;
r1 = r1 ^ r4 ^ (r0 << 7);
r3 = RotateLeft(r3, 5);
r1 = RotateLeft(r1, 22);
r3 ^= serpent24SubKeys[76];
r0 ^= serpent24SubKeys[76 + 1];
r1 ^= serpent24SubKeys[76 + 2];
r4 ^= serpent24SubKeys[76 + 3];
r2 = r3;
r3 |= r4;
r4 ^= r0;
r0 &= r2;
r2 ^= r1;
r1 ^= r4;
r4 &= r3;
r2 |= r0;
r4 ^= r2;
r3 ^= r0;
r2 &= r3;
r0 ^= r4;
r2 ^= r1;
r0 |= r3;
r0 ^= r1;
r3 ^= r4;
r1 = r0;
r0 |= r4;
r0 ^= r3;
r0 = RotateLeft(r0, 13);
r4 = RotateLeft(r4, 3);
r1 = r1 ^ r0 ^ r4;
r2 = r2 ^ r4 ^ (r0 << 3);
r1 = RotateLeft(r1, 1);
r2 = RotateLeft(r2, 7);
r0 = r0 ^ r1 ^ r2;
r4 = r4 ^ r2 ^ (r1 << 7);
r0 = RotateLeft(r0, 5);
r4 = RotateLeft(r4, 22);
r0 ^= serpent24SubKeys[80];
r1 ^= serpent24SubKeys[80 + 1];
r4 ^= serpent24SubKeys[80 + 2];
r2 ^= serpent24SubKeys[80 + 3];
r1 ^= r2;
r2 = ~r2;
r4 ^= r2;
r2 ^= r0;
r3 = r1;
r1 &= r2;
r1 ^= r4;
r3 ^= r2;
r0 ^= r3;
r4 &= r3;
r4 ^= r0;
r0 &= r1;
r2 ^= r0;
r3 |= r1;
r3 ^= r0;
r0 |= r2;
r0 ^= r4;
r4 &= r2;
r0 = ~r0;
r3 ^= r4;
r1 = RotateLeft(r1, 13);
r0 = RotateLeft(r0, 3);
r3 = r3 ^ r1 ^ r0;
r2 = r2 ^ r0 ^ (r1 << 3);
r3 = RotateLeft(r3, 1);
r2 = RotateLeft(r2, 7);
r1 = r1 ^ r3 ^ r2;
r0 = r0 ^ r2 ^ (r3 << 7);
r1 = RotateLeft(r1, 5);
r0 = RotateLeft(r0, 22);
r1 ^= serpent24SubKeys[84];
r3 ^= serpent24SubKeys[84 + 1];
r0 ^= serpent24SubKeys[84 + 2];
r2 ^= serpent24SubKeys[84 + 3];
r1 ^= r3;
r3 ^= r2;
r2 = ~r2;
r4 = r3;
r3 &= r1;
r0 ^= r2;
r3 ^= r0;
r0 |= r4;
r4 ^= r2;
r2 &= r3;
r2 ^= r1;
r4 ^= r3;
r4 ^= r0;
r0 ^= r1;
r1 &= r2;
r0 = ~r0;
r1 ^= r4;
r4 |= r2;
r0 ^= r4;
r3 = RotateLeft(r3, 13);
r1 = RotateLeft(r1, 3);
r2 = r2 ^ r3 ^ r1;
r0 = r0 ^ r1 ^ (r3 << 3);
r2 = RotateLeft(r2, 1);
r0 = RotateLeft(r0, 7);
r3 = r3 ^ r2 ^ r0;
r1 = r1 ^ r0 ^ (r2 << 7);
r3 = RotateLeft(r3, 5);
r1 = RotateLeft(r1, 22);
r3 ^= serpent24SubKeys[88];
r2 ^= serpent24SubKeys[88 + 1];
r1 ^= serpent24SubKeys[88 + 2];
r0 ^= serpent24SubKeys[88 + 3];
r1 = ~r1;
r4 = r0;
r0 &= r3;
r3 ^= r4;
r0 ^= r1;
r1 |= r4;
r2 ^= r0;
r1 ^= r3;
r3 |= r2;
r1 ^= r2;
r4 ^= r3;
r3 |= r0;
r3 ^= r1;
r4 ^= r0;
r4 ^= r3;
r0 = ~r0;
r1 &= r4;
r1 ^= r0;
r3 = RotateLeft(r3, 13);
r4 = RotateLeft(r4, 3);
r2 = r2 ^ r3 ^ r4;
r1 = r1 ^ r4 ^ (r3 << 3);
r2 = RotateLeft(r2, 1);
r1 = RotateLeft(r1, 7);
r3 = r3 ^ r2 ^ r1;
r4 = r4 ^ r1 ^ (r2 << 7);
r3 = RotateLeft(r3, 5);
r4 = RotateLeft(r4, 22);
r3 ^= serpent24SubKeys[92];
r2 ^= serpent24SubKeys[92 + 1];
r4 ^= serpent24SubKeys[92 + 2];
r1 ^= serpent24SubKeys[92 + 3];
r0 = r2;
r2 |= r4;
r2 ^= r1;
r0 ^= r4;
r4 ^= r2;
r1 |= r0;
r1 &= r3;
r0 ^= r4;
r1 ^= r2;
r2 |= r0;
r2 ^= r3;
r3 |= r0;
r3 ^= r4;
r2 ^= r0;
r4 ^= r2;
r2 &= r3;
r2 ^= r0;
r4 = ~r4;
r4 |= r3;
r0 ^= r4;
r0 = RotateLeft(r0, 13);
r2 = RotateLeft(r2, 3);
r1 = r1 ^ r0 ^ r2;
r3 = r3 ^ r2 ^ (r0 << 3);
r1 = RotateLeft(r1, 1);
r3 = RotateLeft(r3, 7);
r0 = r0 ^ r1 ^ r3;
r2 = r2 ^ r3 ^ (r1 << 7);
r0 = RotateLeft(r0, 5);
r2 = RotateLeft(r2, 22);
r0 ^= serpent24SubKeys[96];
r1 ^= serpent24SubKeys[96 + 1];
r2 ^= serpent24SubKeys[96 + 2];
r3 ^= serpent24SubKeys[96 + 3];
lfsr3 = r0;
lfsr2 = r1;
lfsr1 = r2;
lfsr0 = r3;
}
/*
* mulAlpha[] is used to multiply a word by alpha; mulAlpha[x]
* is equal to x * alpha^4.
*
* divAlpha[] is used to divide a word by alpha; divAlpha[x]
* is equal to x / alpha.
*/
private static int[] mulAlpha = new int[256];
private static int[] divAlpha = new int[256];
private static bool alphasBuilt = false;
static void BuildAlphas()
{
if (alphasBuilt)
{
return;
}
/*
* We first build exponential and logarithm tables
* relatively to beta in F_{2^8}. We set log(0x00) = 0xFF
* conventionaly, but this is actually not used in our
* computations.
*/
int[] expb = new int[256];
for (int i = 0, x = 0x01; i < 0xFF; i++)
{
expb[i] = x;
x <<= 1;
if (x > 0xFF)
x ^= 0x1A9;
}
expb[0xFF] = 0x00;
int[] logb = new int[256];
for (int i = 0; i < 0x100; i++)
logb[expb[i]] = i;
/*
* We now compute mulAlpha[] and divAlpha[]. For all
* x != 0, we work with invertible numbers, which are
* as such powers of beta. Multiplication (in F_{2^8})
* is then implemented as integer addition modulo 255,
* over the exponents computed by the logb[] table.
*
* We have the following equations:
* alpha^4 = beta^23 * alpha^3 + beta^245 * alpha^2
* + beta^48 * alpha + beta^239
* 1/alpha = beta^16 * alpha^3 + beta^39 * alpha^2
* + beta^6 * alpha + beta^64
*/
mulAlpha[0x00] = 0x00000000;
divAlpha[0x00] = 0x00000000;
for (int x = 1; x < 0x100; x++)
{
int ex = logb[x];
mulAlpha[x] = (expb[(ex + 23) % 255] << 24)
| (expb[(ex + 245) % 255] << 16)
| (expb[(ex + 48) % 255] << 8)
| expb[(ex + 239) % 255];
divAlpha[x] = (expb[(ex + 16) % 255] << 24)
| (expb[(ex + 39) % 255] << 16)
| (expb[(ex + 6) % 255] << 8)
| expb[(ex + 64) % 255];
}
alphasBuilt = true;
}
private int LogicalShiftRight(int left, int right)
{
return (int)((uint)left >> right);
}
/**
* Produce 80 bytes of output stream into the provided buffer.
*
* @param buf the output buffer
* @param off the output offset
*/
private void MakeStreamBlock(byte[] buf, int off)
{
int s0 = lfsr0;
int s1 = lfsr1;
int s2 = lfsr2;
int s3 = lfsr3;
int s4 = lfsr4;
int s5 = lfsr5;
int s6 = lfsr6;
int s7 = lfsr7;
int s8 = lfsr8;
int s9 = lfsr9;
int r1 = fsmR1;
int r2 = fsmR2;
int f0, f1, f2, f3, f4;
int v0, v1, v2, v3;
int tt;
tt = r1;
r1 = r2 + (s1 ^ ((r1 & 0x01) != 0 ? s8 : 0));
r2 = RotateLeft(tt * 0x54655307, 7);
v0 = s0;
s0 = ((s0 << 8) ^ mulAlpha[LogicalShiftRight(s0, 24)])
^ (LogicalShiftRight(s3, 8) ^ divAlpha[s3 & 0xFF]) ^ s9;
f0 = (s9 + r1) ^ r2;
tt = r1;
r1 = r2 + (s2 ^ ((r1 & 0x01) != 0 ? s9 : 0));
r2 = RotateLeft(tt * 0x54655307, 7);
v1 = s1;
s1 = ((s1 << 8) ^ mulAlpha[LogicalShiftRight(s1, 24)])
^ (LogicalShiftRight(s4, 8) ^ divAlpha[s4 & 0xFF]) ^ s0;
f1 = (s0 + r1) ^ r2;
tt = r1;
r1 = r2 + (s3 ^ ((r1 & 0x01) != 0 ? s0 : 0));
r2 = RotateLeft(tt * 0x54655307, 7);
v2 = s2;
s2 = ((s2 << 8) ^ mulAlpha[LogicalShiftRight(s2, 24)])
^ (LogicalShiftRight(s5, 8) ^ divAlpha[s5 & 0xFF]) ^ s1;
f2 = (s1 + r1) ^ r2;
tt = r1;
r1 = r2 + (s4 ^ ((r1 & 0x01) != 0 ? s1 : 0));
r2 = RotateLeft(tt * 0x54655307, 7);
v3 = s3;
s3 = ((s3 << 8) ^ mulAlpha[LogicalShiftRight(s3, 24)])
^ (LogicalShiftRight(s6, 8) ^ divAlpha[s6 & 0xFF]) ^ s2;
f3 = (s2 + r1) ^ r2;
/*
* Apply the third S-box (number 2) on (f3, f2, f1, f0).
*/
f4 = f0;
f0 &= f2;
f0 ^= f3;
f2 ^= f1;
f2 ^= f0;
f3 |= f4;
f3 ^= f1;
f4 ^= f2;
f1 = f3;
f3 |= f4;
f3 ^= f0;
f0 &= f1;
f4 ^= f0;
f1 ^= f3;
f1 ^= f4;
f4 = ~f4;
/*
* S-box result is in (f2, f3, f1, f4).
*/
Encode32le(f2 ^ v0, buf, off);
Encode32le(f3 ^ v1, buf, off + 4);
Encode32le(f1 ^ v2, buf, off + 8);
Encode32le(f4 ^ v3, buf, off + 12);
tt = r1;
r1 = r2 + (s5 ^ ((r1 & 0x01) != 0 ? s2 : 0));
r2 = RotateLeft(tt * 0x54655307, 7);
v0 = s4;
s4 = ((s4 << 8) ^ mulAlpha[LogicalShiftRight(s4, 24)])
^ (LogicalShiftRight(s7, 8) ^ divAlpha[s7 & 0xFF]) ^ s3;
f0 = (s3 + r1) ^ r2;
tt = r1;
r1 = r2 + (s6 ^ ((r1 & 0x01) != 0 ? s3 : 0));
r2 = RotateLeft(tt * 0x54655307, 7);
v1 = s5;
s5 = ((s5 << 8) ^ mulAlpha[LogicalShiftRight(s5, 24)])
^ (LogicalShiftRight(s8, 8) ^ divAlpha[s8 & 0xFF]) ^ s4;
f1 = (s4 + r1) ^ r2;
tt = r1;
r1 = r2 + (s7 ^ ((r1 & 0x01) != 0 ? s4 : 0));
r2 = RotateLeft(tt * 0x54655307, 7);
v2 = s6;
s6 = ((s6 << 8) ^ mulAlpha[LogicalShiftRight(s6, 24)])
^ (LogicalShiftRight(s9, 8) ^ divAlpha[s9 & 0xFF]) ^ s5;
f2 = (s5 + r1) ^ r2;
tt = r1;
r1 = r2 + (s8 ^ ((r1 & 0x01) != 0 ? s5 : 0));
r2 = RotateLeft(tt * 0x54655307, 7);
v3 = s7;
s7 = ((s7 << 8) ^ mulAlpha[LogicalShiftRight(s7, 24)])
^ (LogicalShiftRight(s0, 8) ^ divAlpha[s0 & 0xFF]) ^ s6;
f3 = (s6 + r1) ^ r2;
/*
* Apply the third S-box (number 2) on (f3, f2, f1, f0).
*/
f4 = f0;
f0 &= f2;
f0 ^= f3;
f2 ^= f1;
f2 ^= f0;
f3 |= f4;
f3 ^= f1;
f4 ^= f2;
f1 = f3;
f3 |= f4;
f3 ^= f0;
f0 &= f1;
f4 ^= f0;
f1 ^= f3;
f1 ^= f4;
f4 = ~f4;
/*
* S-box result is in (f2, f3, f1, f4).
*/
Encode32le(f2 ^ v0, buf, off + 16);
Encode32le(f3 ^ v1, buf, off + 20);
Encode32le(f1 ^ v2, buf, off + 24);
Encode32le(f4 ^ v3, buf, off + 28);
tt = r1;
r1 = r2 + (s9 ^ ((r1 & 0x01) != 0 ? s6 : 0));
r2 = RotateLeft(tt * 0x54655307, 7);
v0 = s8;
s8 = ((s8 << 8) ^ mulAlpha[LogicalShiftRight(s8, 24)])
^ (LogicalShiftRight(s1, 8) ^ divAlpha[s1 & 0xFF]) ^ s7;
f0 = (s7 + r1) ^ r2;
tt = r1;
r1 = r2 + (s0 ^ ((r1 & 0x01) != 0 ? s7 : 0));
r2 = RotateLeft(tt * 0x54655307, 7);
v1 = s9;
s9 = ((s9 << 8) ^ mulAlpha[LogicalShiftRight(s9, 24)])
^ (LogicalShiftRight(s2, 8) ^ divAlpha[s2 & 0xFF]) ^ s8;
f1 = (s8 + r1) ^ r2;
tt = r1;
r1 = r2 + (s1 ^ ((r1 & 0x01) != 0 ? s8 : 0));
r2 = RotateLeft(tt * 0x54655307, 7);
v2 = s0;
s0 = ((s0 << 8) ^ mulAlpha[LogicalShiftRight(s0, 24)])
^ (LogicalShiftRight(s3, 8) ^ divAlpha[s3 & 0xFF]) ^ s9;
f2 = (s9 + r1) ^ r2;
tt = r1;
r1 = r2 + (s2 ^ ((r1 & 0x01) != 0 ? s9 : 0));
r2 = RotateLeft(tt * 0x54655307, 7);
v3 = s1;
s1 = ((s1 << 8) ^ mulAlpha[LogicalShiftRight(s1, 24)])
^ (LogicalShiftRight(s4, 8) ^ divAlpha[s4 & 0xFF]) ^ s0;
f3 = (s0 + r1) ^ r2;
/*
* Apply the third S-box (number 2) on (f3, f2, f1, f0).
*/
f4 = f0;
f0 &= f2;
f0 ^= f3;
f2 ^= f1;
f2 ^= f0;
f3 |= f4;
f3 ^= f1;
f4 ^= f2;
f1 = f3;
f3 |= f4;
f3 ^= f0;
f0 &= f1;
f4 ^= f0;
f1 ^= f3;
f1 ^= f4;
f4 = ~f4;
/*
* S-box result is in (f2, f3, f1, f4).
*/
Encode32le(f2 ^ v0, buf, off + 32);
Encode32le(f3 ^ v1, buf, off + 36);
Encode32le(f1 ^ v2, buf, off + 40);
Encode32le(f4 ^ v3, buf, off + 44);
tt = r1;
r1 = r2 + (s3 ^ ((r1 & 0x01) != 0 ? s0 : 0));
r2 = RotateLeft(tt * 0x54655307, 7);
v0 = s2;
s2 = ((s2 << 8) ^ mulAlpha[LogicalShiftRight(s2, 24)])
^ (LogicalShiftRight(s5, 8) ^ divAlpha[s5 & 0xFF]) ^ s1;
f0 = (s1 + r1) ^ r2;
tt = r1;
r1 = r2 + (s4 ^ ((r1 & 0x01) != 0 ? s1 : 0));
r2 = RotateLeft(tt * 0x54655307, 7);
v1 = s3;
s3 = ((s3 << 8) ^ mulAlpha[LogicalShiftRight(s3, 24)])
^ (LogicalShiftRight(s6, 8) ^ divAlpha[s6 & 0xFF]) ^ s2;
f1 = (s2 + r1) ^ r2;
tt = r1;
r1 = r2 + (s5 ^ ((r1 & 0x01) != 0 ? s2 : 0));
r2 = RotateLeft(tt * 0x54655307, 7);
v2 = s4;
s4 = ((s4 << 8) ^ mulAlpha[LogicalShiftRight(s4, 24)])
^ (LogicalShiftRight(s7, 8) ^ divAlpha[s7 & 0xFF]) ^ s3;
f2 = (s3 + r1) ^ r2;
tt = r1;
r1 = r2 + (s6 ^ ((r1 & 0x01) != 0 ? s3 : 0));
r2 = RotateLeft(tt * 0x54655307, 7);
v3 = s5;
s5 = ((s5 << 8) ^ mulAlpha[LogicalShiftRight(s5, 24)])
^ (LogicalShiftRight(s8, 8) ^ divAlpha[s8 & 0xFF]) ^ s4;
f3 = (s4 + r1) ^ r2;
/*
* Apply the third S-box (number 2) on (f3, f2, f1, f0).
*/
f4 = f0;
f0 &= f2;
f0 ^= f3;
f2 ^= f1;
f2 ^= f0;
f3 |= f4;
f3 ^= f1;
f4 ^= f2;
f1 = f3;
f3 |= f4;
f3 ^= f0;
f0 &= f1;
f4 ^= f0;
f1 ^= f3;
f1 ^= f4;
f4 = ~f4;
/*
* S-box result is in (f2, f3, f1, f4).
*/
Encode32le(f2 ^ v0, buf, off + 48);
Encode32le(f3 ^ v1, buf, off + 52);
Encode32le(f1 ^ v2, buf, off + 56);
Encode32le(f4 ^ v3, buf, off + 60);
tt = r1;
r1 = r2 + (s7 ^ ((r1 & 0x01) != 0 ? s4 : 0));
r2 = RotateLeft(tt * 0x54655307, 7);
v0 = s6;
s6 = ((s6 << 8) ^ mulAlpha[LogicalShiftRight(s6, 24)])
^ (LogicalShiftRight(s9, 8) ^ divAlpha[s9 & 0xFF]) ^ s5;
f0 = (s5 + r1) ^ r2;
tt = r1;
r1 = r2 + (s8 ^ ((r1 & 0x01) != 0 ? s5 : 0));
r2 = RotateLeft(tt * 0x54655307, 7);
v1 = s7;
s7 = ((s7 << 8) ^ mulAlpha[LogicalShiftRight(s7, 24)])
^ (LogicalShiftRight(s0, 8) ^ divAlpha[s0 & 0xFF]) ^ s6;
f1 = (s6 + r1) ^ r2;
tt = r1;
r1 = r2 + (s9 ^ ((r1 & 0x01) != 0 ? s6 : 0));
r2 = RotateLeft(tt * 0x54655307, 7);
v2 = s8;
s8 = ((s8 << 8) ^ mulAlpha[LogicalShiftRight(s8, 24)])
^ (LogicalShiftRight(s1, 8) ^ divAlpha[s1 & 0xFF]) ^ s7;
f2 = (s7 + r1) ^ r2;
tt = r1;
r1 = r2 + (s0 ^ ((r1 & 0x01) != 0 ? s7 : 0));
r2 = RotateLeft(tt * 0x54655307, 7);
v3 = s9;
s9 = ((s9 << 8) ^ mulAlpha[LogicalShiftRight(s9, 24)])
^ (LogicalShiftRight(s2, 8) ^ divAlpha[s2 & 0xFF]) ^ s8;
f3 = (s8 + r1) ^ r2;
/*
* Apply the third S-box (number 2) on (f3, f2, f1, f0).
*/
f4 = f0;
f0 &= f2;
f0 ^= f3;
f2 ^= f1;
f2 ^= f0;
f3 |= f4;
f3 ^= f1;
f4 ^= f2;
f1 = f3;
f3 |= f4;
f3 ^= f0;
f0 &= f1;
f4 ^= f0;
f1 ^= f3;
f1 ^= f4;
f4 = ~f4;
/*
* S-box result is in (f2, f3, f1, f4).
*/
Encode32le(f2 ^ v0, buf, off + 64);
Encode32le(f3 ^ v1, buf, off + 68);
Encode32le(f1 ^ v2, buf, off + 72);
Encode32le(f4 ^ v3, buf, off + 76);
lfsr0 = s0;
lfsr1 = s1;
lfsr2 = s2;
lfsr3 = s3;
lfsr4 = s4;
lfsr5 = s5;
lfsr6 = s6;
lfsr7 = s7;
lfsr8 = s8;
lfsr9 = s9;
fsmR1 = r1;
fsmR2 = r2;
}
/*
* Internal buffer for partial blocks. "streamPtr" points to the
* first stream byte which has been computed but not output.
*/
private static int BUFFERLEN = 80;
private byte[] streamBuf = new byte[BUFFERLEN];
private int streamPtr = BUFFERLEN;
/**
* Produce the required number of stream bytes.
*
* @param buf the destination buffer
* @param off the destination offset
* @param len the required stream length (in bytes)
*/
public void MakeStream(byte[] buf, int off, int len)
{
if (streamPtr < BUFFERLEN)
{
int blen = BUFFERLEN - streamPtr;
if (blen > len)
blen = len;
Buffer.BlockCopy(streamBuf, streamPtr, buf, off, blen);
streamPtr += blen;
off += blen;
len -= blen;
}
while (len > 0)
{
if (len >= BUFFERLEN)
{
MakeStreamBlock(buf, off);
off += BUFFERLEN;
len -= BUFFERLEN;
}
else
{
MakeStreamBlock(streamBuf, 0);
Buffer.BlockCopy(streamBuf, 0, buf, off, len);
streamPtr = len;
len = 0;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment