示例#1
0
        public static void GenerateStatistics()
        {
            // INITIALIZE
            var statistics = new Statistics()
            {
                GlobalFrequencies   = new Dictionary <char, double>(),
                PositionFrequencies = new Dictionary <char, double> [CellPatternSize]
            };

            for (var i = 0; i < CellPatternSize; i++)
            {
                statistics.PositionFrequencies[i] = new Dictionary <char, double>();
            }

            // Load
            var maps = LoadMaps();

            // Frequencies
            var totalDecodedLength = 0;
            var totalCoincidence   = 0.0;

            foreach (var map in maps)
            {
                totalCoincidence   += ComputeCoincidenceRate(map.DecodedData);
                totalDecodedLength += map.DecodedData.Length;
                for (var i = 0; i < map.DecodedData.Length; i++)
                {
                    var currentLetter = map.DecodedData[i];
                    if (!statistics.GlobalFrequencies.ContainsKey(currentLetter))
                    {
                        statistics.GlobalFrequencies[currentLetter] = 1;
                    }
                    else
                    {
                        statistics.GlobalFrequencies[currentLetter]++;
                    }
                    var patternIndex        = i % CellPatternSize;
                    var positionFrequencies = statistics.PositionFrequencies[patternIndex];
                    if (!positionFrequencies.ContainsKey(currentLetter))
                    {
                        positionFrequencies[currentLetter] = 1;
                    }
                    else
                    {
                        positionFrequencies[currentLetter]++;
                    }
                }
            }

            statistics.IndexOfCoincidence = totalCoincidence / maps.Count();

            // Normalize
            foreach (var k in statistics.GlobalFrequencies.Keys.ToList())
            {
                statistics.GlobalFrequencies[k] /= totalDecodedLength;
            }
            for (var i = 0; i < CellPatternSize; i++)
            {
                var positionFrequencies = statistics.PositionFrequencies[i];
                foreach (var k in positionFrequencies.Keys.ToList())
                {
                    positionFrequencies[k] /= totalDecodedLength / CellPatternSize;
                }
            }

            SaveStatistics(statistics);

            // Check
            //var globalTotalFreq = statistics.GlobalFrequencies.Values.Aggregate(0.0, (acc, freq) => acc + freq);
            //var positionTotalFreq = statistics.PositionFrequencies.Sum(p => p.Values.Aggregate(0.0, (acc, freq) => acc + freq));
        }
示例#2
0
 public static void SaveStatistics(Statistics statistics)
 {
     File.WriteAllText(StatisticsPath, JsonConvert.SerializeObject(statistics, Formatting.Indented));
 }
示例#3
0
        private static double ComputeError(string decrypted, int blockOffset, int blockSize, Statistics statistics)
        {
            var frequencies = GetFrequencies(decrypted);

            return(GetPositionError(decrypted, blockOffset, blockSize, statistics));
        }
示例#4
0
        public static double GetPositionError(string decrypted, int blockOffset, int blockSize, Statistics statistics)
        {
            var distance = 0.0;

            for (var i = 0; i < decrypted.Length; i++)
            {
                var absolutePosition   = blockSize * i + blockOffset;
                var positionStatistics = statistics.PositionFrequencies[absolutePosition % CellPatternSize];
                var currentData        = decrypted[i];
                if (positionStatistics.ContainsKey(currentData))
                {
                    distance += (1 - positionStatistics[currentData]);
                }
                else
                {
                    distance += 10;
                }
            }
            return(distance);
        }
示例#5
0
        private static ComputedKey GuessKey(string message, int keyLength, Statistics statistics)
        {
            var alternatives   = new Dictionary <int, List <(int, double)> >();
            var blockSize      = keyLength;
            var numberOfBlock  = (int)Math.Ceiling(message.Length / (double)blockSize);
            var offsetOverflow = message.Length % blockSize;
            var key            = new StringBuilder();

            for (var blockOffset = 0; blockOffset < blockSize; blockOffset++)
            {
                alternatives.Add(blockOffset, new List <(int, double)>());
                var bestError = double.MaxValue;
                var bestXor   = -1;
                // Only between thoses
                for (var xorKey = MinKeyXor; xorKey <= MaxKeyXor; xorKey++)
                {
                    var numberOfBlockAffected = offsetOverflow > 0 ?
                                                blockOffset > offsetOverflow ? numberOfBlock - 1 : numberOfBlock : numberOfBlock;
                    var decryptedBlock = new char[numberOfBlockAffected];
                    for (var blockNumber = 0; blockNumber < numberOfBlock; blockNumber++)
                    {
                        var absoluteOffset = blockNumber * blockSize + blockOffset;
                        if (absoluteOffset < message.Length)
                        {
                            var currentData = message[absoluteOffset];
                            decryptedBlock[blockNumber] = (char)(currentData ^ xorKey);
                        }
                    }
                    var decrypted = HttpUtility.UrlDecode(new string(decryptedBlock));
                    var error     = ComputeError(decrypted, blockOffset, blockSize, statistics);
                    if (error <= bestError)
                    {
                        if (error == bestError)
                        {
                            if (bestXor != -1)
                            {
                                alternatives[blockOffset].Add((xorKey, error));
                            }
                        }
                        else
                        {
                            var clampedValue = error * ErrorClamp;
                            alternatives[blockOffset].RemoveAll(x => x.Item2 > clampedValue);
                            alternatives[blockOffset].Add((xorKey, error));
                        }
                        bestError = error;
                        bestXor   = xorKey;
                    }
                }
                key.Append((char)bestXor);
            }
            // Shift back the key with its checksum
            var computedKey = key.ToString();
            int shift       = int.Parse(Checksum(computedKey), NumberStyles.HexNumber) * 2;
            var finalKey    = RightRotateShift(computedKey, shift);

            return(new ComputedKey
            {
                Value = finalKey,
                Alternatives = alternatives.Where(x => x.Value.Count > 1).ToDictionary(x => x.Key, x => x.Value)
            });
        }