private List <DifferentialCharacteristic> GetPossibleSubstitutionOutcomes(int inputDifference, Dictionary <int, List <SubstitutionBoxOutput> > sBoxOutputs, double previosProbability = 1)
        {
            List <List <SubstitutionBoxOutput> > allOutputs = sBoxOutputs.Select(k => k.Value).ToList();
            IEnumerable <IEnumerable <SubstitutionBoxOutput> > possibleOutcomes = allOutputs.CartesianProduct();

            List <DifferentialCharacteristic> outcomes = new List <DifferentialCharacteristic>();

            foreach (IEnumerable <SubstitutionBoxOutput> possibleOutcome in possibleOutcomes)
            {
                List <int> sBoxIndexes = sBoxOutputs.Keys.ToList();
                int        currentIndex = 0, output = 0;
                double     probability = previosProbability;
                foreach (SubstitutionBoxOutput sBoxOutput in possibleOutcome)
                {
                    output      |= (sBoxOutput.Output << ((_spn.SubstitutionBoxCount - 1 - sBoxIndexes[currentIndex++]) * Substitution.InputLength));
                    probability *= sBoxOutput.Bias;
                }

                if (probability > LOWER_BOUND_PROBABILITY)
                {
                    DifferentialCharacteristic characteristic = new DifferentialCharacteristic(inputDifference, output, probability);
                    characteristic.AddUsedSubstitionBoxForRound(possibleOutcome.ToList());

                    outcomes.Add(characteristic);
                }
            }

            return(outcomes);
        }
        private List <DifferentialCharacteristic> GetPermutatedOutcomes(List <DifferentialCharacteristic> characteristics)
        {
            List <DifferentialCharacteristic> permutatedOutcomes = new List <DifferentialCharacteristic>();

            foreach (DifferentialCharacteristic characteristic in characteristics)
            {
                int output = Permutation.Permutate(characteristic.OutputDifference);
                DifferentialCharacteristic newCharacteristic = new DifferentialCharacteristic(characteristic.InputDifference, output, characteristic.Probability);
                newCharacteristic.AddIntermediateOutputs(characteristic.IntermediateOutputs);
                newCharacteristic.AddUsedSubstitionBoxes(characteristic.UsedSubstitutionBoxes);

                permutatedOutcomes.Add(newCharacteristic);
            }

            return(permutatedOutcomes);
        }
        private List <DifferentialCharacteristic> GetCharacteristicForRound(DifferentialCharacteristic characteristic)
        {
            byte[] sBoxInputs = GetBytes(characteristic.OutputDifference);
            Dictionary <int, List <SubstitutionBoxOutput> > sBoxOutputs = GetSubstitutionOutputs(sBoxInputs);

            List <DifferentialCharacteristic> possibleOutcomes = GetPossibleSubstitutionOutcomes(characteristic.InputDifference, sBoxOutputs, characteristic.Probability);

            possibleOutcomes.ForEach(e => {
                e.AddIntermediateOutputs(characteristic.IntermediateOutputs);
                e.AddIntermediateOutput(characteristic.OutputDifference);

                List <List <SubstitutionBoxOutput> > usedBoxes = new List <List <SubstitutionBoxOutput> >(characteristic.UsedSubstitutionBoxes);
                usedBoxes.AddRange(e.UsedSubstitutionBoxes);
                e.SetUsedSubstitionBoxes(usedBoxes);
            });

            List <DifferentialCharacteristic> permutatedOutcomes = GetPermutatedOutcomes(possibleOutcomes);

            return(permutatedOutcomes);
        }
        private List <DifferentialCharacteristic> GetCharacteristicsForSPN(int inputDifference)
        {
            List <DifferentialCharacteristic> inputCharacteristics = new List <DifferentialCharacteristic>()
            {
                new DifferentialCharacteristic(inputDifference, inputDifference, 1)
            };

            for (int r = 1; r < _spn.RoundCount; r++)
            {
                for (int i = inputCharacteristics.Count - 1; i >= 0; i--)
                {
                    DifferentialCharacteristic inputCharacteristic = inputCharacteristics[i];
                    inputCharacteristics.RemoveAt(i);

                    List <DifferentialCharacteristic> outputCharacteristics = GetCharacteristicForRound(inputCharacteristic);

                    inputCharacteristics.AddRange(outputCharacteristics);
                }
            }

            return(inputCharacteristics);
        }