diff --git a/src/main/java/com/mattrixwv/CipherStreamJava/monoSubstitution/Porta.java b/src/main/java/com/mattrixwv/CipherStreamJava/monoSubstitution/Porta.java new file mode 100644 index 0000000..958ce0c --- /dev/null +++ b/src/main/java/com/mattrixwv/CipherStreamJava/monoSubstitution/Porta.java @@ -0,0 +1,207 @@ +//CipherStreamJava/src/main/java/com/mattrixwv/CipherStreamJava/monoSubstitution/Porta.java +//Mattrixwv +// Created: 02-28-22 +//Modified: 02-28-22 +package com.mattrixwv.CipherStreamJava.monoSubstitution; + + +import com.mattrixwv.CipherStreamJava.exceptions.InvalidInputException; +import com.mattrixwv.CipherStreamJava.exceptions.InvalidKeywordException; + + +public class Porta{ + private static final String[] tableau = { + "NOPQRSTUVWXYZABCDEFGHIJKLM", //A-B + "OPQRSTUVWXYZNMABCDEFGHIJKL", //C-D + "PQRSTUVWXYZNOLMABCDEFGHIJK", //E-F + "QRSTUVWXYZNOPKLMABCDEFGHIJ", //G-H + "RSTUVWXYZNOPQJKLMABCDEFGHI", //I-J + "STUVWXYZNOPQRIJKLMABCDEFGH", //K-L + "TUVWXYZNOPQRSHIJKLMABCDEFG", //M-N + "UVWXYZNOPQRSTGHIJKLMABCDEF", //O-P + "VWXYZNOPQRSTUFGHIJKLMABCDE", //Q-R + "WXYZNOPQRSTUVEFGHIJKLMABCD", //S-T + "XYZNOPQRSTUVWDEFGHIJKLMABC", //U-V + "YZNOPQRSTUVWXCDEFGHIJKLMAB", //W-X + "ZNOPQRSTUVWXYBCDEFGHIJKLMA" //Y-Z + }; + + private String inputString; + private String outputString; + private String keyword; + private boolean preserveCapitals; + private boolean preserveWhitespace; + private boolean preserveSymbols; + + private void setKeyword(String keyword) throws InvalidKeywordException{ + //Make sure the keyword isn't null + if(keyword == null){ + throw new InvalidKeywordException("Keyword cannot be null"); + } + + //Convert all letters to uppercase + keyword = keyword.toUpperCase(); + //Remove all characters except capital letters and save the string + keyword = keyword.replaceAll("[^A-Z]", ""); + this.keyword = keyword; + + //If after eliminating all ususable characters the keyword is empty throw an exception + if(this.keyword.isBlank() || (this.keyword.length() < 2)){ + throw new InvalidKeywordException("Keyword must contain at least 2 letters"); + } + } + private void setInputString(String inputString) throws InvalidInputException{ + //Ensure the input isn't null + if(inputString == null){ + throw new InvalidInputException("Input cannot be null"); + } + + //Apply removal options + if(!preserveCapitals){ + inputString = inputString.toUpperCase(); + } + if(!preserveWhitespace){ + inputString = inputString.replaceAll("\\s", ""); + } + if(!preserveSymbols){ + inputString = inputString.replaceAll("[^a-zA-Z\\s]", ""); + } + + //Save the string + this.inputString = inputString; + + //Ensure the string isn't blank + if(this.inputString.isBlank()){ + throw new InvalidInputException("Input must contain at least 1 letter"); + } + } + private char getReplacer(int keywordCnt, char letter){ + char keyLetter = keyword.charAt(keywordCnt % keyword.length()); + int tableauColumn = (Character.toUpperCase(letter) - 'A'); + char replacer = '\0'; + + switch(keyLetter){ + case 'A': + case 'B': + replacer = tableau[0].charAt(tableauColumn); break; + case 'C': + case 'D': + replacer = tableau[1].charAt(tableauColumn); break; + case 'E': + case 'F': + replacer = tableau[2].charAt(tableauColumn); break; + case 'G': + case 'H': + replacer = tableau[3].charAt(tableauColumn); break; + case 'I': + case 'J': + replacer = tableau[4].charAt(tableauColumn); break; + case 'K': + case 'L': + replacer = tableau[5].charAt(tableauColumn); break; + case 'M': + case 'N': + replacer = tableau[6].charAt(tableauColumn); break; + case 'O': + case 'P': + replacer = tableau[7].charAt(tableauColumn); break; + case 'Q': + case 'R': + replacer = tableau[8].charAt(tableauColumn); break; + case 'S': + case 'T': + replacer = tableau[9].charAt(tableauColumn); break; + case 'U': + case 'V': + replacer = tableau[10].charAt(tableauColumn); break; + case 'W': + case 'X': + replacer = tableau[11].charAt(tableauColumn); break; + case 'Y': + case 'Z': + replacer = tableau[12].charAt(tableauColumn); break; + default: + replacer = letter; + } + + return replacer; + } + private void encode(){ + StringBuilder output = new StringBuilder(); + + //Step through every character in the inputString and advance it the correct amount according to the keyword and tableau + int keywordCnt = 0; + for(char letter : inputString.toCharArray()){ + //If the character is a letter replace with the corresponding character from the tableau + if(Character.isUpperCase(letter)){ + letter = Character.toUpperCase(getReplacer(keywordCnt, letter)); + ++keywordCnt; + } + else if(Character.isLowerCase(letter)){ + letter = Character.toLowerCase(getReplacer(keywordCnt, letter)); + ++keywordCnt; + } + + //Add the current character to the output + output.append(letter); + } + + //Save the output + outputString = output.toString(); + } + private void decode(){ + //Decoding is the same as encoding + encode(); + } + + + //Constructor + public Porta(){ + preserveCapitals = false; + preserveWhitespace = false; + preserveSymbols = false; + reset(); + } + public Porta(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols){ + this.preserveCapitals = preserveCapitals; + this.preserveWhitespace = preserveWhitespace; + this.preserveSymbols = preserveSymbols; + reset(); + } + + public String encode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{ + //Set the parameters + reset(); + setKeyword(keyword); + setInputString(inputString); + + //Encode and return the message + encode(); + return outputString; + } + public String decode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{ + //Set the parameters + reset(); + setKeyword(keyword); + setInputString(inputString); + + //Decode and return the message + decode(); + return outputString; + } + + public String getInputString(){ + return inputString; + } + public String getOutputString(){ + return outputString; + } + public String getKeyword(){ + return keyword; + } + public void reset(){ + inputString = ""; + outputString = ""; + keyword = ""; + } +}