From 4871de241319439cff69b3ebc1ee4362322ae09d Mon Sep 17 00:00:00 2001 From: Daniel <59575049+lumijiez@users.noreply.github.com> Date: Thu, 14 Nov 2024 22:41:05 +0200 Subject: [PATCH] fix --- .idea/misc.xml | 7 + pom.xml | 9 +- src/main/java/org/lumijiez/DoubleCaesar.java | 15 ++ src/main/java/org/lumijiez/Main.java | 89 +++++++- src/main/java/org/lumijiez/SimpleCaesar.java | 29 +++ src/main/java/org/lumijiez/Utils.java | 64 ++++++ src/main/java/org/lumijiez/Vigenere.java | 224 +++++++++++++++++++ 7 files changed, 426 insertions(+), 11 deletions(-) create mode 100644 src/main/java/org/lumijiez/Vigenere.java diff --git a/.idea/misc.xml b/.idea/misc.xml index 68fc085..1c85357 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,13 @@ + + + diff --git a/pom.xml b/pom.xml index 4002483..53d8769 100644 --- a/pom.xml +++ b/pom.xml @@ -8,10 +8,17 @@ Cypher 1.0-SNAPSHOT + + + com.github.freva + ascii-table + 1.2.0 + + 23 23 UTF-8 - + \ No newline at end of file diff --git a/src/main/java/org/lumijiez/DoubleCaesar.java b/src/main/java/org/lumijiez/DoubleCaesar.java index 2401dbf..8502243 100644 --- a/src/main/java/org/lumijiez/DoubleCaesar.java +++ b/src/main/java/org/lumijiez/DoubleCaesar.java @@ -1,4 +1,19 @@ package org.lumijiez; public class DoubleCaesar { + public static String encode(int key, String keyWord, String content) { + StringBuilder encoded = new StringBuilder(); + + String fixedContent = content.replaceAll("\\s",""); + + Utils.ALPHABET = Utils.getDoubleCaesarAlphabet(Utils.toCaesarKey(keyWord)); + + for (char ch : fixedContent.toCharArray()) { + encoded.append(Utils.toNthLetter((Utils.getPos(ch) + key) % Utils.ALPHABET.length())); + } + + Utils.returnAlphabet(); + + return encoded.toString(); + } } diff --git a/src/main/java/org/lumijiez/Main.java b/src/main/java/org/lumijiez/Main.java index c07936b..0c1376c 100644 --- a/src/main/java/org/lumijiez/Main.java +++ b/src/main/java/org/lumijiez/Main.java @@ -1,17 +1,86 @@ package org.lumijiez; -//TIP To Run code, press or -// click the icon in the gutter. +import java.util.Scanner; + public class Main { public static void main(String[] args) { - //TIP Press with your caret at the highlighted text - // to see how IntelliJ IDEA suggests fixing it. - System.out.printf("Hello and welcome!"); + Scanner scanner = new Scanner(System.in); + boolean exit = false; - for (int i = 1; i <= 5; i++) { - //TIP Press to start debugging your code. We have set one breakpoint - // for you, but you can always add more by pressing . - System.out.println("i = " + i); + while (!exit) { + System.out.println("Choose an option:"); + System.out.println("1. Simple Caesar Cipher"); + System.out.println("2. Double Caesar Cipher"); + System.out.println("3. Exit"); + + int choice = scanner.nextInt(); + scanner.nextLine(); + switch (choice) { + case 1: + System.out.println("Simple Caesar Cipher"); + System.out.println("1. Encode"); + System.out.println("2. Decode"); + System.out.print("Select option: "); + int simpleChoice = scanner.nextInt(); + System.out.print("Enter the key (an integer): "); + int simpleKey = scanner.nextInt(); + scanner.nextLine(); + + System.out.print("Enter the content: "); + String simpleContent = scanner.nextLine(); + + if (simpleKey <= 0) { + System.out.println("Invalid key. Please enter a positive integer."); + break; + } + + if (simpleChoice == 1) { + String encodedSimple = SimpleCaesar.encode(simpleKey, simpleContent); + System.out.println("Encoded: " + encodedSimple); + } else if (simpleChoice == 2) { + String decodedSimple = SimpleCaesar.decode(simpleKey, simpleContent); + System.out.println("Decoded: " + decodedSimple); + } else { + System.out.println("Invalid option."); + } + break; + + case 2: + System.out.println("Double Caesar Cipher"); + System.out.print("Enter the key (an integer): "); + int doubleKey = scanner.nextInt(); + scanner.nextLine(); + + System.out.print("Enter the keyword (more than 7 letters A-Z): "); + String doubleKeyWord = scanner.nextLine(); + + if (!isValidKeyword(doubleKeyWord)) { + System.out.println("Invalid keyword. Please ensure it is longer than 7 characters and contains only letters A-Z."); + break; + } + + System.out.print("Enter the content: "); + String doubleContent = scanner.nextLine(); + + String encodedDouble = DoubleCaesar.encode(doubleKey, doubleKeyWord, doubleContent); + System.out.println("Encoded: " + encodedDouble); + break; + + case 3: + exit = true; + System.out.println("Exiting..."); + break; + + default: + System.out.println("Invalid option. Please choose again."); + } + System.out.println("================"); } + + scanner.close(); } -} \ No newline at end of file + + private static boolean isValidKeyword(String keyword) { + return keyword.length() > 7 && keyword.matches("[A-Z]+"); + } +} diff --git a/src/main/java/org/lumijiez/SimpleCaesar.java b/src/main/java/org/lumijiez/SimpleCaesar.java index 1dae926..09e1d61 100644 --- a/src/main/java/org/lumijiez/SimpleCaesar.java +++ b/src/main/java/org/lumijiez/SimpleCaesar.java @@ -1,4 +1,33 @@ package org.lumijiez; public class SimpleCaesar { + public static String encode(int key, String content) { + StringBuilder encoded = new StringBuilder(); + + String fixedContent = content.replaceAll("\\s",""); + + for (char ch : fixedContent.toCharArray()) { + encoded.append(Utils.toNthLetter((Utils.getPos(ch) + key) % Utils.ALPHABET.length())); + } + return encoded.toString(); + } + + public static String decode(int key, String content) { + StringBuilder decoded = new StringBuilder(); + + for (char ch : content.toCharArray()) { + int currentPosition = Utils.getPos(ch); + + int newPosition = (currentPosition - key) % Utils.ALPHABET.length(); + + if (newPosition < 0) { + newPosition += Utils.ALPHABET.length(); + } + + decoded.append(Utils.toNthLetter(newPosition)); + } + + return decoded.toString(); + } + } diff --git a/src/main/java/org/lumijiez/Utils.java b/src/main/java/org/lumijiez/Utils.java index e69de29..85715ce 100644 --- a/src/main/java/org/lumijiez/Utils.java +++ b/src/main/java/org/lumijiez/Utils.java @@ -0,0 +1,64 @@ +package org.lumijiez; + +import java.util.LinkedHashSet; + +public class Utils { + + //public static String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 "; + public static String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + public static void returnAlphabet() { + Utils.ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + //Utils.ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 "; + } + + public static String toCaesarKey(String key) { + LinkedHashSet linkedHashSet = new LinkedHashSet<>(); + key.chars().forEach(ch -> linkedHashSet.add((char) ch)); + + StringBuilder caesarKey = new StringBuilder(); + linkedHashSet.forEach(caesarKey::append); + + return caesarKey.toString().toUpperCase(); + } + + public static char toNthLetter(int n) { + if (n >= ALPHABET.length()) { + throw new IllegalArgumentException("n must be between 1 and " + (ALPHABET.length() - 1)); + } + + if (!ALPHABET.contains(String.valueOf(ALPHABET.charAt(n)))) { + throw new IllegalArgumentException("Please only use letter from this alphabet " + Utils.ALPHABET); + } + return ALPHABET.charAt(n); + } + + public static int getPos(char letter) { + int index = ALPHABET.indexOf(letter); + if (index == -1) { + throw new IllegalArgumentException("Input must be a character in the alphabet: " + ALPHABET); + } + return index; + } + + public static String getDoubleCaesarAlphabet(String key) { + LinkedHashSet linkedHashSet = new LinkedHashSet<>(); + + for (char c : key.toCharArray()) { + linkedHashSet.add(c); + } + + for (char ch : ALPHABET.toCharArray()) { + linkedHashSet.add(ch); + } + + StringBuilder newAlphabet = new StringBuilder(); + + for (char ch : linkedHashSet) { + newAlphabet.append(ch); + } + + return newAlphabet.toString(); + } + +} \ No newline at end of file diff --git a/src/main/java/org/lumijiez/Vigenere.java b/src/main/java/org/lumijiez/Vigenere.java new file mode 100644 index 0000000..c6373f5 --- /dev/null +++ b/src/main/java/org/lumijiez/Vigenere.java @@ -0,0 +1,224 @@ +package org.lumijiez; + +import com.github.freva.asciitable.AsciiTable; +import com.github.freva.asciitable.Column; + +import java.util.Scanner; + +public class Vigenere { + private static final int ALPHABET_SIZE = 31; + private static final String ROMANIAN_ALPHABET = "AĂÂBCDEFGHIÎJKLMNOPQRSȘTȚUVWXYZ"; + + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + boolean continueProgram = true; + + while (continueProgram) { + printMenu(); + int choice = getValidChoice(scanner); + + switch (choice) { + case 1: + performEncryption(scanner); + break; + case 2: + performDecryption(scanner); + break; + case 3: + printTabulaRecta(); + break; + case 4: + continueProgram = false; + System.out.println("Program încheiat. La revedere!"); + break; + default: + System.out.println("Opțiune invalidă!"); + } + } + scanner.close(); + } + + private static void printMenu() { + System.out.println("\n=== Cifrul Vigenère pentru Limba Română ==="); + System.out.println("1. Criptare"); + System.out.println("2. Decriptare"); + System.out.println("3. Afișare Tabula Recta"); + System.out.println("4. Ieșire"); + System.out.print("Alegeți opțiunea (1-4): "); + } + + private static void printTabulaRecta() { + System.out.println("\n=== Tabula Recta pentru Alfabetul Românesc ===\n"); + + String[] headers = new String[ALPHABET_SIZE + 1]; + headers[0] = "K\\M"; + for (int i = 0; i < ALPHABET_SIZE; i++) { + headers[i + 1] = String.valueOf(ROMANIAN_ALPHABET.charAt(i)); + } + + String[][] data = new String[ALPHABET_SIZE][ALPHABET_SIZE + 1]; + for (int i = 0; i < ALPHABET_SIZE; i++) { + data[i][0] = String.valueOf(ROMANIAN_ALPHABET.charAt(i)); + for (int j = 0; j < ALPHABET_SIZE; j++) { + int encryptedIndex = (i + j) % ALPHABET_SIZE; + data[i][j + 1] = String.valueOf(ROMANIAN_ALPHABET.charAt(encryptedIndex)); + } + } + + Column[] columns = new Column[ALPHABET_SIZE + 1]; + columns[0] = new Column() + .header(headers[0]) + .with(row -> ((String[])row)[0]); + + for (int i = 1; i <= ALPHABET_SIZE; i++) { + final int colIndex = i; + columns[i] = new Column() + .header(headers[i]) + .with(row -> ((String[])row)[colIndex]); + } + + System.out.println(AsciiTable.getTable(AsciiTable.FANCY_ASCII, columns, data)); + + System.out.println("\nInstrucțiuni de utilizare:"); + System.out.println("1. K\\M: K = litera din cheie, M = litera din mesaj"); + System.out.println("2. Pentru a cripta, găsiți litera din mesaj (M) în prima linie"); + System.out.println("3. Găsiți litera din cheie (K) în prima coloană"); + System.out.println("4. Intersecția liniei K cu coloana M este litera criptată"); + } + + + private static int getValidChoice(Scanner scanner) { + while (!scanner.hasNextInt()) { + System.out.println("Vă rugăm introduceți un număr!"); + scanner.next(); + } + return scanner.nextInt(); + } + + private static void performEncryption(Scanner scanner) { + scanner.nextLine(); + + String key = getValidKey(scanner); + + System.out.print("Introduceți mesajul de criptat: "); + String message = getValidMessage(scanner); + + String encryptedText = encrypt(message, key); + System.out.println("\nTextul criptat: " + encryptedText); + + System.out.println("\nInformații despre procesul de criptare:"); + System.out.println("Lungimea cheii: " + key.length()); + System.out.println("Lungimea mesajului original: " + message.length()); + System.out.println("Lungimea mesajului criptat: " + encryptedText.length()); + } + + private static void performDecryption(Scanner scanner) { + scanner.nextLine(); + + String key = getValidKey(scanner); + System.out.print("Introduceți textul criptat: "); + String encryptedMessage = getValidMessage(scanner); + + String decryptedText = decrypt(encryptedMessage, key); + System.out.println("\nTextul decriptat: " + decryptedText); + + System.out.println("\nInformații despre procesul de decriptare:"); + System.out.println("Lungimea cheii: " + key.length()); + System.out.println("Lungimea textului criptat: " + encryptedMessage.length()); + System.out.println("Lungimea textului decriptat: " + decryptedText.length()); + } + + private static String getValidKey(Scanner scanner) { + String key; + do { + System.out.print("Introduceți cheia (minim 7 caractere): "); + key = preprocessText(scanner.nextLine()); + + if (key.length() < 7) { + System.out.println("Eroare: Cheia trebuie să aibă cel puțin 7 caractere!"); + continue; + } + + if (isValidRomanianText(key)) { + System.out.println("Eroare: Cheia poate conține doar litere românești!"); + continue; + } + + break; + } while (true); + + return key; + } + + private static String getValidMessage(Scanner scanner) { + String message; + do { + message = preprocessText(scanner.nextLine()); + + if (message.isEmpty()) { + System.out.println("Eroare: Mesajul nu poate fi gol!"); + System.out.print("Introduceți din nou: "); + continue; + } + + if (isValidRomanianText(message)) { + System.out.println("Eroare: Mesajul poate conține doar litere românești!"); + System.out.print("Introduceți din nou: "); + continue; + } + + break; + } while (true); + + return message; + } + + private static String preprocessText(String text) { + return text.replaceAll("\\s+", "").toUpperCase(); + } + + private static boolean isValidRomanianText(String text) { + for (char c : text.toCharArray()) { + if (ROMANIAN_ALPHABET.indexOf(c) == -1) { + return true; + } + } + return false; + } + + private static String encrypt(String message, String key) { + StringBuilder encryptedText = new StringBuilder(); + int keyLength = key.length(); + + for (int i = 0; i < message.length(); i++) { + char messageChar = message.charAt(i); + char keyChar = key.charAt(i % keyLength); + + int messageIndex = ROMANIAN_ALPHABET.indexOf(messageChar); + int keyIndex = ROMANIAN_ALPHABET.indexOf(keyChar); + + int encryptedIndex = (messageIndex + keyIndex) % ALPHABET_SIZE; + encryptedText.append(ROMANIAN_ALPHABET.charAt(encryptedIndex)); + } + + return encryptedText.toString(); + } + + private static String decrypt(String encryptedText, String key) { + StringBuilder decryptedText = new StringBuilder(); + int keyLength = key.length(); + + for (int i = 0; i < encryptedText.length(); i++) { + char encryptedChar = encryptedText.charAt(i); + char keyChar = key.charAt(i % keyLength); + + int encryptedIndex = ROMANIAN_ALPHABET.indexOf(encryptedChar); + int keyIndex = ROMANIAN_ALPHABET.indexOf(keyChar); + + int decryptedIndex = (encryptedIndex - keyIndex + ALPHABET_SIZE) % ALPHABET_SIZE; + decryptedText.append(ROMANIAN_ALPHABET.charAt(decryptedIndex)); + } + + return decryptedText.toString(); + } +} \ No newline at end of file