-
Notifications
You must be signed in to change notification settings - Fork 47
goncharov - 3 tasks (encrypt, decrypt, brute) #20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| package com.javarush.goncharov; | ||
|
|
||
| import static com.javarush.goncharov.view.Menu.run; | ||
|
|
||
| public class EntryPoint { | ||
| public static void main(String[] args) { | ||
| run(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| package com.javarush.goncharov.constants; | ||
|
|
||
| public class ApplicationCompletionConstants { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Слишком неудобное название. Проще было бы назвать Messages
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. А ещё если бы это сделать в виде интерфейса то не пришлось бы писать public static final |
||
|
|
||
| public static final String SUCCESS = "Выполнение приложения завершилось успешно"; | ||
| public static final String MESSAGE_IN = | ||
| "Введите путь к исходному файлу или нажмите Enter, чтобы воспользоваться демонстрационным файлом :\n" + | ||
| "(text/input.txt - используется для последующего шифрования)"; | ||
| public static final String MESSAGE_OUT = "Введите путь к конечному файлу или нажмите Enter, чтобы воспользоваться демонстрационным файлом :\n" + | ||
| "(text/output.txt - сохраниться расшифрованный текст)"; | ||
| public static final String MESSAGE_IN_ENCODED = "Введите путь к исходному файлу или нажмите Enter, чтобы воспользоваться демонстрационным файлом :\n" + | ||
| "(text/encoded.txt - используется для последующей расшифровки)"; | ||
| public static final String MESSAGE_KEY_GENERATED = "Сгенерирован ключ под номером: "; | ||
| public static final String MESSAGE_KEY = "Введите ключ в целочисленном диапазоне : "; | ||
| public static final String INPUT_MODE = """ | ||
| Выберете режим работы:\s | ||
| Чтобы зашифровать текстовый файл, введите - 1 | ||
| Чтобы расшифровать текстовый файл, введите - 2 | ||
| Чтобы расшифровать текстовый файл (подбор ключа методом перебора всех возможных вариантов), введите - 3: """; | ||
| public static final String DESCRIPTION_SERVICE = """ | ||
| Добро пожаловать в сервис шифр Цезаря! | ||
| """; | ||
| public static final String MESSAGE_ERROR_ENCODE = "Операция кодирования завершилась ошибкой - "; | ||
| public static final String MESSAGE_ERROR_DECODE = "Операция декодирования завершилась ошибкой - "; | ||
| public static final String MESSAGE_REPEAT = "Некорректный режим работы. Допустимые значения : \"1\" - для шифрования, " + | ||
| "\"2\" - для расшифровки, \"3\" - bruteforce (подбор ключа методом перебора всех возможных вариантов) \"end\" - для завершения работы!"; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| package com.javarush.goncharov.constants; | ||
|
|
||
| public class CryptoAlphabet { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. И тут тоже |
||
| public static final String lettersUpperCase = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"; | ||
| public static final String lettersLowerCase = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя"; | ||
| public static final String numbers = "0123456789"; | ||
| public static final String symbols = ".,\"^-!& "; | ||
| public static final String ALPHABET = lettersUpperCase + lettersLowerCase + numbers + symbols; | ||
| public static final int ALPHABET_LENGTH = ALPHABET.length(); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| package com.javarush.goncharov.constants; | ||
|
|
||
| public class FunctionCodeConstants { | ||
|
|
||
| public static final String INPUT = "text/input.txt"; | ||
| public static final String OUTPUT = "text/output.txt"; | ||
| public static final String ENCODED = "text/encoded.txt"; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| package com.javarush.goncharov.exception; | ||
|
|
||
| public class ApplicationException extends RuntimeException{ | ||
| public ApplicationException() { | ||
| } | ||
|
|
||
| public ApplicationException(String message) { | ||
| super(message); | ||
| } | ||
|
|
||
| public ApplicationException(String message, Throwable cause) { | ||
| super(message, cause); | ||
| } | ||
|
|
||
| public ApplicationException(Throwable cause) { | ||
| super(cause); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| package com.javarush.goncharov.services; | ||
|
|
||
| import static com.javarush.goncharov.constants.FunctionCodeConstants.*; | ||
| import static com.javarush.goncharov.services.UtilsFunc.*; | ||
|
|
||
| public class PathUtilsFunc { | ||
|
|
||
| public static String getInputFileEncode(String message){ | ||
| System.out.println(message); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. в методах которые начинаются на Prefix get меньше всего ожидаешь увидеть вывод на консоль |
||
| String inputFileEncode = in.nextLine(); | ||
| if (inputFileEncode.isEmpty()){ | ||
| inputFileEncode = INPUT; | ||
| } | ||
| return inputFileEncode; | ||
| } | ||
|
|
||
| public static String getOutputFileEncode(String message){ | ||
| System.out.println(message); | ||
| String outputFileEncode = in.nextLine(); | ||
| if (outputFileEncode.isEmpty()){ | ||
| outputFileEncode = OUTPUT; | ||
| } | ||
| return outputFileEncode; | ||
| } | ||
|
|
||
| public static String getInputFileDecode(String message){ | ||
| System.out.println(message); | ||
| String inputFileDecode = in.nextLine(); | ||
| if (inputFileDecode.isEmpty()){ | ||
| inputFileDecode = OUTPUT; | ||
| } | ||
| return inputFileDecode; | ||
| } | ||
|
|
||
| public static String getOutputFileDecode(String message){ | ||
| System.out.println(message); | ||
| String outputFileDecode = in.nextLine(); | ||
| if (outputFileDecode.isEmpty()){ | ||
| outputFileDecode = ENCODED; | ||
| } | ||
| return outputFileDecode; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| package com.javarush.goncharov.services; | ||
|
|
||
| import java.util.Scanner; | ||
| import java.util.concurrent.ThreadLocalRandom; | ||
|
|
||
| import static com.javarush.goncharov.constants.ApplicationCompletionConstants.*; | ||
| import static com.javarush.goncharov.constants.CryptoAlphabet.*; | ||
|
|
||
| public class UtilsFunc { | ||
|
|
||
| static Scanner in = new Scanner(System.in); | ||
|
|
||
| public static int getInputMode(String message){ | ||
| String input; | ||
| while (true){ | ||
| System.out.println(message); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. и тут тоже самое |
||
| input = in.nextLine(); | ||
| if (input.equals("1") || input.equals("2") || input.equals("3")){ | ||
| return Integer.parseInt(input); | ||
| } else if (input.equals("End".toLowerCase())) { | ||
| close(); | ||
| } else { | ||
| System.out.println(MESSAGE_REPEAT); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| public static void close(){ | ||
| System.exit(0); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Такие способы завершения приложений настоящие ночной кошмар для тестировщика, поэтому так лучше программу никогда не останавливать. Это самое настоящий аварийный вариант и то место где стоит ноль обычно предназначено для указания аварийного кода выхода |
||
| } | ||
|
|
||
| public static int getRandomKey(){ | ||
| int key = ThreadLocalRandom.current().nextInt(1, (ALPHABET_LENGTH + 1) / 2); | ||
| System.out.println(MESSAGE_KEY_GENERATED + key); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. да что-то с дизайном вывода совсем всё печально, в каждом методе выводить что-то на консоль точно не стоит |
||
| return key; | ||
| } | ||
|
|
||
| public static int getShiftKey(String message){ | ||
| String input; | ||
| while (true){ | ||
| System.out.println(message); | ||
| input = in.nextLine(); | ||
| if (input.isEmpty()){ | ||
| return getRandomKey(); | ||
| } else if (Integer.parseInt(input) >= 1 && Integer.parseInt(input) <= ALPHABET_LENGTH) { | ||
| return Integer.parseInt(input); | ||
| } else { | ||
| System.out.printf("Вы можете использовать числа от 1 до %d. \n", ALPHABET_LENGTH); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| package com.javarush.goncharov.view; | ||
|
|
||
| import com.javarush.goncharov.exception.ApplicationException; | ||
|
|
||
| import java.io.*; | ||
| import java.util.regex.Matcher; | ||
| import java.util.regex.Pattern; | ||
|
|
||
| import static com.javarush.goncharov.constants.ApplicationCompletionConstants.*; | ||
| import static com.javarush.goncharov.constants.ApplicationCompletionConstants.SUCCESS; | ||
| import static com.javarush.goncharov.constants.CryptoAlphabet.ALPHABET_LENGTH; | ||
| import static com.javarush.goncharov.services.PathUtilsFunc.getInputFileDecode; | ||
| import static com.javarush.goncharov.services.PathUtilsFunc.getOutputFileDecode; | ||
|
|
||
| public class BruteForce{ | ||
|
|
||
| private static final String REGEX = "^([а-яА-Я]+(\\s|,\\s|:\\s|;\\s|-\\s)){2,}"; | ||
| private static final Pattern PATTERN = Pattern.compile(REGEX); | ||
| private static int key; | ||
| private static boolean find; | ||
|
|
||
| public static void brute(){ | ||
| String inputFile = getInputFileDecode(MESSAGE_OUT); | ||
| String outputFileFile = getOutputFileDecode(MESSAGE_IN_ENCODED); | ||
|
|
||
| for (int i = 0; i < ALPHABET_LENGTH; i++) { | ||
| if (find){ | ||
| break; | ||
| } | ||
| try (BufferedReader reader = new BufferedReader(new FileReader(inputFile)); | ||
| BufferedWriter writer = new BufferedWriter(new FileWriter(outputFileFile))) { | ||
| while (reader.ready()) { | ||
| String result = bruteForce(reader.readLine(), i); | ||
| if (find) { | ||
| writer.write(result); | ||
| writer.newLine(); | ||
| writer.flush(); | ||
| } | ||
| } | ||
| } catch (IOException e) { | ||
| throw new ApplicationException(MESSAGE_ERROR_DECODE, e); | ||
| } | ||
| } | ||
| System.out.println(SUCCESS); | ||
| System.out.printf("Key used for decryption: %d%n", getKey()); | ||
| } | ||
|
|
||
| private static String bruteForce(String textInput, int key) { | ||
| StringBuilder textOutput = new StringBuilder(); | ||
| textOutput.delete(0, textOutput.length()); | ||
| textOutput.append(Decode.encodeText(textInput, key)); | ||
| Matcher matcher = PATTERN.matcher(textOutput); | ||
| if (matcher.find()) { | ||
| BruteForce.key = key; | ||
| BruteForce.find = true; | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Тут как-то очень ненадёжно сделано, этот метод вызывается отдельно для каждой строки, и получается что в некоторых строках он может установить флаг что решение найдены а в некоторых нет. Лучше было бы анализировать весь текст целиком |
||
| } | ||
| return textOutput.toString(); | ||
| } | ||
|
|
||
| private static int getKey() { | ||
| return key; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| package com.javarush.goncharov.view; | ||
|
|
||
| import com.javarush.goncharov.exception.ApplicationException; | ||
|
|
||
| import java.io.*; | ||
|
|
||
| import static com.javarush.goncharov.constants.ApplicationCompletionConstants.*; | ||
| import static com.javarush.goncharov.constants.CryptoAlphabet.ALPHABET; | ||
| import static com.javarush.goncharov.services.PathUtilsFunc.*; | ||
| import static com.javarush.goncharov.services.UtilsFunc.getShiftKey; | ||
|
|
||
| public class Decode { | ||
| public static void decode(){ | ||
| int key = getShiftKey(MESSAGE_KEY); | ||
| String inputFile = getInputFileDecode(MESSAGE_OUT); | ||
| String outputFileFile = getOutputFileDecode(MESSAGE_IN_ENCODED); | ||
|
|
||
| try (BufferedReader reader = new BufferedReader(new FileReader(inputFile)); | ||
| BufferedWriter writer = new BufferedWriter(new FileWriter(outputFileFile))){ | ||
|
|
||
| while (reader.ready()){ | ||
| writer.write(encodeText(reader.readLine(), key)); | ||
| writer.newLine(); | ||
| writer.flush(); | ||
| } | ||
| } catch (IOException e) { | ||
| throw new ApplicationException(MESSAGE_ERROR_DECODE, e); | ||
| } | ||
| System.out.println(SUCCESS); | ||
| } | ||
|
|
||
| public static String encodeText(String string, int shift){ | ||
| StringBuilder builder = new StringBuilder(); | ||
| for (int i = 0; i < string.length(); i++) { | ||
| builder.append(symbolDecode(string.charAt(i), shift)); | ||
| } | ||
| return builder.toString(); | ||
| } | ||
|
|
||
| private static char symbolDecode(char symbol, int shift) { | ||
| if (ALPHABET.indexOf(symbol) != -1) { | ||
| if (ALPHABET.indexOf(symbol) - shift >= 0) { | ||
| return ALPHABET.charAt((ALPHABET.indexOf(symbol) - shift) % ALPHABET.length()); | ||
| } else { | ||
| return ALPHABET.charAt(ALPHABET.length() + (ALPHABET.indexOf(symbol) - shift) % ALPHABET.length()); | ||
| } | ||
| } else { | ||
| return symbol; | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| package com.javarush.goncharov.view; | ||
|
|
||
| import com.javarush.goncharov.exception.ApplicationException; | ||
|
|
||
| import java.io.*; | ||
|
|
||
| import static com.javarush.goncharov.constants.ApplicationCompletionConstants.*; | ||
| import static com.javarush.goncharov.constants.CryptoAlphabet.ALPHABET; | ||
| import static com.javarush.goncharov.services.PathUtilsFunc.*; | ||
| import static com.javarush.goncharov.services.UtilsFunc.*; | ||
|
|
||
| public class Encode { | ||
| public static void encode(){ | ||
| int key = getShiftKey(MESSAGE_KEY); | ||
| String inputFile = getInputFileEncode(MESSAGE_IN); | ||
| String outputFileFile = getOutputFileEncode(MESSAGE_OUT); | ||
|
|
||
| try (BufferedReader reader = new BufferedReader(new FileReader(inputFile)); | ||
| BufferedWriter writer = new BufferedWriter(new FileWriter(outputFileFile))){ | ||
|
|
||
| while (reader.ready()){ | ||
| writer.write(encodeText(reader.readLine(), key)); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. кодирование и декодирования выполняется построчно а не посимвольно, это сильно поможет потенциальному взломщику определить границы строк |
||
| writer.newLine(); | ||
| writer.flush(); | ||
| } | ||
| } catch (IOException e) { | ||
| throw new ApplicationException(MESSAGE_ERROR_ENCODE, e); | ||
| } | ||
| System.out.println(SUCCESS); | ||
| } | ||
|
|
||
| private static String encodeText(String string, int shift){ | ||
| StringBuilder builder = new StringBuilder(); | ||
| for (int i = 0; i < string.length(); i++) { | ||
| builder.append(symbolRightShift(string.charAt(i), shift)); | ||
| } | ||
| return builder.toString(); | ||
| } | ||
|
|
||
| private static char symbolRightShift(char symbol, int shift){ | ||
| if (ALPHABET.indexOf(symbol) != -1){ | ||
| return ALPHABET.charAt((ALPHABET.indexOf(symbol) + shift) % ALPHABET.length()); | ||
| } else { | ||
| return symbol; | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| package com.javarush.goncharov.view; | ||
|
|
||
| import static com.javarush.goncharov.constants.ApplicationCompletionConstants.*; | ||
| import static com.javarush.goncharov.services.UtilsFunc.getInputMode; | ||
| import static com.javarush.goncharov.view.BruteForce.brute; | ||
| import static com.javarush.goncharov.view.Decode.decode; | ||
| import static com.javarush.goncharov.view.Encode.encode; | ||
|
|
||
| public class Menu { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. если в классе только статические методы то у него должен быть приватный конструктор пустой |
||
| public static void run(){ | ||
| printMainMenu(); | ||
| int startValue = getInputMode(INPUT_MODE); | ||
| switch (startValue){ | ||
| case 1 -> encode(); | ||
| case 2 -> decode(); | ||
| case 3 -> brute(); | ||
| } | ||
| } | ||
|
|
||
| private static void printMainMenu(){ | ||
| System.out.println(DESCRIPTION_SERVICE); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
в данном классе нет никакого смысла