public WordsCompleter(string[] words, Dictionary<char, char> substitutions, Storage.Languages language) { this.originWords = words; this.originSubs = substitutions; this.substitutions = substitutions; dictionary = Dictionary.Create(Storage.GetLangChar(language).Dictionary, x => x.Length); }
public static CrackResult[] Attack(string ciphertext, Cipher[] ciphers, Storage.Languages language) { var crackResults = GetCrackResults(ciphertext, ciphers, language); LangCharacteristic langChar = Storage.GetLangChar(language); var results = crackResults.OrderBy(x => Analyse.SimilarityIndex(x.opentext, langChar)).ToArray(); return results; }
public void Attack(string ciphertext, Cipher[] ciphers, Storage.Languages language) { GetCrackResults(ciphertext, ciphers, language, crackResults => { LangCharacteristic langChar = Storage.GetLangChar(language); var results = crackResults.Where(x => x != null) .OrderBy(x => Analyse.SimilarityIndex(x.opentext, langChar)) .ToArray(); results = FixVigenere(results); finish(results.First()); }); }
/// <summary> /// Provede útok testováním všech dostupných klíčů /// a následně vybere nejpravděpodobnější variantu. /// </summary> /// <param name="packet"></param> /// <returns></returns> public List<string> BruteForceAttack(string ciphertext, Storage.Languages language) { Dictionary<char, double> probability = new Dictionary<char, double>(); Caesar caesar = new Caesar(); string opentext; Analyse.DoAlphabet(letter => { opentext = caesar.Decrypt(ciphertext, letter.ToString()); probability[letter] = Analyse.SimilarityIndex(Analyse.NormalizeText(opentext, Analyse.TextTypes.WithoutSpacesLower), Storage.GetLangChar(language)); }); var resultPacket = probability.OrderBy(x => x.Value).ToArray()[0].Key; return new List<string>() { resultPacket.ToString() }; }
/// <summary> /// Provede frekvenční analýzu na slovech, tj. text musí obsahovat mezery /// jako hranice pro slova. /// </summary> /// <param name="ciphertext">Šifrový text</param> /// <param name="language">Jazyk, který byl text zašifrován</param> /// <returns>Seznam možných klíčů</returns> public List<string> FrequencyAnalysisWithSpaces(string ciphertext, Storage.Languages language) { string key; string[] words = TextAnalysis.ToWords(ciphertext); UniqueWords uniqueWords = new UniqueWords(Storage.GetLangChar(language).UniqueWords); var result = uniqueWords.GetLettersSubst(words); if (result != null) { WordsCompleter completer = new WordsCompleter(words, result, language); var subst = completer.Complete(); key = GetKey(subst); } else { throw new Exceptions.MatchNotFound(); } return new List<string>() { key }; }
private static List<CrackResult> GetCrackResults(string ciphertext, Cipher[] ciphers, Storage.Languages language) { List<CrackResult> results = new List<CrackResult>(); foreach (var cipher in ciphers) { try { var keys = cipher.Crack(ciphertext, 0, language); if (keys.Count > 0) { var result = new CrackResult(); result.key = keys[0]; result.opentext = cipher.Decrypt(ciphertext, result.key); result.cipher = cipher; results.Add(result); } } catch (Exceptions.MatchNotFound) { } } return results; }
private List<string> BruteForceAttack(string ciphertext, Storage.Languages language, int[] keysLength) { ciphertext = Analyse.NormalizeText(ciphertext, Analyse.TextTypes.WithoutSpacesLower); Caesar caesar = new Caesar(); Dictionary<int, string> crackedKeys = new Dictionary<int, string>(); foreach(int keyLength in keysLength) { char[][] splitedChars = new char[keyLength][]; for (int i = 0; i < keyLength; i++) splitedChars[i] = GetNthChars(ciphertext, keyLength, i); char[] crackKeys = new char[keyLength]; for (int i = 0; i < keyLength; i++) { try { crackKeys[i] = caesar.Crack(Analyse.NormalizeText(new string(splitedChars[i]), Analyse.TextTypes.WithoutSpacesUpper), Caesar.TriangleID, language).First()[0]; } catch (Exceptions.MatchNotFound) { crackKeys[i] = '?'; } } crackedKeys[keyLength] = new string(crackKeys); } var possKeys = crackedKeys.Where(x => x.Value.Length > 0).Select(x => x.Value).ToArray(); Dictionary<string, double> simIndexes = new Dictionary<string, double>(); for (int i = 0; i < possKeys.Length; i++) { string openttext = Decrypt(ciphertext, possKeys[i]); double simIndex = Analyse.SimilarityIndex(openttext, Storage.GetLangChar(language)); simIndexes[possKeys[i]] = simIndex; } var result = simIndexes.OrderBy(x => x.Value).Select(x => x.Key).ToList(); return result; }
/// <summary> /// Metoda použitá v testování /// </summary> /// <param name="ciphertext"></param> /// <param name="language"></param> /// <returns></returns> public string UnitTextFrequency(string ciphertext, Storage.Languages language) { return FrequencyAnalysisWithSpaces(ciphertext, language)[0]; }
/// <summary> /// Provede útok na šifru pomocí frekvenční analýzy. /// </summary> /// <param name="packet">Balíček obsahující zašifrovaný text</param> /// <returns>Balíček obsahující dešifrovaný text a klíč</returns> private List<string> FrequencyAnalysis(string ciphertext, Storage.Languages language) { int spacesCount = ciphertext.Count(' '); if (spacesCount > 0 && (ciphertext.Length / spacesCount < 15)) { return FrequencyAnalysisWithSpaces(ciphertext, language); } else { throw new Exceptions.MatchNotFound(); } }
private void GetCrackResults(string ciphertext, Cipher[] ciphers, Storage.Languages language, Action<CrackResult[]> afterCrack) { int threadsCount = ciphers.Length; CrackResult[] results = new CrackResult[threadsCount]; bool[] syncArray = new bool[threadsCount].Fill(false); object progressLockObject = new object(); object endTestLockObject = new object(); threadsCount.Times(i => { Thread thread = new Thread(() => { try { var currentCipher = ciphers[i]; var keys = currentCipher.Crack(ciphertext, 0, language); if (keys.Count > 0) { var crackResult = new CrackResult(); crackResult.key = keys[0]; crackResult.opentext = currentCipher.Decrypt(ciphertext, crackResult.key); crackResult.cipher = currentCipher; results[i] = crackResult; } else { throw new Exceptions.MatchNotFound(); } lock (progressLockObject) { progress(); } } catch (Exceptions.MatchNotFound) { lock (progressLockObject) { progress(); } } lock (endTestLockObject) { syncArray[i] = true; if (syncArray.All(x => x)) { afterCrack(results); } } }); thread.Priority = ThreadPriority.Lowest; thread.IsBackground = true; addThread(thread); thread.Start(); }); }
/// <summary> /// Násilné dešifrování zašifrovaného textu bez znalosti klíče. /// </summary> /// <param name="CipherText">Text, který se pokoušíme dešifrovat</param> /// <returns>Otevřený text</returns> public List<string> Crack(string ciphertext, int attackType, Storage.Languages language) { return CrackMethods[attackType](ciphertext, language); }
/*********************************************/ /*********** One big word attack *************/ /*********************************************/ private List<string> BigWordAttack(string ciphertext, Storage.Languages language) { ciphertext = Analyse.NormalizeText(ciphertext, Analyse.TextTypes.WithoutSpacesLower); var keyLengths = GetKeyLengths(ciphertext); LangCharacteristic lang = Storage.GetLangChar(language); List<string> possKeys = new List<string>(); foreach (int keyLength in keyLengths) { string[] columns = GetDecryptColumns(ciphertext, keyLength); string[] rows = GetRows(columns); DictionaryAttack attack = new DictionaryAttack(); string[] keys = attack.GetKeys(rows, lang.TopWords); string[] orderedKeys = OrderKeys(keys, ciphertext, lang); if (orderedKeys.Length > 0) possKeys.Add(orderedKeys[0]); } if (possKeys.Count > 0) { string[] finalKeys = OrderKeys(possKeys.ToArray(), ciphertext, lang); return finalKeys.ToList(); } throw new Exceptions.MatchNotFound(); }
/// <summary> /// Crackovací metoda, která se nejprve pokusí zjistit délku klíče /// a následně se pokusí prolomit šifru standardně. /// </summary> /// <param name="ciphertext"></param> /// <param name="language"></param> /// <returns></returns> private List<string> TestKeyLengthAttack(string ciphertext, Storage.Languages language) { KeyLength keyLength = new KeyLength(); var keysLength = keyLength.GetKeyLength(ciphertext).Take(6).ToArray(); if (keysLength.Length == 0) keysLength = new int[MaxKeyLength - 2].Fill(x => x + 2); return BruteForceAttack(ciphertext, language, keysLength); }
/*********** Brute force attack **************/ private List<string> BruteForceAttack(string ciphertext, Storage.Languages language) { int keyLength = 7; string[] columns = GetDecryptColumns(ciphertext, keyLength); string[] rows = GetRows(columns); string firstLine = rows[0]; var variations = Combinatorics.Permutation(firstLine.ToCharArray().ToList()); int res = variations.Count(x => x.Implode() == "namstar"); List<string> canonicalKey = Storage.Letters.Take(keyLength).ToList(); var permKeys = Combinatorics.Permutation(canonicalKey); Dictionary<string, string> possTexts = new Dictionary<string, string>(); foreach (var key in permKeys) { string k = key.Implode(); possTexts[k] = Decrypt(ciphertext, k); } var langChar = Storage.GetLangChar(language); var result = possTexts.OrderBy(x => Analyse.SimilarityIndex(x.Value, langChar)).Take(10).ToDictionary(x => x.Key, x => x.Value); throw new Exceptions.MatchNotFound(); }
/*********** First Letters Attack ************/ // TODO: ostatní jazyky nemají TopWords!!! private List<string> FirstLettersAttack(string ciphertext, Storage.Languages language) { var keyLengths = GetKeyLengths(ciphertext); int minWordLength = 3; int testStringLength = 20; double minSuccess = (double)20 / (double)1300; foreach (int keyLength in keyLengths) { if (keyLength < 10) continue; string[] columns = GetDecryptColumns(ciphertext, keyLength); string[] rows = GetRows(columns); string[] sentence = rows.Take((int)Math.Ceiling((double)testStringLength / (double)keyLength)).ToArray(); var lang = Storage.GetLangChar(language); DictionaryAttack firstAttack = new DictionaryAttack(); string[] topWords = lang.TopWords.Where(x => x.Length >= minWordLength).ToArray(); string[] topTopWords = topWords.Take(100).ToArray(); var keys = firstAttack.CrossFilter(sentence, topWords); var opentexts = new string[keys.Length]; for (int i = 0; i < keys.Length; i++) opentexts[i] = Decrypt(ciphertext, keys[i]); Dictionary<string, int> probabilities = new Dictionary<string, int>(); for (int i = 0; i < keys.Length; i++) probabilities[keys[i]] = Analyse.WordsContains(opentexts[i], topTopWords); var resultKeys = probabilities.OrderByDescending(x => x.Value).ToDictionary(x => x.Key, x => x.Value); var isthere = opentexts.Where(x => x.Contains("oznamenipodala")).Count() == 1; if(resultKeys.Count > 0 && ((double)resultKeys.First().Value / (double)1300) > minSuccess) return resultKeys.Take(10).Select(x => x.Key).ToList(); } throw new Exceptions.MatchNotFound(); }
private List<string> BruteForceAttack(string ciphertext, Storage.Languages language) { int[] keysLength = new int[MaxKeyLength - 2].Fill(x => x + 2); return BruteForceAttack(ciphertext, language, keysLength); }
/// <summary> /// Provede útok na šifru pomocí frekvenční analýzy. /// </summary> /// <param name="packet">Balíček obsahující zašifrovaný text</param> /// <returns>Balíček obsahující dešifrovaný text a klíč</returns> private List<string> FrequencyAnalysis(string ciphertext, Storage.Languages language) { int spacesCount = ciphertext.Count(' '); if (spacesCount > 0 && (ciphertext.Length / spacesCount < 15)) { return FrequencyAnalysisWithSpaces(ciphertext, language); } else { /*var lang = Storage.GetLangChar(language); TopLetters topLettersAttack = new TopLetters(); var topLetters = topLettersAttack.Get(ciphertext, lang); SamePatternAttack samePattern = new SamePatternAttack(); var substitutions = samePattern.GetKey(ciphertext, lang, topLetters); var key = GetReverseKey(substitutions); return new List<string>() { key };*/ throw new Exceptions.MatchNotFound(); } }
/*********** test key length attack *******************/ private List<string> TestKeyLength(string ciphertext, Storage.Languages language) { int averageKeyLength = 10; int minSentenceLength = 40; var keyLengths = Maths.AllDivisors(ciphertext.Length); var orderKeyLengths = keyLengths.OrderBy(x => Math.Abs(x - averageKeyLength)).ToArray(); foreach (int keyLength in orderKeyLengths) { string[] columns = GetDecryptColumns(ciphertext, keyLength); string sentence = GetOpentext(columns).Take(minSentenceLength); var lang = Storage.GetLangChar(language); DictionaryAttack attack = new DictionaryAttack(lang.Dictionary, lang.SortedDictionary); attack.Start(sentence, keyLength); } return new List<string>() { "abc" }; }
/// <summary> /// Vrátí pole klíčů, které jsou možnými klíči dané šifry /// </summary> /// <param name="packet">Informace o šifrovém textu</param> /// <returns>Pole klíčů</returns> private char[] GetTriangle(string ciphertext, bool orderByDescending, Storage.Languages language) { char[] topCiphertextLetters; char[] topLanguagesLetters; int max = 9; if (orderByDescending) { topCiphertextLetters = Analyse.CharsRelativeOccurrence(ciphertext.ToLower()).OrderByDescending(x => x.Value).Take(max).Select(x => x.Key.ToString().ToLower()[0]).ToArray(); topLanguagesLetters = Storage.GetLangChar(language).Letters.Where(x => x.Key != " ").OrderByDescending(x => x.Value).Take(3).Select(x => x.Key.ToLower()[0]).ToArray(); } else { topCiphertextLetters = Analyse.CharsRelativeOccurrence(ciphertext.ToLower()).OrderBy(x => x.Value).Take(max).Select(x => x.Key.ToString().ToLower()[0]).ToArray(); topLanguagesLetters = Storage.GetLangChar(language).Letters.Where(x => x.Key != " ").OrderBy(x => x.Value).Take(3).Select(x => x.Key.ToLower()[0]).ToArray(); } List<char[]> triples = FindEquivalentTriple(topLanguagesLetters, topCiphertextLetters); if (triples.Count == 0) throw new Exceptions.MatchNotFound(); return GetKeysFromTriples(topLanguagesLetters[0], triples); }
/// <summary> /// Provede trojúhelníkový útok na šifru /// </summary> /// <param name="packet"></param> /// <returns></returns> public List<string> TriangleAttack(string ciphertext, Storage.Languages language) { bool modern = true; if (modern) { ciphertext = Analyse.NormalizeText(ciphertext, Analyse.TextTypes.WithoutSpacesLower); int polygonSize = 3; int complementSize = 10; var topLetters = Storage.GetLangChar(language).Letters.OrderByDescending(x => x.Value).Take(polygonSize).Select(x => x.Key[0]).ToArray(); var bottomLetters = Storage.GetLangChar(language).Letters.OrderBy(x => x.Value).Take(polygonSize).Select(x => x.Key[0]).ToArray(); var letters = TextAnalysis.GetOccurrence(ciphertext, 1); var topTextLetters = letters.OrderByDescending(x => x.Value).Take(complementSize).Select(x => x.Key[0]).ToArray(); var bottomTextLetters = letters.OrderBy(x => x.Value).Take(complementSize).Select(x => x.Key[0]).ToArray(); var keysTop = GetPolygonKeys(topTextLetters, topLetters, complementSize); var keysBottom = GetPolygonKeys(bottomTextLetters, bottomLetters, complementSize); if (keysTop.Length == 0) throw new Exceptions.MatchNotFound(); var interKeys = keysBottom.Intersect(keysTop).ToList(); if (interKeys.Count > 0) { return interKeys.Select(x => x.ToString()).ToList(); } else { var unionKeys = keysBottom.Union(keysTop).Select(x => x.ToString()).ToList(); if (unionKeys.Count > 0) { return unionKeys; } else { throw new Exceptions.MatchNotFound(); } } } else { char[] keysTop = GetTriangle(ciphertext, true, language); char[] keysLess = GetTriangle(ciphertext, false, language); char[] universalKeys = keysLess.Intersect(keysTop).ToArray(); string key; if (universalKeys.Length == 1) { key = universalKeys[0].ToString(); return new List<string>() { key }; } else { char[] unionsKeys = keysLess.Union(keysTop).ToArray(); if (unionsKeys.Length != 0) { key = unionsKeys[0].ToString(); return new List<string>() { key }; } } throw new Exceptions.MatchNotFound(); } }