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; } } }
public void FindRepeatSequencesSpacings_Test() { var result1 = Kasiski.FindRepeatSequencesSpacings( "PPQCAXQVEKGYBNKMAZUYBNGBALJONITSZMJYIMVRAGVOHTVRAUCTKSGDDWUOXITLAZUVAVVRAZCVKBQPIWPOU"); var expected = new Dictionary <string, List <int> >() { { "YBN", new List <int> { 8 } }, { "AZU", new List <int> { 48 } }, { "VRA", new List <int> { 8, 32, 24 } } }; CollectionAssert.AreEqual(expected["YBN"], result1["YBN"]); CollectionAssert.AreEqual(expected["AZU"], result1["AZU"]); CollectionAssert.AreEqual(expected["VRA"], result1["VRA"]); Assert.AreEqual(expected.Count, result1.Count); }
public void TestEncode() { Kasiski kasiski = new Kasiski(); IEnumerable <ValueTuple <int, int, double> > check = kasiski.Decode("LFWKIMJCLPSISWKHJOGLKMVGURAGKMKMXMAMJCVXWUYLGGIISW" + "ALXAEYCXMFKMKBQBDCLAEFLFWKIMJCGUZUGSKECZGBWYMOACFV" + "MQKYFWXTWMLAIDOYQBWFGKSDIULQGVSYHJAVEFWBLAEFLFWKIM" + "JCFHSNNGGNWPWDAVMQFAAXWFZCXBVELKWMLAVGKYEDEMJXHUXD" + "AVYXL"); Assert.IsNotNull(check); }
public void KasiskiExamination_Test() { var result1 = Kasiski.KasiskiExamination( "PPQCAXQVEKGYBNKMAZUYBNGBALJONITSZMJYIMVRAGVOHTVRAUCTKSGDDWUOXITLAZUVAVVRAZCVKBQPIWPOU"); var expected = new List <int> { 2, 4, 8 }; CollectionAssert.AreEqual(expected, result1); }
public IEnumerable <ValueTuple <int, double> > GetKasiskiResult(string encodedText, string alphabet) { var repository = new Repository(); var result = repository.GetKasiskiResult(encodedText); if (ReferenceEquals(result, null)) { var kasiski = new Kasiski(alphabet); var res = kasiski.Decode(encodedText); result = repository.AddKasiskiResult(encodedText, res); } return(result.Select(item => (item.Size, item.Probability))); }
public void GetUsefulFactors_Test() { var result1 = Kasiski.GetUsefulFactors(48); var expected = new List <int>() { 2, 3, 4, 6, 8, 12, 16 }; CollectionAssert.AreEqual(expected, result1); }
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); }
/// <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); }