Exemple #1
0
        public SymmetricCipherResult ProcessPayload(IFfxModeBlockCipherParameters param)
        {
            var key = param.Key.ToBytes();

            var engineParam = new EngineInitParameters(param.Direction, key, param.UseInverseCipherMode);

            _engine.Init(engineParam);

            CheckPayloadRequirements(param.Payload);

            if (param.Direction == BlockCipherDirections.Encrypt)
            {
                return(new SymmetricCipherResult(Encrypt(param)));
            }

            return(new SymmetricCipherResult(Decrypt(param)));
        }
Exemple #2
0
 protected abstract BitString Decrypt(IFfxModeBlockCipherParameters param);
        protected override BitString Decrypt(IFfxModeBlockCipherParameters param)
        {
            var mode = _factory.GetStandardCipher(_engine, BlockCipherModesOfOperation.Ecb);

            var X = NumeralString.ToNumeralString(param.Payload);
            var n = X.Numbers.Length;

            // 1. Let u = ⌈n / 2⌉; v = n – u.
            var u = n.CeilingDivide(2);
            var v = n - u;

            // 2. Let A = X[1..u]; B = X[u + 1..n].
            var A = new NumeralString(X.Numbers.Take(u).ToArray());
            var B = new NumeralString(X.Numbers.Skip(u).Take(v).ToArray());

            // Let TL = T[0..31] and TR = T[32..63]
            var TL = param.Iv.Substring(32, 32);
            var TR = param.Iv.Substring(0, 32);

            // 4. For i from 0 to 7:
            for (var i = NumberOfRounds - 1; i >= 0; i--)
            {
                // i. If i is even, let m = u and W = TR, else let m = v and W = TL.
                //     v. If i is even, let m = u; else, let m = v.
                var m = i % 2 == 0 ? u : v;
                var W = i % 2 == 0 ? TR : TL;

                // ii. Let P = W ⊕ [i] 4 || [NUMradix(REV(B))]12 .
                var numA = new BitString(_ffInternals.Num(param.Radix, _ffInternals.Rev(A)));
                if (numA.BitLength < 12 * BitsInByte)
                {
                    var bitsToPrepend = new BitString(12 * BitsInByte - numA.BitLength);
                    numA = bitsToPrepend.ConcatenateBits(numA);
                }

                var P = W.XOR(new BitString(new byte[3]).ConcatenateBits(((byte)i).ToBitString()))
                        .ConcatenateBits(numA);

                // iii. Let S = REVB(CIPHREVB(K) REVB(P)).
                var S = _ffInternals.RevB(mode.ProcessPayload(
                                              new ModeBlockCipherParameters(
                                                  BlockCipherDirections.Encrypt,
                                                  _ffInternals.RevB(param.Key),
                                                  _ffInternals.RevB(P))).Result);

                // iv. Let y = NUM(S).
                var y = _ffInternals.Num(S);

                // v. Let c = (NUMradix (REV(B)) - y) mod radix m .
                var c = (_ffInternals.Num(param.Radix, _ffInternals.Rev(B)) - y).PosMod(BigInteger.Pow(param.Radix, m));

                // vi. Let C = REV(STRm radix(c)).
                var C = _ffInternals.Rev(_ffInternals.Str(param.Radix, m, c));

                // vii. Let B = A.
                B = A;

                // viii. Let A = C.
                A = C;
            }

            // 5. Return A || B.
            return(NumeralString.ToBitString(A)
                   .ConcatenateBits(NumeralString.ToBitString(B)));
        }
        protected override BitString Encrypt(IFfxModeBlockCipherParameters param)
        {
            var mode = _factory.GetStandardCipher(_engine, BlockCipherModesOfOperation.Ecb);

            var X = NumeralString.ToNumeralString(param.Payload);
            var n = X.Numbers.Length;
            var t = param.Iv.BitLength / BitsInByte;

            // 1. Let u = Floor(n/2); v = n – u.
            var u = n / 2;
            var v = n - u;

            // 2. Let A = X[1..u]; B = X[u + 1..n].
            var A = new NumeralString(X.Numbers.Take(u).ToArray());
            var B = new NumeralString(X.Numbers.Skip(u).Take(v).ToArray());

            // 3. Let b = Ceiling(Ceiling(v×LOG(radix))/8).
            var b = (int)System.Math.Ceiling(System.Math.Ceiling(v * System.Math.Log(param.Radix, 2)) / 8);

            // 4. Let d = 4*Ceiling(b/4) + 4.
            var d = 4 * b.CeilingDivide(4) + 4;

            // the number times to iterate through the concatenation of cipher iterator blocks
            var jCount = d.CeilingDivide(16);

            // 5. Let P = [1] 1 || [2] 1 || [1] 1 || [radix] 3 || [10] 1 || [u mod 256] 1 || [n] 4 || [t] 4.
            var pBytes = new byte[_engine.BlockSizeBytes];

            pBytes[0] = 0x01;
            pBytes[1] = 0x02;
            pBytes[2] = 0x01;
            // 3 bytes for radix, but radix is capped at 16 bits (2^16), so add a 0 byte
            pBytes[3] = 0x00;
            Array.Copy(BitString.To32BitString(param.Radix).GetLeastSignificantBits(16).ToBytes(), 0, pBytes, 4, 2);
            pBytes[6] = 0x0a;
            pBytes[7] = (byte)(u % 256);
            Array.Copy(BitString.To32BitString(n).ToBytes(), 0, pBytes, 8, 4);
            Array.Copy(BitString.To32BitString(t).ToBytes(), 0, pBytes, 12, 4);
            var P = new BitString(pBytes);

            // 6. For i from 0 to 9:
            for (var i = 0; i < NumberOfRounds; i++)
            {
                // i. Let Q = T || [0] (−t−b−1) mod 16 || [i] 1 || [NUMradix(B)]b.
                var numB = new BitString(_ffInternals.Num(param.Radix, B));
                if (numB.BitLength < b * BitsInByte)
                {
                    var bitsToPrepend = new BitString(b * BitsInByte - numB.BitLength);
                    numB = bitsToPrepend.ConcatenateBits(numB);
                }

                var Q = new BitString(0)
                        .ConcatenateBits(param.Iv)
                        .ConcatenateBits(new BitString((-t - b - 1).PosMod(16) * BitsInByte))
                        .ConcatenateBits(((byte)i).ToBitString())
                        .ConcatenateBits(numB.GetMostSignificantBits(b * BitsInByte));

                //     ii. Let R = PRF(P || Q).
                var R = _ffInternals.Prf(P.ConcatenateBits(Q), param.Key);

                //     iii. Let S be the first d bytes of the following string of Ceiling(d/16) blocks:
                //         R || CIPHK(R Å [1]16) || CIPHK (R Å [2]16) … CIPHK(R Å [éd/16ù–1]).
                var S = R.GetDeepCopy();
                for (var j = 1; j < jCount; j++)
                {
                    var pad = BitString.To32BitString(j).PadToModulusMsb(_engine.BlockSizeBits);
                    S = S.ConcatenateBits(
                        mode.ProcessPayload(
                            new ModeBlockCipherParameters(
                                BlockCipherDirections.Encrypt,
                                param.Key,
                                R.XOR(pad))).Result
                        );
                }
                S = S.GetMostSignificantBits(d * BitsInByte);

                //     iv. Let y = NUM(S).
                var y = _ffInternals.Num(S);

                //     v. If i is even, let m = u; else, let m = v.
                var m = i % 2 == 0 ? u : v;

                //     vi. Let c = (NUMradix (A)+y) mod radix m .
                var c = (_ffInternals.Num(param.Radix, A) + y).PosMod(BigInteger.Pow(param.Radix, m));

                //     vii. Let C = STR m radix (c).
                var C = _ffInternals.Str(param.Radix, m, c);

                //     viii. Let A = B.
                A = B;
                //     ix. Let B = C.
                B = C;
            }

            // 7. Return A || B.
            return(NumeralString.ToBitString(A)
                   .ConcatenateBits(NumeralString.ToBitString(B)));
        }