コード例 #1
0
        public void GetNthSubkeysLetters_Test()
        {
            var result1 = Kasiski.GetNthSubkeysLetters(1, 3, "ABCABCABC");

            Assert.AreEqual("AAA", result1);

            var result2 = Kasiski.GetNthSubkeysLetters(2, 3, "ABCABCABC");

            Assert.AreEqual("BBB", result2);

            var result3 = Kasiski.GetNthSubkeysLetters(3, 3, "ABCABCABC");

            Assert.AreEqual("CCC", result3);

            var result4 = Kasiski.GetNthSubkeysLetters(1, 5, "ABCDEFGHI");

            Assert.AreEqual("AF", result4);

            var result5 = Kasiski.GetNthSubkeysLetters(1, 3, "ABC ABC ABC");

            Assert.AreEqual("AAA", result5);
        }
コード例 #2
0
        /// <summary>
        ///     Performs a Kasiski attack provided a given key length
        /// </summary>
        /// <param name="cipherText"></param>
        /// <param name="keyLength"></param>
        /// <returns></returns>
        public static string AttackWithKeyLength(string cipherText, int keyLength)
        {
            var cipher        = new Vigenere();
            var allFreqScores = new List <Dictionary <char, int> >();

            for (var i = 1; i < keyLength + 1; i++)
            {
                var nthLetters = Kasiski.GetNthSubkeysLetters(i, keyLength, cipherText.ToUpper());

                var frequencyScore = new Dictionary <char, int>();
                foreach (var letter in Constants.Letters)
                {
                    var decryptedText = cipher.Decipher(nthLetters, Char.ToString(letter));

                    var score = Frequency.EnglishFreqMatchScore(decryptedText);
                    frequencyScore.Add(letter, score);
                }

                //Sort the dictionary by factor ocurrences descending
                var sortedCommonFactors = (from entry in frequencyScore orderby entry.Value descending select entry)
                                          .Take(4)
                                          .ToDictionary(pair => pair.Key, pair => pair.Value);

                allFreqScores.Add(sortedCommonFactors);
            }

            //Print our possible keys
            var position     = 1;
            var possibleKeys = new List <char[]>();

            foreach (var freq in allFreqScores)
            {
                _log.InfoFormat("Possible letters for letter {0} of the key: ", position);
                var possibleKeyOutput = new StringBuilder();
                var keyStore          = new char[freq.Keys.Count];
                var keyPosition       = 0;
                foreach (var keyPossible in freq.Keys)
                {
                    possibleKeyOutput.AppendFormat("{0}\t", keyPossible);
                    keyStore[keyPosition] = keyPossible;
                    keyPosition++;
                }
                possibleKeys.Add(keyStore);
                _log.InfoFormat(possibleKeyOutput.ToString());
                position++;
            }

            var keyCombinations = Combinator.Combinations(possibleKeys);

            var keyFound = false;
            var key      = string.Empty;

            //Go through the possible keys with the given freqency and determine if they produce
            //an English sentence.
            Parallel.ForEach(keyCombinations, (possibleKey, loopState) =>
            {
                //Stop processing if we find the possible key
                if (keyFound)
                {
                    loopState.Break();
                }

                _log.DebugFormat("Attempting with key: {0}", possibleKey);

                var decryptAttempt = cipher.Decipher(cipherText, possibleKey.ToString());

                if (!English.IsEnglish(decryptAttempt))
                {
                    return;
                }

                _log.InfoFormat("Found Possible Decryption Key: {0}", possibleKey);
                keyFound = true;
                key      = possibleKey.ToString();
            }
                             );

            return(key);
        }