Friday, April 4, 2014

High Performance Quasigroup Block Cipher

Hey, I've recently put the finishing touches on a high-performance block cipher that users principals that came from previous work on the quasigroup block cipher, and will be referencing it in my Master of Science in CompSci thesis.  It's performance is built around 64-bit CPU's that weren't available when AES was developed in the late 90's, and doesn't use any of those silly LUTs either, which is really just a calculation over the Rijndael finite field.

I'm posting the block encryption routine, you could probably figure out the decryption routine on your own pretty easily.




class QGBC_HP {
public:
    class BLOCK {
        unsigned long long w[4];    // the 4 words of a block
    }

    class KEY {
        unsigned long long w[4];    // the 4 words of a block
    }

protected:
    BLOCK   b;      // previous block
    bool    cbc;

    void left_rotate(BLOCK& c, int l) {
        if (l == 57) {
            unsigned long long c0 = c.w[0];

            c.w[0] = (c.w[0] << 57) | (c.w[1] >> 7);
            c.w[1] = (c.w[1] << 57) | (c.w[2] >> 7);
            c.w[2] = (c.w[2] << 57) | (c.w[3] >> 7);
            c.w[3] = (c.w[3] << 57) | (c.w >> 7);
        } else if (l == 83) {
            unsigned long long c0 = c.w[0];
            unsigned long long c1 = c.w[1];

            c.w[0] = (c.w[1] << 19) | (c.w[2] >> 45);
            c.w[1] = (c.w[2] << 19) | (c.w[3] >> 45);
            c.w[2] = (c.w[3] << 19) | (c0 >> 45);
            c.w[3] = (c0 << 19) | (c1 >> 45);
        }
    }


public:
    QGBC_HP() : cbc(false) {
    }

    void init(bool cbc = false, BLOCK* iv = NULL) {
        this->cbc = cbc;
        if (cbc) {
            if (iv != null) {
                b.w[0] = iv->w[0];
                b.w[1] = iv->w[1];
                b.w[2] = iv->w[2];
                b.w[3] = iv->w[3];
            } else {
                throw std::exception("iv must not be null if cbc is true");
            }
        } else {
            b.w[0] = b.w[1] = b.w[2] = b.w[3] = 0;
        }
    }

    void encrypt_block(KEY& k, BLOCK& m, BLOCK& c) {
        if (cbc) {
            c.w[0] = m.w[0] ^ b.w[0];
            c.w[1] = m.w[1] ^ b.w[1];
            c.w[2] = m.w[2] ^ b.w[2];
            c.w[3] = m.w[3] ^ b.w[3];
        }

        for(int x=0; x<4; ++x) {
            if (x == 1) left_rotate(c, 57);
            else if (x > 1) left_rotate(c, 83);

            c.w[0] = K.w[3] ^ ( ~K.w[x] + c.w[0]);
            c.w[1] = K.w[2] ^ (  c.w[0] + c.w[1]);
            c.w[2] = K.w[1] ^ (  c.w[1] + c.w[2]);
            c.w[3] = K.w[0] ^ (  c.w[2] + c.w[3]);
        }

        if (cbc) {
            b.w[0] = c.w[0];
            b.w[1] = c.w[1];
            b.w[2] = c.w[2];
            b.w[3] = c.w[3];
        }
    }
};

No comments:

Post a Comment