Esempio n. 1
0
        private void Encrypt16(byte[] Input, int InOffset, byte[] Output, int OutOffset)
        {
            int    LRD = _expKey.Length - 1;
            int    keyCtr = 0;
            UInt32 X0 = IntUtils.BytesToLe32(Input, InOffset) ^ _expKey[keyCtr];
            UInt32 X1 = IntUtils.BytesToLe32(Input, InOffset + 4) ^ _expKey[++keyCtr];
            UInt32 X2 = IntUtils.BytesToLe32(Input, InOffset + 8) ^ _expKey[++keyCtr];
            UInt32 X3 = IntUtils.BytesToLe32(Input, InOffset + 12) ^ _expKey[++keyCtr];
            UInt32 T0, T1;

            keyCtr = 7;
            do
            {
                T0  = Fe0(X0);
                T1  = Fe3(X1);
                X2 ^= T0 + T1 + _expKey[++keyCtr];
                X2  = (X2 >> 1) | X2 << 31;
                X3  = (X3 << 1 | (X3 >> 31)) ^ (T0 + 2 * T1 + _expKey[++keyCtr]);

                T0  = Fe0(X2);
                T1  = Fe3(X3);
                X0 ^= T0 + T1 + _expKey[++keyCtr];
                X0  = (X0 >> 1) | X0 << 31;
                X1  = (X1 << 1 | (X1 >> 31)) ^ (T0 + 2 * T1 + _expKey[++keyCtr]);
            } while (keyCtr != LRD);

            keyCtr = 4;
            IntUtils.Le32ToBytes(X2 ^ _expKey[keyCtr], Output, OutOffset);
            IntUtils.Le32ToBytes(X3 ^ _expKey[++keyCtr], Output, OutOffset + 4);
            IntUtils.Le32ToBytes(X0 ^ _expKey[++keyCtr], Output, OutOffset + 8);
            IntUtils.Le32ToBytes(X1 ^ _expKey[++keyCtr], Output, OutOffset + 12);
        }
Esempio n. 2
0
        private void Transform(byte[] Output, int OutOffset, uint[] Counter)
        {
            int  ctr = 0;
            uint X0  = m_wrkState[ctr];
            uint X1  = m_wrkState[++ctr];
            uint X2  = m_wrkState[++ctr];
            uint X3  = m_wrkState[++ctr];
            uint X4  = m_wrkState[++ctr];
            uint X5  = m_wrkState[++ctr];
            uint X6  = m_wrkState[++ctr];
            uint X7  = m_wrkState[++ctr];
            uint X8  = Counter[0];
            uint X9  = Counter[1];
            uint X10 = m_wrkState[++ctr];
            uint X11 = m_wrkState[++ctr];
            uint X12 = m_wrkState[++ctr];
            uint X13 = m_wrkState[++ctr];
            uint X14 = m_wrkState[++ctr];
            uint X15 = m_wrkState[++ctr];

            ctr = Rounds;

            while (ctr != 0)
            {
                X4  ^= IntUtils.RotateLeft(X0 + X12, 7);
                X8  ^= IntUtils.RotateLeft(X4 + X0, 9);
                X12 ^= IntUtils.RotateLeft(X8 + X4, 13);
                X0  ^= IntUtils.RotateLeft(X12 + X8, 18);
                X9  ^= IntUtils.RotateLeft(X5 + X1, 7);
                X13 ^= IntUtils.RotateLeft(X9 + X5, 9);
                X1  ^= IntUtils.RotateLeft(X13 + X9, 13);
                X5  ^= IntUtils.RotateLeft(X1 + X13, 18);
                X14 ^= IntUtils.RotateLeft(X10 + X6, 7);
                X2  ^= IntUtils.RotateLeft(X14 + X10, 9);
                X6  ^= IntUtils.RotateLeft(X2 + X14, 13);
                X10 ^= IntUtils.RotateLeft(X6 + X2, 18);
                X3  ^= IntUtils.RotateLeft(X15 + X11, 7);
                X7  ^= IntUtils.RotateLeft(X3 + X15, 9);
                X11 ^= IntUtils.RotateLeft(X7 + X3, 13);
                X15 ^= IntUtils.RotateLeft(X11 + X7, 18);
                X1  ^= IntUtils.RotateLeft(X0 + X3, 7);
                X2  ^= IntUtils.RotateLeft(X1 + X0, 9);
                X3  ^= IntUtils.RotateLeft(X2 + X1, 13);
                X0  ^= IntUtils.RotateLeft(X3 + X2, 18);
                X6  ^= IntUtils.RotateLeft(X5 + X4, 7);
                X7  ^= IntUtils.RotateLeft(X6 + X5, 9);
                X4  ^= IntUtils.RotateLeft(X7 + X6, 13);
                X5  ^= IntUtils.RotateLeft(X4 + X7, 18);
                X11 ^= IntUtils.RotateLeft(X10 + X9, 7);
                X8  ^= IntUtils.RotateLeft(X11 + X10, 9);
                X9  ^= IntUtils.RotateLeft(X8 + X11, 13);
                X10 ^= IntUtils.RotateLeft(X9 + X8, 18);
                X12 ^= IntUtils.RotateLeft(X15 + X14, 7);
                X13 ^= IntUtils.RotateLeft(X12 + X15, 9);
                X14 ^= IntUtils.RotateLeft(X13 + X12, 13);
                X15 ^= IntUtils.RotateLeft(X14 + X13, 18);
                ctr -= 2;
            }

            IntUtils.Le32ToBytes(X0 + m_wrkState[ctr], Output, OutOffset); OutOffset    += 4;
            IntUtils.Le32ToBytes(X1 + m_wrkState[++ctr], Output, OutOffset); OutOffset  += 4;
            IntUtils.Le32ToBytes(X2 + m_wrkState[++ctr], Output, OutOffset); OutOffset  += 4;
            IntUtils.Le32ToBytes(X3 + m_wrkState[++ctr], Output, OutOffset); OutOffset  += 4;
            IntUtils.Le32ToBytes(X4 + m_wrkState[++ctr], Output, OutOffset); OutOffset  += 4;
            IntUtils.Le32ToBytes(X5 + m_wrkState[++ctr], Output, OutOffset); OutOffset  += 4;
            IntUtils.Le32ToBytes(X6 + m_wrkState[++ctr], Output, OutOffset); OutOffset  += 4;
            IntUtils.Le32ToBytes(X7 + m_wrkState[++ctr], Output, OutOffset); OutOffset  += 4;
            IntUtils.Le32ToBytes(X8 + Counter[0], Output, OutOffset); OutOffset         += 4;
            IntUtils.Le32ToBytes(X9 + Counter[1], Output, OutOffset); OutOffset         += 4;
            IntUtils.Le32ToBytes(X10 + m_wrkState[++ctr], Output, OutOffset); OutOffset += 4;
            IntUtils.Le32ToBytes(X11 + m_wrkState[++ctr], Output, OutOffset); OutOffset += 4;
            IntUtils.Le32ToBytes(X12 + m_wrkState[++ctr], Output, OutOffset); OutOffset += 4;
            IntUtils.Le32ToBytes(X13 + m_wrkState[++ctr], Output, OutOffset); OutOffset += 4;
            IntUtils.Le32ToBytes(X14 + m_wrkState[++ctr], Output, OutOffset); OutOffset += 4;
            IntUtils.Le32ToBytes(X15 + m_wrkState[++ctr], Output, OutOffset);
        }
Esempio n. 3
0
        private void Transform(byte[] Output, int OutOffset, uint[] Counter)
        {
            int  ctr = 0;
            uint X0  = m_wrkState[ctr];
            uint X1  = m_wrkState[++ctr];
            uint X2  = m_wrkState[++ctr];
            uint X3  = m_wrkState[++ctr];
            uint X4  = m_wrkState[++ctr];
            uint X5  = m_wrkState[++ctr];
            uint X6  = m_wrkState[++ctr];
            uint X7  = m_wrkState[++ctr];
            uint X8  = m_wrkState[++ctr];
            uint X9  = m_wrkState[++ctr];
            uint X10 = m_wrkState[++ctr];
            uint X11 = m_wrkState[++ctr];
            uint X12 = Counter[0];
            uint X13 = Counter[1];
            uint X14 = m_wrkState[++ctr];
            uint X15 = m_wrkState[++ctr];

            ctr = Rounds;
            while (ctr != 0)
            {
                X0  += X4;
                X12  = IntUtils.RotateLeft(X12 ^ X0, 16);
                X8  += X12;
                X4   = IntUtils.RotateLeft(X4 ^ X8, 12);
                X0  += X4;
                X12  = IntUtils.RotateLeft(X12 ^ X0, 8);
                X8  += X12;
                X4   = IntUtils.RotateLeft(X4 ^ X8, 7);
                X1  += X5;
                X13  = IntUtils.RotateLeft(X13 ^ X1, 16);
                X9  += X13;
                X5   = IntUtils.RotateLeft(X5 ^ X9, 12);
                X1  += X5;
                X13  = IntUtils.RotateLeft(X13 ^ X1, 8);
                X9  += X13;
                X5   = IntUtils.RotateLeft(X5 ^ X9, 7);
                X2  += X6;
                X14  = IntUtils.RotateLeft(X14 ^ X2, 16);
                X10 += X14;
                X6   = IntUtils.RotateLeft(X6 ^ X10, 12);
                X2  += X6;
                X14  = IntUtils.RotateLeft(X14 ^ X2, 8);
                X10 += X14;
                X6   = IntUtils.RotateLeft(X6 ^ X10, 7);
                X3  += X7;
                X15  = IntUtils.RotateLeft(X15 ^ X3, 16);
                X11 += X15;
                X7   = IntUtils.RotateLeft(X7 ^ X11, 12);
                X3  += X7;
                X15  = IntUtils.RotateLeft(X15 ^ X3, 8);
                X11 += X15;
                X7   = IntUtils.RotateLeft(X7 ^ X11, 7);
                X0  += X5;
                X15  = IntUtils.RotateLeft(X15 ^ X0, 16);
                X10 += X15;
                X5   = IntUtils.RotateLeft(X5 ^ X10, 12);
                X0  += X5;
                X15  = IntUtils.RotateLeft(X15 ^ X0, 8);
                X10 += X15;
                X5   = IntUtils.RotateLeft(X5 ^ X10, 7);
                X1  += X6;
                X12  = IntUtils.RotateLeft(X12 ^ X1, 16);
                X11 += X12;
                X6   = IntUtils.RotateLeft(X6 ^ X11, 12);
                X1  += X6;
                X12  = IntUtils.RotateLeft(X12 ^ X1, 8);
                X11 += X12;
                X6   = IntUtils.RotateLeft(X6 ^ X11, 7);
                X2  += X7;
                X13  = IntUtils.RotateLeft(X13 ^ X2, 16);
                X8  += X13;
                X7   = IntUtils.RotateLeft(X7 ^ X8, 12);
                X2  += X7;
                X13  = IntUtils.RotateLeft(X13 ^ X2, 8);
                X8  += X13;
                X7   = IntUtils.RotateLeft(X7 ^ X8, 7);
                X3  += X4;
                X14  = IntUtils.RotateLeft(X14 ^ X3, 16);
                X9  += X14;
                X4   = IntUtils.RotateLeft(X4 ^ X9, 12);
                X3  += X4;
                X14  = IntUtils.RotateLeft(X14 ^ X3, 8);
                X9  += X14;
                X4   = IntUtils.RotateLeft(X4 ^ X9, 7);
                ctr -= 2;
            }

            IntUtils.Le32ToBytes(X0 + m_wrkState[ctr], Output, OutOffset); OutOffset    += 4;
            IntUtils.Le32ToBytes(X1 + m_wrkState[++ctr], Output, OutOffset); OutOffset  += 4;
            IntUtils.Le32ToBytes(X2 + m_wrkState[++ctr], Output, OutOffset); OutOffset  += 4;
            IntUtils.Le32ToBytes(X3 + m_wrkState[++ctr], Output, OutOffset); OutOffset  += 4;
            IntUtils.Le32ToBytes(X4 + m_wrkState[++ctr], Output, OutOffset); OutOffset  += 4;
            IntUtils.Le32ToBytes(X5 + m_wrkState[++ctr], Output, OutOffset); OutOffset  += 4;
            IntUtils.Le32ToBytes(X6 + m_wrkState[++ctr], Output, OutOffset); OutOffset  += 4;
            IntUtils.Le32ToBytes(X7 + m_wrkState[++ctr], Output, OutOffset); OutOffset  += 4;
            IntUtils.Le32ToBytes(X8 + m_wrkState[++ctr], Output, OutOffset); OutOffset  += 4;
            IntUtils.Le32ToBytes(X9 + m_wrkState[++ctr], Output, OutOffset); OutOffset  += 4;
            IntUtils.Le32ToBytes(X10 + m_wrkState[++ctr], Output, OutOffset); OutOffset += 4;
            IntUtils.Le32ToBytes(X11 + m_wrkState[++ctr], Output, OutOffset); OutOffset += 4;
            IntUtils.Le32ToBytes(X12 + Counter[0], Output, OutOffset); OutOffset        += 4;
            IntUtils.Le32ToBytes(X13 + Counter[1], Output, OutOffset); OutOffset        += 4;
            IntUtils.Le32ToBytes(X14 + m_wrkState[++ctr], Output, OutOffset); OutOffset += 4;
            IntUtils.Le32ToBytes(X15 + m_wrkState[++ctr], Output, OutOffset);
        }
Esempio n. 4
0
        private UInt32[] ExpandKey(byte[] Key)
        {
            int    k64Cnt = Key.Length / 8;
            int    kmLen = k64Cnt > 4 ? 8 : 4;
            int    keyCtr = 0;
            UInt32 A, B, Q;
            UInt32 Y0, Y1, Y2, Y3;

            UInt32[] eKm   = new UInt32[kmLen];
            UInt32[] oKm   = new UInt32[kmLen];
            byte[]   sbKey = new byte[Key.Length == 64 ? 32 : 16];
            UInt32[] wK    = new UInt32[_dfnRounds * 2 + 8];

            for (int i = 0; i < k64Cnt; i++)
            {
                // round key material
                eKm[i]  = IntUtils.BytesToLe32(Key, keyCtr);
                keyCtr += 4;
                oKm[i]  = IntUtils.BytesToLe32(Key, keyCtr);
                keyCtr += 4;
                // sbox key material
                IntUtils.Le32ToBytes(MDSEncode(eKm[i], oKm[i]), sbKey, ((k64Cnt * 4) - 4) - (i * 4));
            }

            keyCtr = 0;

            while (keyCtr < KEY_BITS)
            {
                // create the expanded key
                if (keyCtr < (wK.Length / 2))
                {
                    Q  = (uint)keyCtr * SK_STEP;
                    A  = Mix(Q, eKm, k64Cnt);
                    B  = Mix(Q + SK_BUMP, oKm, k64Cnt);
                    B  = B << 8 | (UInt32)(B >> 24);
                    A += B;
                    wK[keyCtr * 2] = A;
                    A += B;
                    wK[keyCtr * 2 + 1] = A << SK_ROTL | (UInt32)(A >> (32 - SK_ROTL));
                }

                Y0 = Y1 = Y2 = Y3 = (uint)keyCtr;

                // 512 key
                if (Key.Length == 64)
                {
                    Y0 = (uint)(byte)Q1[Y0] ^ sbKey[28];
                    Y1 = (uint)(byte)Q0[Y1] ^ sbKey[29];
                    Y2 = (uint)(byte)Q0[Y2] ^ sbKey[30];
                    Y3 = (uint)(byte)Q1[Y3] ^ sbKey[31];

                    Y0 = (uint)(byte)Q1[Y0] ^ sbKey[24];
                    Y1 = (uint)(byte)Q1[Y1] ^ sbKey[25];
                    Y2 = (uint)(byte)Q0[Y2] ^ sbKey[26];
                    Y3 = (uint)(byte)Q0[Y3] ^ sbKey[27];

                    Y0 = (uint)(byte)Q0[Y0] ^ sbKey[20];
                    Y1 = (uint)(byte)Q1[Y1] ^ sbKey[21];
                    Y2 = (uint)(byte)Q1[Y2] ^ sbKey[22];
                    Y3 = (uint)(byte)Q0[Y3] ^ sbKey[23];

                    Y0 = (uint)(byte)Q0[Y0] ^ sbKey[16];
                    Y1 = (uint)(byte)Q0[Y1] ^ sbKey[17];
                    Y2 = (uint)(byte)Q1[Y2] ^ sbKey[18];
                    Y3 = (uint)(byte)Q1[Y3] ^ sbKey[19];
                }
                // 256 key
                if (Key.Length > 24)
                {
                    Y0 = (uint)(byte)Q1[Y0] ^ sbKey[12];
                    Y1 = (uint)(byte)Q0[Y1] ^ sbKey[13];
                    Y2 = (uint)(byte)Q0[Y2] ^ sbKey[14];
                    Y3 = (uint)(byte)Q1[Y3] ^ sbKey[15];
                }
                // 192 key
                if (Key.Length > 16)
                {
                    Y0 = (uint)(byte)Q1[Y0] ^ sbKey[8];
                    Y1 = (uint)(byte)Q1[Y1] ^ sbKey[9];
                    Y2 = (uint)(byte)Q0[Y2] ^ sbKey[10];
                    Y3 = (uint)(byte)Q0[Y3] ^ sbKey[11];
                }

                // sbox members as MDS matrix multiplies
                _sprBox[keyCtr * 2]           = MDS0[(byte)Q0[(byte)Q0[Y0] ^ sbKey[4]] ^ sbKey[0]];
                _sprBox[keyCtr * 2 + 1]       = MDS1[(byte)Q0[Q1[Y1] ^ sbKey[5]] ^ sbKey[1]];
                _sprBox[(keyCtr * 2) + 0x200] = MDS2[(byte)Q1[(byte)Q0[Y2] ^ sbKey[6]] ^ sbKey[2]];
                _sprBox[keyCtr++ *2 + 0x201]  = MDS3[(byte)Q1[(byte)Q1[Y3] ^ sbKey[7]] ^ sbKey[3]];
            }

            // key processed
            _isInitialized = true;
            return(wK);
        }
Esempio n. 5
0
        private void Encrypt16(byte[] Input, int InOffset, byte[] Output, int OutOffset)
        {
            int LRD    = m_expKey.Length - 5;
            int keyCtr = -1;

            // input round
            uint R0 = IntUtils.BytesToLe32(Input, InOffset);
            uint R1 = IntUtils.BytesToLe32(Input, InOffset + 4);
            uint R2 = IntUtils.BytesToLe32(Input, InOffset + 8);
            uint R3 = IntUtils.BytesToLe32(Input, InOffset + 12);

            // process 8 round blocks
            do
            {
                R0 ^= m_expKey[++keyCtr];
                R1 ^= m_expKey[++keyCtr];
                R2 ^= m_expKey[++keyCtr];
                R3 ^= m_expKey[++keyCtr];
                Sb0(ref R0, ref R1, ref R2, ref R3);
                LinearTransform(ref R0, ref R1, ref R2, ref R3);

                R0 ^= m_expKey[++keyCtr];
                R1 ^= m_expKey[++keyCtr];
                R2 ^= m_expKey[++keyCtr];
                R3 ^= m_expKey[++keyCtr];
                Sb1(ref R0, ref R1, ref R2, ref R3);
                LinearTransform(ref R0, ref R1, ref R2, ref R3);

                R0 ^= m_expKey[++keyCtr];
                R1 ^= m_expKey[++keyCtr];
                R2 ^= m_expKey[++keyCtr];
                R3 ^= m_expKey[++keyCtr];
                Sb2(ref R0, ref R1, ref R2, ref R3);
                LinearTransform(ref R0, ref R1, ref R2, ref R3);;

                R0 ^= m_expKey[++keyCtr];
                R1 ^= m_expKey[++keyCtr];
                R2 ^= m_expKey[++keyCtr];
                R3 ^= m_expKey[++keyCtr];
                Sb3(ref R0, ref R1, ref R2, ref R3);
                LinearTransform(ref R0, ref R1, ref R2, ref R3);

                R0 ^= m_expKey[++keyCtr];
                R1 ^= m_expKey[++keyCtr];
                R2 ^= m_expKey[++keyCtr];
                R3 ^= m_expKey[++keyCtr];
                Sb4(ref R0, ref R1, ref R2, ref R3);
                LinearTransform(ref R0, ref R1, ref R2, ref R3);

                R0 ^= m_expKey[++keyCtr];
                R1 ^= m_expKey[++keyCtr];
                R2 ^= m_expKey[++keyCtr];
                R3 ^= m_expKey[++keyCtr];
                Sb5(ref R0, ref R1, ref R2, ref R3);
                LinearTransform(ref R0, ref R1, ref R2, ref R3);

                R0 ^= m_expKey[++keyCtr];
                R1 ^= m_expKey[++keyCtr];
                R2 ^= m_expKey[++keyCtr];
                R3 ^= m_expKey[++keyCtr];
                Sb6(ref R0, ref R1, ref R2, ref R3);
                LinearTransform(ref R0, ref R1, ref R2, ref R3);

                R0 ^= m_expKey[++keyCtr];
                R1 ^= m_expKey[++keyCtr];
                R2 ^= m_expKey[++keyCtr];
                R3 ^= m_expKey[++keyCtr];
                Sb7(ref R0, ref R1, ref R2, ref R3);

                // skip on last block
                if (keyCtr != LRD)
                {
                    LinearTransform(ref R0, ref R1, ref R2, ref R3);
                }
            }while (keyCtr != LRD);

            // last round
            IntUtils.Le32ToBytes(m_expKey[++keyCtr] ^ R0, Output, OutOffset);
            IntUtils.Le32ToBytes(m_expKey[++keyCtr] ^ R1, Output, OutOffset + 4);
            IntUtils.Le32ToBytes(m_expKey[++keyCtr] ^ R2, Output, OutOffset + 8);
            IntUtils.Le32ToBytes(m_expKey[++keyCtr] ^ R3, Output, OutOffset + 12);
        }
Esempio n. 6
0
        private void Decrypt16(byte[] Input, int InOffset, byte[] Output, int OutOffset)
        {
            int LRD    = 4;
            int keyCtr = m_expKey.Length;

            // input round
            uint R3 = m_expKey[--keyCtr] ^ IntUtils.BytesToLe32(Input, InOffset + 12);
            uint R2 = m_expKey[--keyCtr] ^ IntUtils.BytesToLe32(Input, InOffset + 8);
            uint R1 = m_expKey[--keyCtr] ^ IntUtils.BytesToLe32(Input, InOffset + 4);
            uint R0 = m_expKey[--keyCtr] ^ IntUtils.BytesToLe32(Input, InOffset);

            // process 8 round blocks
            do
            {
                Ib7(ref R0, ref R1, ref R2, ref R3);
                R3 ^= m_expKey[--keyCtr];
                R2 ^= m_expKey[--keyCtr];
                R1 ^= m_expKey[--keyCtr];
                R0 ^= m_expKey[--keyCtr];
                InverseTransform(ref R0, ref R1, ref R2, ref R3);

                Ib6(ref R0, ref R1, ref R2, ref R3);
                R3 ^= m_expKey[--keyCtr];
                R2 ^= m_expKey[--keyCtr];
                R1 ^= m_expKey[--keyCtr];
                R0 ^= m_expKey[--keyCtr];
                InverseTransform(ref R0, ref R1, ref R2, ref R3);

                Ib5(ref R0, ref R1, ref R2, ref R3);
                R3 ^= m_expKey[--keyCtr];
                R2 ^= m_expKey[--keyCtr];
                R1 ^= m_expKey[--keyCtr];
                R0 ^= m_expKey[--keyCtr];
                InverseTransform(ref R0, ref R1, ref R2, ref R3);

                Ib4(ref R0, ref R1, ref R2, ref R3);
                R3 ^= m_expKey[--keyCtr];
                R2 ^= m_expKey[--keyCtr];
                R1 ^= m_expKey[--keyCtr];
                R0 ^= m_expKey[--keyCtr];
                InverseTransform(ref R0, ref R1, ref R2, ref R3);

                Ib3(ref R0, ref R1, ref R2, ref R3);
                R3 ^= m_expKey[--keyCtr];
                R2 ^= m_expKey[--keyCtr];
                R1 ^= m_expKey[--keyCtr];
                R0 ^= m_expKey[--keyCtr];
                InverseTransform(ref R0, ref R1, ref R2, ref R3);

                Ib2(ref R0, ref R1, ref R2, ref R3);
                R3 ^= m_expKey[--keyCtr];
                R2 ^= m_expKey[--keyCtr];
                R1 ^= m_expKey[--keyCtr];
                R0 ^= m_expKey[--keyCtr];
                InverseTransform(ref R0, ref R1, ref R2, ref R3);

                Ib1(ref R0, ref R1, ref R2, ref R3);
                R3 ^= m_expKey[--keyCtr];
                R2 ^= m_expKey[--keyCtr];
                R1 ^= m_expKey[--keyCtr];
                R0 ^= m_expKey[--keyCtr];
                InverseTransform(ref R0, ref R1, ref R2, ref R3);

                Ib0(ref R0, ref R1, ref R2, ref R3);

                // skip on last block
                if (keyCtr != LRD)
                {
                    R3 ^= m_expKey[--keyCtr];
                    R2 ^= m_expKey[--keyCtr];
                    R1 ^= m_expKey[--keyCtr];
                    R0 ^= m_expKey[--keyCtr];
                    InverseTransform(ref R0, ref R1, ref R2, ref R3);
                }
            }while (keyCtr != LRD);

            // last round
            IntUtils.Le32ToBytes(R3 ^ m_expKey[--keyCtr], Output, OutOffset + 12);
            IntUtils.Le32ToBytes(R2 ^ m_expKey[--keyCtr], Output, OutOffset + 8);
            IntUtils.Le32ToBytes(R1 ^ m_expKey[--keyCtr], Output, OutOffset + 4);
            IntUtils.Le32ToBytes(R0 ^ m_expKey[--keyCtr], Output, OutOffset);
        }