Esempio n. 1
0
        static void Main(string[] args)
        {
            //Example Enciphered Text
            const string cipherText = "Ar op chmrivv tfh ofvx nyneiksfnv cxsvu dc ysxjvv zszg di lgqg rhoagg kltl M'xv fxwr vlvgari fzxj mp dc farf vzxj wkegx. \"Olgeiowv afy ywin cmdw gtzxbumbzrz sra frx,\" zi vfpw ei, \"llwm jiovquwv vyem spn klx hiqgpx ar vyml ostch aszge'x ash vyi tvzcextyiu kltl cql'zx zef.\"";

            //Example of how to execute a known plaintext attack
            _log.Info("-------- KNOWN PLAINTEXT ATTACK --------");
            var possibleKeys = KnownPlaintextAttack.AttackWithKnownPlaintext(cipherText, "the");

            foreach (var key in possibleKeys)
            {
                _log.InfoFormat("Possible Key: {0}", key);
                _log.InfoFormat(VigenereEngine.Decipher(cipherText, key));
            }

            //Example of how to execute a Kasiski/Babbage Analysis & Attack
            _log.Info("-------- KASISKI ATTACK --------");
            var likelyKeyLengths = Kasiski.KasiskiExamination(cipherText);

            foreach (var keyLength in likelyKeyLengths)
            {
                _log.InfoFormat("Attempting hack with key length {0} ({1} possible keys)", keyLength, Math.Pow(Convert.ToDouble(keyLength), Convert.ToDouble(Constants.NumMostFreqLetters)));
                var foundKey = KasiskiAttack.AttackWithKeyLength(cipherText, keyLength);

                if (!string.IsNullOrEmpty(foundKey))
                {
                    _log.InfoFormat("Decrypted Text: {0}", new Vigenere().Decipher(cipherText, foundKey));
                    System.Console.ReadKey();
                    return;
                }
            }
        }
Esempio n. 2
0
        public void DecipherWithKey_Test()
        {
            var cipher = new Vigenere();

            var output = cipher.Decipher("mlw JNmuD uvGPG jGQ CyEIL sNxK xzx EeRR wsy", "TEST");

            const string expected = "The quick brown fox jumps over the lazy dog";

            Assert.AreEqual(expected.ToLower(), output.ToLower());
        }
Esempio n. 3
0
        /// <summary>
        ///     Attacks a Cipher with a known section of plaintext.
        /// </summary>
        /// <param name="message"></param>
        /// <param name="plainText"></param>
        /// <returns></returns>
        public static List <string> AttackWithKnownPlaintext(string message, string plainText)
        {
            var possiblePassword       = new StringBuilder();
            var possiblePasswords      = new List <string>();
            var foundPlainTextPassword = new List <string>();
            var cipher = new Vigenere();

            if (message.IndexOf(' ') > -1)
            {
                var decryptedWords = message.ToUpper().Split(' ');

                //Find words of the same size as the plainText and determine the cipher order
                foreach (var word in decryptedWords)
                {
                    if (word.Length == plainText.Length)
                    {
                        for (var i = 0; i < word.Length; i++)
                        {
                            //Determine difference between decryption and plaintext
                            var decryptIndex   = Helpers.Constants.Letters.IndexOf(word[i]);
                            var plaintextIndex = Helpers.Constants.Letters.IndexOf(plainText.ToUpper()[i]);

                            //Wraparound occured
                            var keyCharacterValue = decryptIndex - plaintextIndex;

                            keyCharacterValue %= Helpers.Constants.Letters.Length;

                            if (keyCharacterValue < 0)
                            {
                                keyCharacterValue += Helpers.Constants.Letters.Length;
                            }

                            possiblePassword.Append(Helpers.Constants.Letters[keyCharacterValue]);
                        }
                    }

                    possiblePasswords.Add(possiblePassword.ToString());
                    possiblePassword.Clear();
                }
            }

            //Remove empty strings from possible passwords
            possiblePasswords.RemoveAll(s => s == string.Empty);

            //Find words that contain the discinct letters in the possible passwords
            var possiblePlainTextPasswords = (from word in possiblePasswords
                                              let distinct = word.Distinct().ToArray()
                                                             from dictWordList in English.SortedDictionary.OrderByDescending(k => k.Key)
                                                             from dictWord in dictWordList.Value
                                                             let intersection = word.Intersect(dictWord)
                                                                                where intersection.Count() == distinct.Length
                                                                                select dictWord).ToList();

            //Now Decipher - use those plainTextPasswords to find the possible real one..
            Parallel.ForEach(possiblePlainTextPasswords, key =>
            {
                if (English.IsEnglish(cipher.Decipher(message, key)))
                {
                    foundPlainTextPassword.Add(key);
                }
            });

            return(foundPlainTextPassword);
        }
Esempio n. 4
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);
        }