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

net.straylightlabs.quickturing.QuickTuring Maven / Gradle / Ivy

The newest version!
/*
 * 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, }; }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy