
Лабораторная работа №2 Головков И. Е
..docxФЕДЕРАЛЬНОЕ Государственное АВТОНОМНОЕ образовательное УЧРЕЖДЕНИЕ ВЫСШЕГО образования
«БЕЛГОРОДСКИЙ ГОСУДАРСТВЕННЫЙ НАЦИОНАЛЬНЫЙ
ИССЛЕДОВАТЕЛЬСКИЙ УНИВЕРСИТЕТ»
(НИУ «БелГУ»)
ИНСТИТУТ ИНЖЕНЕРНЫХ И ЦИФРОВЫХ ТЕХНОЛОГИЙ
Отчет по лабораторной работе № 2
Вариант № 6
Тема работы «Методы анализа шифрованных текстов, поиск ключа шифрования»
по дисциплине «Методы и средства защиты информации»
студента очного отделения
3 курса 12002108 группы
Головкова Игоря Евгеньевича
Проверил:
доц. Титов А. И.
БЕЛГОРОД
2023
Цель работы: научиться выявлять закономерности в шифрованном тексе. Получать статистические данные включений определённых символов. Определять ключ шифрования, основываясь на полученной статистике.
Ход работы:
Получить шифрованный текст
Разработать алгоритм выявления включений, основываясь на полученном шифр тексте.
Сопоставить полученные статистические данные
Попытаться выявить часть ключа шифрования или алгоритма шифрования (таблицы замен)
Попытаться расшифровать полученное сообщение
Для расшифровки был получен исходный текст (далее для краткости приведена его часть): — айо, ий ъйчркш, — чьбдбпиб боъйхшё юъпябпёшпёбъ. — н ч фшбабп зйоббъибп ьбхоп ипдбёяш ий ябшёпчр. фы ъйчркш чбёёшчиб щпёп, п биш кибп ъчйёяш ябъбёриш бчошъшёшчр. чёычо ь жьбобйжпё, ъб ъчй ишгп чйкр ёйо, ъчйёб обёрдб яъш бшвш (йчёп ий чхпошор йэй бяибёб обйорйёб чёжхшь, ъйчркш, ъьббхйк, яъжчкычёйиибёб): ъ ьйбъып бшв — яъш кйчьэш чьжчоь ьбчёй ишгйёб жбшдш, обохшч щй ьб ьбпйвяй ъ яйбйъил, п ъбо ойьйбйгипп ьбчёйяипп чёжхшп…
Также были даны относительные частоты появления русских букв (Буква/Частота): о/0,09; в/0,038; з/0,016; ж/0,007; е, ё/0,072; л/0,035; ы/0,016; ш/0,006; а/0,062; к/0,028; б/0,014; ю/0,006; и/0,062; м/0,026; ь, ъ/0,014; ц/0,004; н/0,053; д/0,025; г/0,013; щ/0,003; т/0,053; п/0,023; ч/0,012; э/0,003; с/0,045; у/0,021; й/0,01; ф/0,002; р/0,04; я/0,018; х/0,009.
С помощью разработанной программы были выбраны только буквы исходного текста и заменены на их относительные частоты.
Буквы: айоийъйчркшчьбдбпиббоъйхшёюъпябпёшпёбънчфшбабпзйоббъибпьбхопипдбёяшийябшёпчрфыъйчркшчбёёшчибщпёппбишкибпъчйёяшябъбёришбчошъшёшчрчёычоьжьбобйжпёъбъчйишгпчйкрёйоъчйёбобёрдбяъшбшвшйчёпийчхпошорйэйбяибёбобйорйёбчёжхшьъйчркшъьббхйкяъжчкычёйиибёбъьйбъыпбшвяъшкйчьэшчьжчоььбчёйишгйёбжбшдшобохшчщйьбьбпйвяйъяйбйъилпъбоойьйбйгиппьбчёйяиппчёжхшпнъыжщяжкшёпьошдбппвъйбёбйоббёбшядбйьбчоипдъйъйндчошопийьбпьбкипойёпъыхбяпбихбкшибъпхдшдийчдбёрдбёйообкжишвшяй…
Частоты: 0.004 0.069 0.057 0.047 0.069 0.047 0.069 0.044 0.016 0.024 0.066 0.044 0.033 0.111 0.023 0.111 0.054 0.047 0.111 0.111 0.057 0.047 0.069 0.014 0.066 0.044 0.001 0.047 0.054 0.026 0.111 0.054 0.044 0.066 0.054 0.044 0.111 0.047 0.004 0.044 0.002 0.066 0.111 0.004 0.111 0.054 0.003 0.069 0.057 0.111 0.111 0.047 0.047 0.111 0.054 0.033 0.111 0.014 0.057 0.054 0.047 0.054 0.023 0.111 0.044 0.026 0.066 0.047 0.069…
Далее с помощью разработанной программы частоты букв исходного текста были сопоставлены с наиболее вероятными данными частотами и заменены на соответствующие буквы:
Цетсесесыдаслопотсоотсеьасфстмотсатсосцсфаоцотщетооссотлоьттстпосмасемоастсыфйсесыдасоссассохтсттосадсотссесмамососысаостасасасыссйстлклотоектссоссесахтседысетссесотосыпомсаоагаесстсесьттатыецеомсосотоетыесосскьалсесыдаслооьедмсксдйссессосослеосйтоагмсадеслцаслкстллоссесахесокоапатотьасхелолотегмесмеоессцтсоттелеоехсттлоссемсттсскьатцсйкхмкдастлтапоттгсеосоетоосоампоелостстпсесецпстаттселотлодсттестсйьомтосьодасостьпапсеспосыпосеттодксагамец…
Проанализировав текст, можно сделать вывод, что программа не смогла преобразовать текст к его незашифрованному варианту. Предполагаемыми основными причинами неуспешного результата можно назвать:
- повторения в таблице частот, из-за чего букву нельзя однозначно расшифровать, а также неразделение в таблице частот букв ъ/ь и е/ё;
- малый размер исходного текста, из-за чего было собрано недостаточное количество данных для выявления более точных частот букв.
Получим незашифрованный исходный текст и только его буквы:
нет, не весьма, — спокойно отвечал свидригайлов. — а с марфой петровной почти никогда не дрались. мы весьма согласно жили, и она мной всегда довольна оставалась. хлыст я употребил, во все наши семь лет…
нетневесьмаспокойноотвечалсвидригайловасмарфойпетровнойпочтиникогданедралисьмывесьмасогласножилиионамнойвсегдадовольнаоставаласьхлыстяупотребилвовсенашисемьлет…
Для анализа сопоставим первые несколько букв текста, полученного в результате работы программы, и изначального:
нетневесьмаспокойно
цетсесесыдаслопотсо
Можно сделать вывод, что программа хоть не сделала текста читаемым, однако правильно сопоставила примерно половину букв, что можно назвать не безуспешным результатом.
Листинг программы:
package org.infoprotection; import java.io.*; import java.text.DecimalFormat; import java.util.*; public class FreqAlg { public static void main(String[] args) { Map<Character, Double> frequencyMap; Map<Character, Double> theoreticalFrequencyMap = getNativeFrequencyMap(); String fileContent = readFileContent("1.txt"); System.out.println("Изначальный текст: " + fileContent); frequencyMap = getFrequencyMap(fileContent); StringBuilder fileLetters = getFileLetters(fileContent); System.out.println("Буквы начального текста: " + fileLetters); StringBuilder printableFrequencies = getPrintableFrequencies(fileLetters, frequencyMap); String printableFrequenciesStr = printableFrequencies.toString().replaceAll(",", "."); System.out.println("Частоты букв начального текста: " + printableFrequenciesStr); List<Double> orderedPrintableFrequencies = new ArrayList<>(); for (String frequencyStr : printableFrequenciesStr.split(" ")) { orderedPrintableFrequencies.add(Double.parseDouble(frequencyStr)); } System.out.println("Предполагаемый текст при замене частот на буквы: "); for (Double frequency : orderedPrintableFrequencies) { Character closestChar = 'щ'; for (Character currentCharacter : theoreticalFrequencyMap.keySet()) { if (theoreticalFrequencyMap.get(closestChar) != null && Math.abs(frequency - theoreticalFrequencyMap.get(currentCharacter)) < Math.abs(frequency - theoreticalFrequencyMap.get(closestChar))) { closestChar = currentCharacter; } } System.out.print(closestChar); } } private static Map<Character, Double> getFrequencyMap(String str) { Map<Character, Integer> charCount = new HashMap<>(); for (Character character : str.toCharArray()) { charCount.merge(character, 1, Integer::sum); } Map<Character, Double> charFreq = new TreeMap<>(Comparator.comparing(charCount::get)); for (Character character : charCount.keySet()) if (isRusLetter(character)) { charFreq.put(character, (double) (charCount.get(character)) / str.length()); } return charFreq; } private static Map<Character, Double> getNativeFrequencyMap() { String input = "о/0,09;в/0,038;з/0,016;ж/0,007;е,ё/0,072;л/0,035;ы/0,016;ш/0,006;а/0,062;к/0,028;б/0,014;" + "ю/0,006;и/0,062;м/0,026;ь,ъ/0,014;ц/0,004;н/0,053;д/0,025;г/0,013;щ/0,003;т/0,053;п/0,023;ч/0,012" + ";э/0,003;с/0,045;у/0,021;й/0,01;ф/0,002;р/0,04;я/0,018;х/0,009"; input = input.replaceAll(",", "."); Map<Character, Double> map = new HashMap<>(); String[] kvPairs = input.split(";"); for (String pair : kvPairs) { String[] keyValue = pair.split("/"); Character character = keyValue[0].charAt(0); Double frequency = Double.parseDouble(keyValue[1]); map.put(character, frequency); } return map; } private static String readFileContent(String fileName) { String fileContent; try (BufferedReader bufferedReader = new BufferedReader(new FileReader(new File(fileName)));) { fileContent = bufferedReader.readLine(); fileContent = fileContent.toLowerCase(); } catch (IOException e) { throw new RuntimeException(e); } return fileContent; } private static StringBuilder getFileLetters(String fileContent) { StringBuilder fileLetters = new StringBuilder(); for (int i = 0; i < fileContent.length(); i++) { Character currentChar = fileContent.charAt(i); if (isRusLetter(currentChar)) { fileLetters.append(currentChar); } } return fileLetters; } private static StringBuilder getPrintableFrequencies(StringBuilder fileLetters, Map<Character, Double> frequencyMap) { DecimalFormat format = new DecimalFormat("0.000"); StringBuilder printableFrequencies = new StringBuilder(); for (int i = 0; i < fileLetters.length(); i++) { Character currentChar = fileLetters.charAt(i); if (!isRusLetter(currentChar)) { continue; } printableFrequencies.append(format.format(frequencyMap.get(currentChar))) .append(" "); } return printableFrequencies; } private static boolean isRusLetter(Character character) { return character.toString().matches("[а-яА-ЯёЁ]+"); } }
Вывод: были получены навыки выявления закономерностей в шифрованном тексе и статистические данные включений определённых символов.