private void setKey(byte[] key)
    {
        int[] k32e = new int[MAX_KEY_BITS/64]; // 4
        int[] k32o = new int[MAX_KEY_BITS/64]; // 4 

        int[] sBoxKeys = new int[MAX_KEY_BITS/64]; // 4 
        gSubKeys = new int[TOTAL_SUBKEYS];

        if (k64Cnt < 1) 
        {
            throw new IllegalArgumentException("Key size less than 64 bits");
        }
        
        if (k64Cnt > 4)
        {
            throw new IllegalArgumentException("Key size larger than 256 bits");
        }

        /*
         * k64Cnt is the number of 8 byte blocks (64 chunks)
         * that are in the input key.  The input key is a
         * maximum of 32 bytes (256 bits), so the range
         * for k64Cnt is 1..4
         */
        for (int i=0; i<k64Cnt ; i++)
        {
            int p = i* 8;

            k32e[i] = BytesTo32Bits(key, p);
            k32o[i] = BytesTo32Bits(key, p+4);

            sBoxKeys[k64Cnt-1-i] = RS_MDS_Encode(k32e[i], k32o[i]);
        }

        int q,A,B;
        for (int i=0; i < TOTAL_SUBKEYS / 2 ; i++) 
        {
            q = i*SK_STEP;
            A = F32(q,         k32e);
            B = F32(q+SK_BUMP, k32o);
            B = B << 8 | B >>> 24;
            A += B;
            gSubKeys[i*2] = A;
            A += B;
            gSubKeys[i*2 + 1] = A << SK_ROTL | A >>> (32-SK_ROTL);
        }

        /*
         * fully expand the table for speed
         */
        int k0 = sBoxKeys[0];
        int k1 = sBoxKeys[1];
        int k2 = sBoxKeys[2];
        int k3 = sBoxKeys[3];
        int b0, b1, b2, b3;
        gSBox = new int[4*MAX_KEY_BITS];
        for (int i=0; i<MAX_KEY_BITS; i++)
        {
            b0 = b1 = b2 = b3 = i;
            switch (k64Cnt & 3)
            {
                case 1:
                    gSBox[i*2]       = gMDS0[(P[P_01][b0] & 0xff) ^ b0(k0)];
                    gSBox[i*2+1]     = gMDS1[(P[P_11][b1] & 0xff) ^ b1(k0)];
                    gSBox[i*2+0x200] = gMDS2[(P[P_21][b2] & 0xff) ^ b2(k0)];
                    gSBox[i*2+0x201] = gMDS3[(P[P_31][b3] & 0xff) ^ b3(k0)];
                break;
                case 0: // 256 bits of key
                    b0 = (P[P_04][b0] & 0xff) ^ b0(k3);
                    b1 = (P[P_14][b1] & 0xff) ^ b1(k3);
                    b2 = (P[P_24][b2] & 0xff) ^ b2(k3);
                    b3 = (P[P_34][b3] & 0xff) ^ b3(k3);
                    // fall through, having pre-processed b[0]..b[3] with k32[3]
                case 3: // 192 bits of key
                    b0 = (P[P_03][b0] & 0xff) ^ b0(k2);
                    b1 = (P[P_13][b1] & 0xff) ^ b1(k2);
                    b2 = (P[P_23][b2] & 0xff) ^ b2(k2);
                    b3 = (P[P_33][b3] & 0xff) ^ b3(k2);
                    // fall through, having pre-processed b[0]..b[3] with k32[2]
                case 2: // 128 bits of key
                    gSBox[i*2]   = gMDS0[(P[P_01]
                        [(P[P_02][b0] & 0xff) ^ b0(k1)] & 0xff) ^ b0(k0)];
                    gSBox[i*2+1] = gMDS1[(P[P_11]
                        [(P[P_12][b1] & 0xff) ^ b1(k1)] & 0xff) ^ b1(k0)];
                    gSBox[i*2+0x200] = gMDS2[(P[P_21]
                        [(P[P_22][b2] & 0xff) ^ b2(k1)] & 0xff) ^ b2(k0)];
                    gSBox[i*2+0x201] = gMDS3[(P[P_31]
                        [(P[P_32][b3] & 0xff) ^ b3(k1)] & 0xff) ^ b3(k0)];
                break;
            }
        }

        /* 
         * the function exits having setup the gSBox with the 
         * input key material.
         */
    }