net.straylightlabs.quickturing.QuickTuring Maven / Gradle / Ivy
Show all versions of tivo-libre Show documentation
/*
* Fast (unrolled) implementation of Turing
*
* Copyright C 2002, Qualcomm Inc. Written by Greg Rose
*
* Initial Java port by Joseph A Dudar
*
* Optimized Java port by Todd Kulesza
*/
/*
This software is free for commercial and non-commercial use subject to
the following conditions:
1. Copyright remains vested in QUALCOMM Incorporated, and Copyright
notices in the code are not to be removed. If this package is used in
a product, QUALCOMM should be given attribution as the author of the
Turing encryption algorithm. This can be in the form of a textual
message at program startup or in documentation (online or textual)
provided with the package.
2. Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
a. Redistributions of source code must retain the copyright notice,
this list of conditions and the following disclaimer.
b. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the
distribution.
c. All advertising materials mentioning features or use of this
software must display the following acknowledgement: This product
includes software developed by QUALCOMM Incorporated.
3. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND AGAINST
INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4. The license and distribution terms for any publically available version
or derivative of this code cannot be changed, that is, this code cannot
simply be copied and put under another distribution license including
the GNU Public License.
5. The Turing family of encryption algorithms are covered by patents in
the United States of America and other countries. A free and
irrevocable license is hereby granted for the use of such patents to
the extent required to utilize the Turing family of encryption
algorithms for any purpose, subject to the condition that any
commercial product utilising any of the Turing family of encryption
algorithms should show the words "Encryption by QUALCOMM" either on the
product or in the associated documentation.
*/
package net.straylightlabs.quickturing;
/**
* A fast Java implementation of Qualcomm's Turing stream cipher.
*/
public class QuickTuring {
private int keyLength;
private int[] mixedKey = new int[MAX_KEY_LENGTH / 4];
private int[] shiftRegister = new int[SHIFT_REGISTER_LENGTH];
private int[] s0 = new int[256];
private int[] s1 = new int[256];
private int[] s2 = new int[256];
private int[] s3 = new int[256];
public static final int MAX_KEY_LENGTH = 32; // bytes
public static final int MAX_IV_LENGTH = 48; // bytes
public static final int MAX_STREAM_LENGTH = 340; // bytes, maximum stream generated by one call
public static final int SHIFT_REGISTER_LENGTH = 17; // words
public static final int ROUND_OUTPUT_LENGTH = 20; // bytes
/**
* Sets the key on the cipher instance.
*
* @param key the new cipher key
* @param length the length of the cipher key
*/
public void setTuringKey(byte[] key, int length) {
if ((length & 0x03) != 0 || length > MAX_KEY_LENGTH) {
throw new IllegalArgumentException("Invalid key length " + length);
}
keyLength = 0;
for (int i = 0; i < length; i += 4) {
mixedKey[keyLength++] = fixedS(byteArray2Word(key, i));
}
mixWords(mixedKey, keyLength);
buildSBoxTables();
}
/**
* Convert a byte[] to a WORD (big endian).
*/
private static int byteArray2Word(byte[] b, int offset) {
return ((b[offset] & 0xff) << 24) | ((b[offset + 1] & 0xff) << 16) | ((b[offset + 2] & 0xff) << 8) | (b[offset + 3] & 0xff);
}
private void buildSBoxTables() {
int i;
for (int j = 0; j < 256; ++j) {
int w = 0;
int k = j;
for (i = 0; i < keyLength; ++i) {
k = theSBox[getByte(mixedKey[i], 0) ^ k];
w ^= leftRotateWord(theQBox[k], i);
}
s0[j] = (w & 0x00FFFFFF) | (k << 24);
}
for (int j = 0; j < 256; ++j) {
int w = 0;
int k = j;
for (i = 0; i < keyLength; ++i) {
k = theSBox[getByte(mixedKey[i], 1) ^ k];
w ^= leftRotateWord(theQBox[k], i + 8);
}
s1[j] = (w & 0xFF00FFFF) | (k << 16);
}
for (int j = 0; j < 256; ++j) {
int w = 0;
int k = j;
for (i = 0; i < keyLength; ++i) {
k = theSBox[getByte(mixedKey[i], 2) ^ k];
w ^= leftRotateWord(theQBox[k], i + 16);
}
s2[j] = (w & 0xFFFF00FF) | (k << 8);
}
for (int j = 0; j < 256; ++j) {
int w = 0;
int k = j;
for (i = 0; i < keyLength; ++i) {
k = theSBox[getByte(mixedKey[i], 3) ^ k];
w ^= leftRotateWord(theQBox[k], i + 24);
}
s3[j] = (w & 0xFFFFFF00) | k;
}
}
/**
* Return the byte at offset @i of @word.
*/
private static int getByte(int word, int i) {
return ((word >> (24 - 8 * i)) & 0xff);
}
/**
* Convert a WORD (big endian) to a byte[].
*/
private static int leftRotateWord(int word, int bits) {
return (word << bits) | (word >>> (32 - bits));
}
/**
* Load the Initialization Vector.
* Actually, this fills the LFSR, with IV, key, length, and more.
* IV goes through the fixed S-box, key is premixed, the rest go through
* the keyed S-boxes. The reason for this is to avoid nasty interactions
* between the mixed key and the S-boxes that depend on them, and also
* to avoid any "chosen-IV" interactions with the keyed S-boxes, not that I
* can think of any.
*
* @param iv the initialization vector
* @param length length of the initialization vector
*/
public void setTuringIV(byte[] iv, int length) {
int i, j;
if ((length & 0x03) != 0 || (length + 4 * keyLength) > MAX_IV_LENGTH) {
throw new IllegalArgumentException("Invalid IV length " + length);
}
// first copy in the IV, mixing as we go
for (i = j = 0; j < length; j += 4) {
shiftRegister[i++] = fixedS(byteArray2Word(iv, j));
}
// continue with premixed key
for (j = 0; j < keyLength; ++j) {
shiftRegister[i++] = mixedKey[j];
}
// length-dependent word
shiftRegister[i++] = (keyLength << 4) | (length >> 2) | 0x01020300;
// fill the rest of the register
for (j = 0; i < SHIFT_REGISTER_LENGTH; ++i, ++j) {
shiftRegister[i] = s(shiftRegister[j] + shiftRegister[i - 1], 0);
}
// mix all the words
mixWords(shiftRegister, SHIFT_REGISTER_LENGTH);
}
/**
* Performs a reversible transformation of a word, based on the S-boxes.
* The reversibility isn't used, but it guarantees no loss of information,
* and hence no equivalent keys or IVs.
*/
private static int fixedS(int w) {
int b;
b = theSBox[getByte(w, 0)];
w = ((w ^ theQBox[b]) & 0x00ffffff) | (b << 24);
b = theSBox[getByte(w, 1)];
w = ((w ^ leftRotateWord(theQBox[b], 8)) & 0xff00ffff) | (b << 16);
b = theSBox[getByte(w, 2)];
w = ((w ^ leftRotateWord(theQBox[b], 16)) & 0xffff00ff) | (b << 8);
b = theSBox[getByte(w, 3)];
w = ((w ^ leftRotateWord(theQBox[b], 24)) & 0xffffff00) | b;
return w;
}
/*
* Pushes a word through the keyed S-boxes.
* As the bytes bounce around the permutation table, they are used
* to build up words from the Qbox entries. Then the byte position
* corresponding to the input byte is replaced with the result of
* the S-box, which is a permutation of the input and guarantees
* a balanced function.
* Also added a rotation of the input word, to combat a differential
* trail allowed by the PHT.
*/
private int s(int w, int r) {
return (s0[getByte(w, (r) & 0x3)]
^ s1[getByte(w, (1 + r) & 0x3)]
^ s2[getByte(w, (2 + r) & 0x3)]
^ s3[getByte(w, (3 + r) & 0x3)]);
}
/**
* General word-wide n-PHT (Pseudo-Hadamard Transform)
*/
static private void mixWords(int[] w, int n) {
int sum;
int i;
for (sum = i = 0; i < n - 1; ++i) {
sum += w[i];
}
w[n - 1] += sum;
sum = w[n - 1];
for (i = 0; i < n - 1; ++i) {
w[i] += sum;
}
}
/**
* Generate a 340-byte buffer of cipher data.
* Return the number of bytes generated
*
* @param buf the buffer to store the generated cipher data in
* @return the number of bytes generated
*/
public int turingGen(byte[] buf) {
if (buf.length < MAX_STREAM_LENGTH) {
throw new IllegalArgumentException("Buffer is too small");
}
turingGenRound(0, buf, 0);
turingGenRound(5, buf, 20);
turingGenRound(10, buf, 40);
turingGenRound(15, buf, 60);
turingGenRound(3, buf, 80);
turingGenRound(8, buf, 100);
turingGenRound(13, buf, 120);
turingGenRound(1, buf, 140);
turingGenRound(6, buf, 160);
turingGenRound(11, buf, 180);
turingGenRound(16, buf, 200);
turingGenRound(4, buf, 220);
turingGenRound(9, buf, 240);
turingGenRound(14, buf, 260);
turingGenRound(2, buf, 280);
turingGenRound(7, buf, 300);
turingGenRound(12, buf, 320);
return MAX_STREAM_LENGTH;
}
/**
* Generates a 5-word block of output.
* Buffering issues are outside the scope of this implementation.
* Returns the number of bytes of stream generated.
*/
private int turingGenRound(int z, byte[] buf, int offset) {
int a, b, c, d, e;
step(z);
a = shiftRegister[offset(z + 1, 16)];
b = shiftRegister[offset(z + 1, 13)];
c = shiftRegister[offset(z + 1, 6)];
d = shiftRegister[offset(z + 1, 1)];
e = shiftRegister[offset(z + 1, 0)];
// mix 5 words in place (variant PHT)
e += a + b + c + d;
a += e;
b += e;
c += e;
d += e;
a = s(a, 0);
b = s(b, 1);
c = s(c, 2);
d = s(d, 3);
e = s(e, 0);
// mix 5 words in place (variant PHT)
e += a + b + c + d;
a += e;
b += e;
c += e;
d += e;
step(z + 1);
step(z + 2);
step(z + 3);
a += shiftRegister[offset(z + 4, 14)];
b += shiftRegister[offset(z + 4, 12)];
c += shiftRegister[offset(z + 4, 8)];
d += shiftRegister[offset(z + 4, 1)];
e += shiftRegister[offset(z + 4, 0)];
word2ByteArray(a, buf, offset);
word2ByteArray(b, buf, offset + 4);
word2ByteArray(c, buf, offset + 8);
word2ByteArray(d, buf, offset + 12);
word2ByteArray(e, buf, offset + 16);
step(z + 4);
return ROUND_OUTPUT_LENGTH;
}
/**
* Step the LSFR.
*/
private void step(int z) {
shiftRegister[offset(z, 0)] = shiftRegister[offset(z, 15)] ^ shiftRegister[offset(z, 4)] ^
(shiftRegister[offset(z, 0)] << 8) ^ theMultab[(shiftRegister[offset(z, 0)] >>> 24) & 0xFF];
}
/**
* Calculate the offset for the current position of the shift register.
*/
private static int offset(int zero, int i) {
return (zero + i) % SHIFT_REGISTER_LENGTH;
}
/**
* Word is defined as 4 bytes.
*/
private static void word2ByteArray(int word, byte[] b, int offset) {
b[offset] = (byte) (word >> 24);
b[offset + 1] = (byte) (word >> 16);
b[offset + 2] = (byte) (word >> 8);
b[offset + 3] = (byte) word;
}
/**
* Basic Sbox for Turing.
*
* This was generated by keying RC4 with the 11-character string
* "Alan Turing", and then ignoring 256 generated bytes.
* Then the current permutation was tested for nonlinearity, another byte
* generated, etc., until a total
* of 10000 bytes had been generated. The best observed min nonlinearity was
* 104, which first occurred after 736 bytes had been generated. The
* corresponding state table is used in Turing. By happy coincidence it
* also has no fixed points (ie. Sbox[x] != x for all x).
*/
private static final int[] theSBox = new int[]{
0x61, 0x51, 0xeb, 0x19, 0xb9, 0x5d, 0x60, 0x38,
0x7c, 0xb2, 0x06, 0x12, 0xc4, 0x5b, 0x16, 0x3b,
0x2b, 0x18, 0x83, 0xb0, 0x7f, 0x75, 0xfa, 0xa0,
0xe9, 0xdd, 0x6d, 0x7a, 0x6b, 0x68, 0x2d, 0x49,
0xb5, 0x1c, 0x90, 0xf7, 0xed, 0x9f, 0xe8, 0xce,
0xae, 0x77, 0xc2, 0x13, 0xfd, 0xcd, 0x3e, 0xcf,
0x37, 0x6a, 0xd4, 0xdb, 0x8e, 0x65, 0x1f, 0x1a,
0x87, 0xcb, 0x40, 0x15, 0x88, 0x0d, 0x35, 0xb3,
0x11, 0x0f, 0xd0, 0x30, 0x48, 0xf9, 0xa8, 0xac,
0x85, 0x27, 0x0e, 0x8a, 0xe0, 0x50, 0x64, 0xa7,
0xcc, 0xe4, 0xf1, 0x98, 0xff, 0xa1, 0x04, 0xda,
0xd5, 0xbc, 0x1b, 0xbb, 0xd1, 0xfe, 0x31, 0xca,
0xba, 0xd9, 0x2e, 0xf3, 0x1d, 0x47, 0x4a, 0x3d,
0x71, 0x4c, 0xab, 0x7d, 0x8d, 0xc7, 0x59, 0xb8,
0xc1, 0x96, 0x1e, 0xfc, 0x44, 0xc8, 0x7b, 0xdc,
0x5c, 0x78, 0x2a, 0x9d, 0xa5, 0xf0, 0x73, 0x22,
0x89, 0x05, 0xf4, 0x07, 0x21, 0x52, 0xa6, 0x28,
0x9a, 0x92, 0x69, 0x8f, 0xc5, 0xc3, 0xf5, 0xe1,
0xde, 0xec, 0x09, 0xf2, 0xd3, 0xaf, 0x34, 0x23,
0xaa, 0xdf, 0x7e, 0x82, 0x29, 0xc0, 0x24, 0x14,
0x03, 0x32, 0x4e, 0x39, 0x6f, 0xc6, 0xb1, 0x9b,
0xea, 0x72, 0x79, 0x41, 0xd8, 0x26, 0x6c, 0x5e,
0x2c, 0xb4, 0xa2, 0x53, 0x57, 0xe2, 0x9c, 0x86,
0x54, 0x95, 0xb6, 0x80, 0x8c, 0x36, 0x67, 0xbd,
0x08, 0x93, 0x2f, 0x99, 0x5a, 0xf8, 0x3a, 0xd7,
0x56, 0x84, 0xd2, 0x01, 0xf6, 0x66, 0x4d, 0x55,
0x8b, 0x0c, 0x0b, 0x46, 0xb7, 0x3c, 0x45, 0x91,
0xa4, 0xe3, 0x70, 0xd6, 0xfb, 0xe6, 0x10, 0xa9,
0xc9, 0x00, 0x9e, 0xe7, 0x4f, 0x76, 0x25, 0x3f,
0x5f, 0xa3, 0x33, 0x20, 0x02, 0xef, 0x62, 0x74,
0xee, 0x17, 0x81, 0x42, 0x58, 0x0a, 0x4b, 0x63,
0xe5, 0xbe, 0x6e, 0xad, 0xbf, 0x43, 0x94, 0x97,
};
/**
* 8->32 Sbox generated by Millan et. al. at Queensland University of
* Technology. See: E. Dawson, W. Millan, L. Burnett, G. Carter,
* "On the Design of 8*32 S-boxes". Unpublished report, by the
* Information Systems Research Centre,
* Queensland University of Technology, 1999.
*/
private static final int[] theQBox = new int[]{
0x1faa1887, 0x4e5e435c, 0x9165c042, 0x250e6ef4,
0x5957ee20, 0xd484fed3, 0xa666c502, 0x7e54e8ae,
0xd12ee9d9, 0xfc1f38d4, 0x49829b5d, 0x1b5cdf3c,
0x74864249, 0xda2e3963, 0x28f4429f, 0xc8432c35,
0x4af40325, 0x9fc0dd70, 0xd8973ded, 0x1a02dc5e,
0xcd175b42, 0xf10012bf, 0x6694d78c, 0xacaab26b,
0x4ec11b9a, 0x3f168146, 0xc0ea8ec5, 0xb38ac28f,
0x1fed5c0f, 0xaab4101c, 0xea2db082, 0x470929e1,
0xe71843de, 0x508299fc, 0xe72fbc4b, 0x2e3915dd,
0x9fa803fa, 0x9546b2de, 0x3c233342, 0x0fcee7c3,
0x24d607ef, 0x8f97ebab, 0xf37f859b, 0xcd1f2e2f,
0xc25b71da, 0x75e2269a, 0x1e39c3d1, 0xeda56b36,
0xf8c9def2, 0x46c9fc5f, 0x1827b3a3, 0x70a56ddf,
0x0d25b510, 0x000f85a7, 0xb2e82e71, 0x68cb8816,
0x8f951e2a, 0x72f5f6af, 0xe4cbc2b3, 0xd34ff55d,
0x2e6b6214, 0x220b83e3, 0xd39ea6f5, 0x6fe041af,
0x6b2f1f17, 0xad3b99ee, 0x16a65ec0, 0x757016c6,
0xba7709a4, 0xb0326e01, 0xf4b280d9, 0x4bfb1418,
0xd6aff227, 0xfd548203, 0xf56b9d96, 0x6717a8c0,
0x00d5bf6e, 0x10ee7888, 0xedfcfe64, 0x1ba193cd,
0x4b0d0184, 0x89ae4930, 0x1c014f36, 0x82a87088,
0x5ead6c2a, 0xef22c678, 0x31204de7, 0xc9c2e759,
0xd200248e, 0x303b446b, 0xb00d9fc2, 0x9914a895,
0x906cc3a1, 0x54fef170, 0x34c19155, 0xe27b8a66,
0x131b5e69, 0xc3a8623e, 0x27bdfa35, 0x97f068cc,
0xca3a6acd, 0x4b55e936, 0x86602db9, 0x51df13c1,
0x390bb16d, 0x5a80b83c, 0x22b23763, 0x39d8a911,
0x2cb6bc13, 0xbf5579d7, 0x6c5c2fa8, 0xa8f4196e,
0xbcdb5476, 0x6864a866, 0x416e16ad, 0x897fc515,
0x956feb3c, 0xf6c8a306, 0x216799d9, 0x171a9133,
0x6c2466dd, 0x75eb5dcd, 0xdf118f50, 0xe4afb226,
0x26b9cef3, 0xadb36189, 0x8a7a19b1, 0xe2c73084,
0xf77ded5c, 0x8b8bc58f, 0x06dde421, 0xb41e47fb,
0xb1cc715e, 0x68c0ff99, 0x5d122f0f, 0xa4d25184,
0x097a5e6c, 0x0cbf18bc, 0xc2d7c6e0, 0x8bb7e420,
0xa11f523f, 0x35d9b8a2, 0x03da1a6b, 0x06888c02,
0x7dd1e354, 0x6bba7d79, 0x32cc7753, 0xe52d9655,
0xa9829da1, 0x301590a7, 0x9bc1c149, 0x13537f1c,
0xd3779b69, 0x2d71f2b7, 0x183c58fa, 0xacdc4418,
0x8d8c8c76, 0x2620d9f0, 0x71a80d4d, 0x7a74c473,
0x449410e9, 0xa20e4211, 0xf9c8082b, 0x0a6b334a,
0xb5f68ed2, 0x8243cc1b, 0x453c0ff3, 0x9be564a0,
0x4ff55a4f, 0x8740f8e7, 0xcca7f15f, 0xe300fe21,
0x786d37d6, 0xdfd506f1, 0x8ee00973, 0x17bbde36,
0x7a670fa8, 0x5c31ab9e, 0xd4dab618, 0xcc1f52f5,
0xe358eb4f, 0x19b9e343, 0x3a8d77dd, 0xcdb93da6,
0x140fd52d, 0x395412f8, 0x2ba63360, 0x37e53ad0,
0x80700f1c, 0x7624ed0b, 0x703dc1ec, 0xb7366795,
0xd6549d15, 0x66ce46d7, 0xd17abe76, 0xa448e0a0,
0x28f07c02, 0xc31249b7, 0x6e9ed6ba, 0xeaa47f78,
0xbbcfffbd, 0xc507ca84, 0xe965f4da, 0x8e9f35da,
0x6ad2aa44, 0x577452ac, 0xb5d674a7, 0x5461a46a,
0x6763152a, 0x9c12b7aa, 0x12615927, 0x7b4fb118,
0xc351758d, 0x7e81687b, 0x5f52f0b3, 0x2d4254ed,
0xd4c77271, 0x0431acab, 0xbef94aec, 0xfee994cd,
0x9c4d9e81, 0xed623730, 0xcf8a21e8, 0x51917f0b,
0xa7a9b5d6, 0xb297adf8, 0xeed30431, 0x68cac921,
0xf1b35d46, 0x7a430a36, 0x51194022, 0x9abca65e,
0x85ec70ba, 0x39aea8cc, 0x737bae8b, 0x582924d5,
0x03098a5a, 0x92396b81, 0x18de2522, 0x745c1cb8,
0xa1b8fe1d, 0x5db3c697, 0x29164f83, 0x97c16376,
0x8419224c, 0x21203b35, 0x833ac0fe, 0xd966a19a,
0xaaf0b24f, 0x40fda998, 0xe7d52d71, 0x390896a8,
0xcee6053f, 0xd0b0d300, 0xff99cbcc, 0x065e3d40,
};
/**
* Multiplication table for Turing using 0xD02B4367
*/
private static final int[] theMultab = new int[]{
0x00000000, 0xD02B4367, 0xED5686CE, 0x3D7DC5A9,
0x97AC41D1, 0x478702B6, 0x7AFAC71F, 0xAAD18478,
0x631582EF, 0xB33EC188, 0x8E430421, 0x5E684746,
0xF4B9C33E, 0x24928059, 0x19EF45F0, 0xC9C40697,
0xC62A4993, 0x16010AF4, 0x2B7CCF5D, 0xFB578C3A,
0x51860842, 0x81AD4B25, 0xBCD08E8C, 0x6CFBCDEB,
0xA53FCB7C, 0x7514881B, 0x48694DB2, 0x98420ED5,
0x32938AAD, 0xE2B8C9CA, 0xDFC50C63, 0x0FEE4F04,
0xC154926B, 0x117FD10C, 0x2C0214A5, 0xFC2957C2,
0x56F8D3BA, 0x86D390DD, 0xBBAE5574, 0x6B851613,
0xA2411084, 0x726A53E3, 0x4F17964A, 0x9F3CD52D,
0x35ED5155, 0xE5C61232, 0xD8BBD79B, 0x089094FC,
0x077EDBF8, 0xD755989F, 0xEA285D36, 0x3A031E51,
0x90D29A29, 0x40F9D94E, 0x7D841CE7, 0xADAF5F80,
0x646B5917, 0xB4401A70, 0x893DDFD9, 0x59169CBE,
0xF3C718C6, 0x23EC5BA1, 0x1E919E08, 0xCEBADD6F,
0xCFA869D6, 0x1F832AB1, 0x22FEEF18, 0xF2D5AC7F,
0x58042807, 0x882F6B60, 0xB552AEC9, 0x6579EDAE,
0xACBDEB39, 0x7C96A85E, 0x41EB6DF7, 0x91C02E90,
0x3B11AAE8, 0xEB3AE98F, 0xD6472C26, 0x066C6F41,
0x09822045, 0xD9A96322, 0xE4D4A68B, 0x34FFE5EC,
0x9E2E6194, 0x4E0522F3, 0x7378E75A, 0xA353A43D,
0x6A97A2AA, 0xBABCE1CD, 0x87C12464, 0x57EA6703,
0xFD3BE37B, 0x2D10A01C, 0x106D65B5, 0xC04626D2,
0x0EFCFBBD, 0xDED7B8DA, 0xE3AA7D73, 0x33813E14,
0x9950BA6C, 0x497BF90B, 0x74063CA2, 0xA42D7FC5,
0x6DE97952, 0xBDC23A35, 0x80BFFF9C, 0x5094BCFB,
0xFA453883, 0x2A6E7BE4, 0x1713BE4D, 0xC738FD2A,
0xC8D6B22E, 0x18FDF149, 0x258034E0, 0xF5AB7787,
0x5F7AF3FF, 0x8F51B098, 0xB22C7531, 0x62073656,
0xABC330C1, 0x7BE873A6, 0x4695B60F, 0x96BEF568,
0x3C6F7110, 0xEC443277, 0xD139F7DE, 0x0112B4B9,
0xD31DD2E1, 0x03369186, 0x3E4B542F, 0xEE601748,
0x44B19330, 0x949AD057, 0xA9E715FE, 0x79CC5699,
0xB008500E, 0x60231369, 0x5D5ED6C0, 0x8D7595A7,
0x27A411DF, 0xF78F52B8, 0xCAF29711, 0x1AD9D476,
0x15379B72, 0xC51CD815, 0xF8611DBC, 0x284A5EDB,
0x829BDAA3, 0x52B099C4, 0x6FCD5C6D, 0xBFE61F0A,
0x7622199D, 0xA6095AFA, 0x9B749F53, 0x4B5FDC34,
0xE18E584C, 0x31A51B2B, 0x0CD8DE82, 0xDCF39DE5,
0x1249408A, 0xC26203ED, 0xFF1FC644, 0x2F348523,
0x85E5015B, 0x55CE423C, 0x68B38795, 0xB898C4F2,
0x715CC265, 0xA1778102, 0x9C0A44AB, 0x4C2107CC,
0xE6F083B4, 0x36DBC0D3, 0x0BA6057A, 0xDB8D461D,
0xD4630919, 0x04484A7E, 0x39358FD7, 0xE91ECCB0,
0x43CF48C8, 0x93E40BAF, 0xAE99CE06, 0x7EB28D61,
0xB7768BF6, 0x675DC891, 0x5A200D38, 0x8A0B4E5F,
0x20DACA27, 0xF0F18940, 0xCD8C4CE9, 0x1DA70F8E,
0x1CB5BB37, 0xCC9EF850, 0xF1E33DF9, 0x21C87E9E,
0x8B19FAE6, 0x5B32B981, 0x664F7C28, 0xB6643F4F,
0x7FA039D8, 0xAF8B7ABF, 0x92F6BF16, 0x42DDFC71,
0xE80C7809, 0x38273B6E, 0x055AFEC7, 0xD571BDA0,
0xDA9FF2A4, 0x0AB4B1C3, 0x37C9746A, 0xE7E2370D,
0x4D33B375, 0x9D18F012, 0xA06535BB, 0x704E76DC,
0xB98A704B, 0x69A1332C, 0x54DCF685, 0x84F7B5E2,
0x2E26319A, 0xFE0D72FD, 0xC370B754, 0x135BF433,
0xDDE1295C, 0x0DCA6A3B, 0x30B7AF92, 0xE09CECF5,
0x4A4D688D, 0x9A662BEA, 0xA71BEE43, 0x7730AD24,
0xBEF4ABB3, 0x6EDFE8D4, 0x53A22D7D, 0x83896E1A,
0x2958EA62, 0xF973A905, 0xC40E6CAC, 0x14252FCB,
0x1BCB60CF, 0xCBE023A8, 0xF69DE601, 0x26B6A566,
0x8C67211E, 0x5C4C6279, 0x6131A7D0, 0xB11AE4B7,
0x78DEE220, 0xA8F5A147, 0x958864EE, 0x45A32789,
0xEF72A3F1, 0x3F59E096, 0x0224253F, 0xD20F6658,
};
}