diff --git a/README.md b/README.md index 27e37a6..4952e78 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,16 @@ Message to encode -> Wiqooxh fs wfcuhx ``` +### Columnar +TODO: + +Example: +``` +key = keyword +Message to encode -> +Edxeoxm te acxgoxsnxsex +``` + ## Poly-Substitution These ciphers are slightly more complex, encoding multiple letters at the same time making the cipher harder to crack. While many of these keep one letter from always being encoded as another single letter it often does so in such a way that if multiple letters are often seen together they will be encoded the same way. This is offset somewhat because they have to appear in the same location in the cipher text % the number of letters you are encoding by. i.e. If you are using a cipher that encodes with pairs the 'es' in 'mess' and 'these' would not encode to the same thing because 'me' and 'ss' are encoded in the first example while 'th', 'es', 'e_' are encoded in the second, unless there were an odd number of characters before one of these words, shifting one of the words by one place. diff --git a/src/main/java/com/mattrixwv/CipherStreamJava/polySubstitution/Columnar.java b/src/main/java/com/mattrixwv/CipherStreamJava/polySubstitution/Columnar.java index 8cf1934..fd88e77 100644 --- a/src/main/java/com/mattrixwv/CipherStreamJava/polySubstitution/Columnar.java +++ b/src/main/java/com/mattrixwv/CipherStreamJava/polySubstitution/Columnar.java @@ -4,82 +4,279 @@ //Modified: 01-16-22 package com.mattrixwv.CipherStreamJava.polySubstitution; + import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; + +import com.mattrixwv.CipherStreamJava.exceptions.InvalidCharacterException; +import com.mattrixwv.CipherStreamJava.exceptions.InvalidInputException; +import com.mattrixwv.CipherStreamJava.exceptions.InvalidKeywordException; + public class Columnar{ private boolean preserveCapitals; //Whether to respect capitals in the output string private boolean preserveWhitespace; //Whether to respect whitespace in the output string private boolean preserveSymbols; //Whether to respect symbols in the output string + private boolean removePadding; //Whether to respect the padding letters added to the cipher private String inputString; //The message that needs to be encoded/decoded private String outputString; //The encoded/decoded message private String keyword; //The keyword used to create the grid - //TODO: Make this more robust private char characterToAdd; //The character that is added to the end of a string to bring it to the correct length + private int charsAdded; //The number of characters that were added to the end of the message private ArrayList> grid; //The grid used to encode/decode the message + private String getCleanInputString(){ + return inputString.toUpperCase().replaceAll("[^A-Z]", ""); + } //Create the grid from the keyword - private void createGrid(){ + private void createGridEncode(){ //Add the keyword to the first row in the array + grid = new ArrayList>(); grid.add(new ArrayList(Arrays.asList(keyword.chars().mapToObj(c -> (char)c).toArray(Character[]::new)))); //Create the input that will be used for encoding - StringBuilder gridInputString = new StringBuilder(); - gridInputString.append(inputString.toUpperCase().replaceAll("[^A-Za-z]", "")); - - //Make sure the input is the correct length - while((gridInputString.length() % keyword.length()) != 0){ - gridInputString.append(characterToAdd); - } + String gridInputString = getCleanInputString(); //Create arrays from the inputString of keyword.size length and add them each as new rows to the grid //?gridRow could be changed to grid.size(), but would it be worth the extra confusion? Probably not unless I really want to min/max for(int gridRow = 1;(keyword.length() * gridRow) <= gridInputString.length();++gridRow){ grid.add(new ArrayList(Arrays.asList( - gridInputString.substring(keyword.length() * (gridRow - 1), (keyword.length() * gridRow) + 1) + gridInputString.substring(keyword.length() * (gridRow - 1), (keyword.length() * gridRow)) .chars().mapToObj(c->(char)c).toArray(Character[]::new) ))); } } + private void createGridDecode(){ + //Add the keyword to the first row in the array + grid = new ArrayList>(); + StringBuilder orderedKeyword = new StringBuilder(); + for(int cnt : getKeywordAlphaLocations()){ + orderedKeyword.append(keyword.charAt(cnt)); + } + grid.add(new ArrayList(Arrays.asList(orderedKeyword.chars().mapToObj(c -> (char)c).toArray(Character[]::new)))); + + //Create the input that will be used for encoding + String gridInputString = getCleanInputString(); + + //Make sure the grid has the appropritate number of rows + int numRows = inputString.length() / keyword.length(); + while(grid.size() <= numRows){ + grid.add(new ArrayList()); + } + //Add each character to the grid + int rowCnt = 1; + for(char ch : gridInputString.toCharArray()){ + grid.get(rowCnt++).add(ch); + if(rowCnt > numRows){ + rowCnt = 1; + } + } + } //Strips invalid characters from the string that needs encoded/decoded - private void setInputString(String inputString){ + private void setInputStringEncode(String inputString) throws InvalidInputException{ + if(inputString == null){ + throw new InvalidInputException("Input must not be null"); + } + if(!preserveCapitals){ - inputString = inputString.toLowerCase(); + inputString = inputString.toUpperCase(); } if(!preserveWhitespace){ inputString = inputString.replaceAll("[\\s+]", ""); } if(!preserveSymbols){ - //TODO: Should numbers be treated like symbols? Probably, so this might need modified as well as testing; For all ciphers - inputString = inputString.replaceAll("[^a-zA-Z0-9\\s]", ""); + inputString = inputString.replaceAll("[^a-zA-Z\\s]", ""); } - //TODO: Make sure that the input is not blank. This should be added to all ciphers + + //Make sure the input is the correct length + this.inputString = inputString; + StringBuilder inputStringBuilder = new StringBuilder(); + inputStringBuilder.append(inputString); + int cleanLength = getCleanInputString().length(); + int charsToAdd = (cleanLength % keyword.length()); + if(charsToAdd != 0){ + charsToAdd = keyword.length() - charsToAdd; + } + for(int cnt = 0;cnt < charsToAdd;++cnt){ + inputStringBuilder.append(characterToAdd); + } + charsAdded = charsToAdd; + inputString = inputStringBuilder.toString(); this.inputString = inputString; + + if(this.inputString.isBlank() || getCleanInputString().isBlank()){ + throw new InvalidInputException("Input cannot be blank"); + } } - //Creates the output string from the grid - private String createOutputString(){ - //Check every character of the inputString and add the appropriate character to the output - int row = 1; - int col = 0; - StringBuilder output = new StringBuilder(); - for(char ch : inputString.toCharArray()){ - //If the character is a letter get the next letter from the grid - if(Character.isUpperCase(ch)){ - output.append(grid.get(row++).get(col)); - } - else if(Character.isLowerCase(ch)){ - output.append(grid.get(row++).get(col)); - } - //If the character is a symbol or whitespace add it to the output - else{ - output.append(ch); + private void setInputStringDecode(String inputString) throws InvalidInputException{ + if(inputString == null){ + throw new InvalidInputException("Input must not be null"); + } + + if(!preserveCapitals){ + inputString = inputString.toUpperCase(); + } + if(!preserveWhitespace){ + inputString = inputString.replaceAll("[\\s+]", ""); + } + if(!preserveSymbols){ + inputString = inputString.replaceAll("[^a-zA-Z\\s]", ""); + } + + //Make sure the input is the correct length + charsAdded = 0; + this.inputString = inputString; + //Figure out how many rows there will be + int numRows = getCleanInputString().length() / keyword.length(); + //Get the number of characters the input is over the limit + int numCharsOver = getCleanInputString().length() % keyword.length(); + if(numCharsOver > 0){ + //Get the first n of the characters in the keyword and their encoded column locations + ArrayList originalLocations = getKeywordOriginalLocations(); + ArrayList longColumns = new ArrayList(); + for(int cnt = 0;cnt < numCharsOver;++cnt){ + longColumns.add(originalLocations.get(cnt)); } - //Wrap around the grid when you reach the bottom - if(row == grid.size()){ - row = 1; + //Add letters where they need to be added to fill out the grid + StringBuilder input = new StringBuilder(); + int col = 0; + int row = 0; + for(char ch : inputString.toCharArray()){ + if(!Character.isAlphabetic(ch)){ + input.append(ch); + continue; + } + if(row < numRows){ + input.append(ch); + ++row; + } + else{ + if(longColumns.contains(col)){ + input.append(ch); + row = 0; + } + else{ + input.append(characterToAdd); + ++charsAdded; + input.append(ch); + row = 1; + } + ++col; + } + } + if(!longColumns.contains(col)){ + input.append(characterToAdd); + ++charsAdded; + } + inputString = input.toString(); + } + + //Save the input + this.inputString = inputString; + + if(this.inputString.isBlank() || getCleanInputString().isBlank()){ + throw new InvalidInputException("Input cannot be blank"); + } + } + //Creates the output string from the grid + private String createOutputStringFromColumns(){ + //Get the current rows of any characters that you added + ArrayList colsAddedTo = new ArrayList(); + if(removePadding){ + ArrayList cols = getKeywordOriginalLocations(); + Collections.reverse(cols); + for(int cnt = 0;cnt < charsAdded;++cnt){ + colsAddedTo.add(cols.get(cnt)); + } + } + else{ + charsAdded = 0; + } + + //Turn the grid into a string + StringBuilder gridOutput = new StringBuilder(); + for(int col = 0;col < grid.get(0).size();++col){ + for(int row = 1;row < grid.size();++row){ + gridOutput.append(grid.get(row).get(col)); + } + if(colsAddedTo.contains(col)){ + gridOutput.deleteCharAt(gridOutput.length() - 1); + } + } + + //Preserve any remaining symbols in the string + StringBuilder output = new StringBuilder(); + for(int outputLoc = 0, inputLoc = 0;inputLoc < (inputString.length() - charsAdded);){ + char inputChar = inputString.charAt(inputLoc++); + if(Character.isUpperCase(inputChar)){ + output.append(Character.toUpperCase(gridOutput.charAt(outputLoc++))); + } + else if(Character.isLowerCase(inputChar)){ + output.append(Character.toLowerCase(gridOutput.charAt(outputLoc++))); + } + else{ + output.append(inputChar); + } + } + + //Save and return the output + outputString = output.toString(); + return outputString; + } + private String createOutputStringFromRows(){ + //Turn the grid into a string + StringBuilder gridOutput = new StringBuilder(); + for(int row = 1;row < grid.size();++row){ + for(int col = 0;col < grid.get(row).size();++col){ + gridOutput.append(grid.get(row).get(col)); + } + } + //Remove any added characters + if(removePadding){ + for(int cnt = 0;cnt < charsAdded;++cnt){ + gridOutput.deleteCharAt(gridOutput.length() - 1); + } + } + else{ + charsAdded = 0; + } + + ArrayList colsAddedTo = new ArrayList(); + if(removePadding){ + ArrayList cols = getKeywordOriginalLocations(); + Collections.reverse(cols); + for(int cnt = 0;cnt < charsAdded;++cnt){ + colsAddedTo.add(cols.get(cnt)); + } + } + //Preserve any remaining symbols in the string + StringBuilder output = new StringBuilder(); + for(int outputLoc = 0, inputLoc = 0, row = 1, col = 0;inputLoc < inputString.length();){ + char inputChar = inputString.charAt(inputLoc++); + if(((row + 1) == grid.size()) && (colsAddedTo.contains(col)) && (Character.isAlphabetic(inputChar))){ ++col; + row = 1; + continue; + } + + if(Character.isUpperCase(inputChar)){ + output.append(Character.toUpperCase(gridOutput.charAt(outputLoc++))); + ++row; + } + else if(Character.isLowerCase(inputChar)){ + output.append(Character.toLowerCase(gridOutput.charAt(outputLoc++))); + ++row; + } + else{ + output.append(inputChar); + } + + if(row == grid.size()){ + ++col; + row = 1; } } @@ -88,57 +285,137 @@ public class Columnar{ return outputString; } //Strips invalid characters from the keyword and creates the grid - private void setKeyword(String keyword){ + private void setKeyword(String keyword) throws InvalidKeywordException{ + if(keyword == null){ + throw new NullPointerException("Keyword cannot be null"); + } + this.keyword = keyword.toUpperCase().replaceAll("[^A-Z]", ""); + + //Make sure a valid keyword is present + if(this.keyword.length() < 2){ + throw new InvalidKeywordException("The keyword must contain at least 2 letters"); + } + } + //Set the character that is added to the end of the string + private void setCharacterToAdd(char characterToAdd) throws InvalidCharacterException{ + if(!Character.isAlphabetic(characterToAdd)){ + throw new InvalidCharacterException("Character to add must be a letter"); + } + + if(!preserveCapitals){ + this.characterToAdd = Character.toUpperCase(characterToAdd); + } + else{ + this.characterToAdd = characterToAdd; + } + } + //Returns a list of integers that represents the location of the characters of the keyword in alphabetic order + private ArrayList getKeywordAlphaLocations(){ + ArrayList orderedLocations = new ArrayList(); + //go through every letter and check it against the keyword + for(char ch = 'A';ch <= 'Z';++ch){ + for(int cnt = 0;cnt < keyword.length();++cnt){ + //If the current letter is the same as the letter we are looking for add the location to the array + if(keyword.charAt(cnt) == ch){ + orderedLocations.add(cnt); + } + } + } + + //Return the alphabetic locations + return orderedLocations; + } + private ArrayList getKeywordOriginalLocations(){ + //Figure out the order the columns are in + ArrayList orderedLocations = getKeywordAlphaLocations(); + //Figure out what order the columns need rearanged to + ArrayList originalOrder = new ArrayList(); + for(int orgCnt = 0;orgCnt < orderedLocations.size();++orgCnt){ + for(int orderedCnt = 0;orderedCnt < orderedLocations.size();++orderedCnt){ + if(orderedLocations.get(orderedCnt) == orgCnt){ + originalOrder.add(orderedCnt); + break; + } + } + } + return originalOrder; } //Rearanges the grid based on the list of numbers given - private void rearangeList(ArrayList listOrder){ - //TODO: + private void rearangeGrid(ArrayList listOrder){ + //Create a new grid and make sure it is the same size as the original grid + int numCol = grid.get(0).size(); + ArrayList> newGrid = new ArrayList>(grid.size()); + for(int cnt = 0;cnt < grid.size();++cnt){ + newGrid.add(new ArrayList(numCol)); + } + + //Step through the list order, pull out the columns, and add them to the new grid + for(int col : listOrder){ + for(int row = 0;row < grid.size();++row){ + newGrid.get(row).add(grid.get(row).get(col)); + } + } + + //Save the new grid + grid = newGrid; } //Encodes inputString using the Columnar cipher and stores the result in outputString private String encode(){ - //TODO: - return null; + //Create the grid + createGridEncode(); + //Figure out the new column order + ArrayList orderedLocations = getKeywordAlphaLocations(); + //Rearange the grid to the new order + rearangeGrid(orderedLocations); + //Create and return the output + return createOutputStringFromColumns(); } //Decodes inputString using the Columnar cipher and stores the result in outputString private String decode(){ - //TODO: - return null; + //Create the grid + createGridDecode(); + ArrayList originalOrder = getKeywordOriginalLocations(); + //Rearange the grid to the original order + rearangeGrid(originalOrder); + //Create and return the output + return createOutputStringFromRows(); } - public Columnar(){ + public Columnar() throws InvalidCharacterException{ preserveCapitals = false; preserveWhitespace = false; preserveSymbols = false; - characterToAdd = 'X'; + removePadding = false; + setCharacterToAdd('x'); reset(); } - public Columnar(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols){ + public Columnar(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols, boolean removePadding) throws InvalidCharacterException{ this.preserveCapitals = preserveCapitals; this.preserveWhitespace = preserveWhitespace; this.preserveSymbols = preserveSymbols; - characterToAdd = 'X'; + this.removePadding = removePadding; + setCharacterToAdd('x'); reset(); } - public Columnar(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols, char characterToAdd){ + public Columnar(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols, boolean removePadding, char characterToAdd) throws InvalidCharacterException{ this.preserveCapitals = preserveCapitals; this.preserveWhitespace = preserveWhitespace; this.preserveSymbols = preserveSymbols; - characterToAdd = 'X'; + this.removePadding = removePadding; + setCharacterToAdd(characterToAdd); reset(); } //Sets the keyword, grid, and inputString and encodes the message - public String encode(String keyword, String inputString){ + public String encode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{ setKeyword(keyword); - setInputString(inputString); - createGrid(); + setInputStringEncode(inputString); return encode(); } //Sets the keyword, grid, and inputString and decodes the message - public String decode(String keyword, String inputString){ + public String decode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{ setKeyword(keyword); - setInputString(inputString); - createGrid(); + setInputStringDecode(inputString); return decode(); } @@ -148,6 +425,7 @@ public class Columnar{ outputString = ""; keyword = ""; grid = new ArrayList>(); + charsAdded = 0; } //Gets public String getInputString(){ diff --git a/src/test/java/com/mattrixwv/CipherStreamJava/polySubstitution/TestColumnar.java b/src/test/java/com/mattrixwv/CipherStreamJava/polySubstitution/TestColumnar.java index 3104eb9..dbdca07 100644 --- a/src/test/java/com/mattrixwv/CipherStreamJava/polySubstitution/TestColumnar.java +++ b/src/test/java/com/mattrixwv/CipherStreamJava/polySubstitution/TestColumnar.java @@ -5,16 +5,472 @@ package com.mattrixwv.CipherStreamJava.polySubstitution; +import static org.junit.Assert.assertEquals; + +import com.mattrixwv.CipherStreamJava.exceptions.InvalidCharacterException; +import com.mattrixwv.CipherStreamJava.exceptions.InvalidInputException; +import com.mattrixwv.CipherStreamJava.exceptions.InvalidKeywordException; + import org.junit.Test; public class TestColumnar{ @Test - public void testEncode(){ - Columnar cipher = new Columnar(true, true, true); + public void testEncode() throws InvalidCharacterException, InvalidKeywordException, InvalidInputException{ + Columnar cipher = new Columnar(true, true, true, false); + + //Test lowercase encoding + String inputString = "messagetoencode"; + String keyword = "keyword"; + String correctOutput = "edxeoxmteacxgoxsnxsex"; + String output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed lowercase encoding.", correctOutput, output); + //Test uppercase encoding + inputString = "MESSAGETOENCODE"; + keyword = "keyword"; + correctOutput = "EDXEOXMTEACXGOXsnxsex"; + output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed uppercase encoding.", correctOutput, output); + + //Test whitespace encoding + inputString = "message to encode"; + keyword = "keyword"; + correctOutput = "edxeoxm te acxgoxsnxsex"; + output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed whitespace encoding.", correctOutput, output); + + //Test symbol encoding + inputString = "message@to-encode"; + keyword = "keyword"; + correctOutput = "edxeoxm@te-acxgoxsnxsex"; + output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed symbol encoding.", correctOutput, output); + + //Test mixed case, whitespace, symbol encoding + inputString = "Message to*encode"; + keyword = "keyword"; + correctOutput = "Edxeoxm te*acxgoxsnxsex"; + output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed whitespace encoding.", correctOutput, output); } @Test - public void testDecode(){ - Columnar cipher = new Columnar(true, true, true); + public void testNoCapitalEncode() throws InvalidCharacterException, InvalidKeywordException, InvalidInputException{ + Columnar cipher = new Columnar(false, true, true, false); + + //Test lowercase encoding + String inputString = "messagetoencode"; + String keyword = "keyword"; + String correctOutput = "EDXEOXMTEACXGOXSNXSEX"; + String output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed no capitals lowercase encoding.", correctOutput, output); + //Test uppercase encoding + inputString = "MESSAGETOENCODE"; + keyword = "keyword"; + correctOutput = "EDXEOXMTEACXGOXSNXSEX"; + output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed no capitals uppercase encoding.", correctOutput, output); + + //Test whitespace encoding + inputString = "message to encode"; + keyword = "keyword"; + correctOutput = "EDXEOXM TE ACXGOXSNXSEX"; + output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed no capitals whitespace encoding.", correctOutput, output); + + //Test symbol encoding + inputString = "message@to-encode"; + keyword = "keyword"; + correctOutput = "EDXEOXM@TE-ACXGOXSNXSEX"; + output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed no capitals symbol encoding.", correctOutput, output); + + //Test mixed case, whitespace, symbol encoding + inputString = "Message to*encode"; + keyword = "keyword"; + correctOutput = "EDXEOXM TE*ACXGOXSNXSEX"; + output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed no capitals whitespace encoding.", correctOutput, output); + } + @Test + public void testNoWhitespaceEncode() throws InvalidCharacterException, InvalidKeywordException, InvalidInputException{ + Columnar cipher = new Columnar(true, false, true, false); + + //Test lowercase encoding + String inputString = "messagetoencode"; + String keyword = "keyword"; + String correctOutput = "edxeoxmteacxgoxsnxsex"; + String output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed no whitespace lowercase encoding.", correctOutput, output); + //Test uppercase encoding + inputString = "MESSAGETOENCODE"; + keyword = "keyword"; + correctOutput = "EDXEOXMTEACXGOXsnxsex"; + output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed no whitespace uppercase encoding.", correctOutput, output); + + //Test whitespace encoding + inputString = "message to encode"; + keyword = "keyword"; + correctOutput = "edxeoxmteacxgoxsnxsex"; + output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed no whitespace whitespace encoding.", correctOutput, output); + + //Test symbol encoding + inputString = "message@to-encode"; + keyword = "keyword"; + correctOutput = "edxeoxm@te-acxgoxsnxsex"; + output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed no whitespace symbol encoding.", correctOutput, output); + + //Test mixed case, whitespace, symbol encoding + inputString = "Message to*encode"; + keyword = "keyword"; + correctOutput = "Edxeoxmte*acxgoxsnxsex"; + output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed no whitespace whitespace encoding.", correctOutput, output); + } + @Test + public void testNoSymbolEncode() throws InvalidCharacterException, InvalidKeywordException, InvalidInputException{ + Columnar cipher = new Columnar(true, true, false, false); + + //Test lowercase encoding + String inputString = "messagetoencode"; + String keyword = "keyword"; + String correctOutput = "edxeoxmteacxgoxsnxsex"; + String output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed no symbol lowercase encoding.", correctOutput, output); + //Test uppercase encoding + inputString = "MESSAGETOENCODE"; + keyword = "keyword"; + correctOutput = "EDXEOXMTEACXGOXsnxsex"; + output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed no symbol uppercase encoding.", correctOutput, output); + + //Test whitespace encoding + inputString = "message to encode"; + keyword = "keyword"; + correctOutput = "edxeoxm te acxgoxsnxsex"; + output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed no symbol whitespace encoding.", correctOutput, output); + + //Test symbol encoding + inputString = "message@to-encode"; + keyword = "keyword"; + correctOutput = "edxeoxmteacxgoxsnxsex"; + output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed no symbol symbol encoding.", correctOutput, output); + + //Test mixed case, whitespace, symbol encoding + inputString = "Message to*encode"; + keyword = "keyword"; + correctOutput = "Edxeoxm teacxgoxsnxsex"; + output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed no symbol whitespace encoding.", correctOutput, output); + } + @Test + public void testNoPaddingEncoding() throws InvalidCharacterException, InvalidKeywordException, InvalidInputException{ + Columnar cipher = new Columnar(true, true, true, true); + + //Test lowercase encoding + String inputString = "messagetoencode"; + String keyword = "keyword"; + String correctOutput = "edeomteacgosnse"; + String output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed no padding lowercase encoding.", correctOutput, output); + //Test uppercase encoding + inputString = "MESSAGETOENCODE"; + keyword = "keyword"; + correctOutput = "EDEOMTEACGOSNSE"; + output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed no padding uppercase encoding.", correctOutput, output); + + //Test whitespace encoding + inputString = "message to encode"; + keyword = "keyword"; + correctOutput = "edeomte ac gosnse"; + output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed no padding whitespace encoding.", correctOutput, output); + + //Test symbol encoding + inputString = "message@to-encode"; + keyword = "keyword"; + correctOutput = "edeomte@ac-gosnse"; + output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed no padding symbol encoding.", correctOutput, output); + + //Test mixed case, whitespace, symbol encoding + inputString = "Message To*encode"; + keyword = "keyword"; + correctOutput = "Edeomte Ac*gosnse"; + output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed no padding whitespace encoding.", correctOutput, output); + } + @Test + public void testNoCapitalWhitespaceSymbolEncode() throws InvalidCharacterException, InvalidKeywordException, InvalidInputException{ + Columnar cipher = new Columnar(false, false, false, false); + + //Test lowercase encoding + String inputString = "messagetoencode"; + String keyword = "keyword"; + String correctOutput = "EDXEOXMTEACXGOXSNXSEX"; + String output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed secure lowercase encoding.", correctOutput, output); + //Test uppercase encoding + inputString = "MESSAGETOENCODE"; + keyword = "keyword"; + correctOutput = "EDXEOXMTEACXGOXSNXSEX"; + output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed secure uppercase encoding.", correctOutput, output); + + //Test whitespace encoding + inputString = "message to encode"; + keyword = "keyword"; + correctOutput = "EDXEOXMTEACXGOXSNXSEX"; + output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed secure whitespace encoding.", correctOutput, output); + + //Test symbol encoding + inputString = "message@to-encode"; + keyword = "keyword"; + correctOutput = "EDXEOXMTEACXGOXSNXSEX"; + output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed secure symbol encoding.", correctOutput, output); + + //Test mixed case, whitespace, symbol encoding + inputString = "Message to*encode"; + keyword = "keyword"; + correctOutput = "EDXEOXMTEACXGOXSNXSEX"; + output = cipher.encode(keyword, inputString); + assertEquals("Columnar failed secure whitespace encoding.", correctOutput, output); + } + + + @Test + public void testDecode() throws InvalidCharacterException, InvalidKeywordException, InvalidInputException{ + Columnar cipher = new Columnar(true, true, true, false); + + //Test lowercase decoding + String inputString = "edxeoxmteacxgoxsnxsex"; + String keyword = "keyword"; + String correctOutput = "messagetoencodexxxxxx"; + String output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed lowercase decoding.", correctOutput, output); + //Test uppercase decoding + inputString = "EDXEOXMTEACXGOXsnxsex"; + keyword = "keyword"; + correctOutput = "MESSAGETOENCODExxxxxx"; + output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed uppercase decoding.", correctOutput, output); + + //Test whitespace decoding + inputString = "edxeoxm te acxgoxsnxsex"; + keyword = "keyword"; + correctOutput = "message to encodexxxxxx"; + output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed whitespace decoding.", correctOutput, output); + + //Test symbol decoding + inputString = "edxeoxm@te-acxgoxsnxsex"; + keyword = "keyword"; + correctOutput = "message@to-encodexxxxxx"; + output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed symbol decoding.", correctOutput, output); + + //Test mixed case, whitespace, symbol decoding + inputString = "Edxeoxm te*acxgoxsnxsex"; + keyword = "keyword"; + correctOutput = "Message to*encodexxxxxx"; + output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed whitespace decoding.", correctOutput, output); + } + @Test + public void testNoCapitalDecode() throws InvalidCharacterException, InvalidKeywordException, InvalidInputException{ + Columnar cipher = new Columnar(false, true, true, false); + + //Test lowercase decoding + String inputString = "edxeoxmteacxgoxsnxsex"; + String keyword = "keyword"; + String correctOutput = "MESSAGETOENCODEXXXXXX"; + String output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed no capital lowercase decoding.", correctOutput, output); + //Test uppercase decoding + inputString = "EDXEOXMTEACXGOXsnxsex"; + keyword = "keyword"; + correctOutput = "MESSAGETOENCODEXXXXXX"; + output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed no capital uppercase decoding.", correctOutput, output); + + //Test whitespace decoding + inputString = "edxeoxm te acxgoxsnxsex"; + keyword = "keyword"; + correctOutput = "MESSAGE TO ENCODEXXXXXX"; + output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed no capital whitespace decoding.", correctOutput, output); + + //Test symbol decoding + inputString = "edxeoxm@te-acxgoxsnxsex"; + keyword = "keyword"; + correctOutput = "MESSAGE@TO-ENCODEXXXXXX"; + output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed no capital symbol decoding.", correctOutput, output); + + //Test mixed case, whitespace, symbol decoding + inputString = "Edxeoxm te*acxgoxsnxsex"; + keyword = "keyword"; + correctOutput = "MESSAGE TO*ENCODEXXXXXX"; + output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed no capital whitespace decoding.", correctOutput, output); + } + @Test + public void testNoWhitespaceDecode() throws InvalidCharacterException, InvalidKeywordException, InvalidInputException{ + Columnar cipher = new Columnar(true, false, true, false); + + //Test lowercase decoding + String inputString = "edxeoxmteacxgoxsnxsex"; + String keyword = "keyword"; + String correctOutput = "messagetoencodexxxxxx"; + String output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed no whitespace lowercase decoding.", correctOutput, output); + //Test uppercase decoding + inputString = "EDXEOXMTEACXGOXsnxsex"; + keyword = "keyword"; + correctOutput = "MESSAGETOENCODExxxxxx"; + output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed no whitespace uppercase decoding.", correctOutput, output); + + //Test whitespace decoding + inputString = "edxeoxm te acxgoxsnxsex"; + keyword = "keyword"; + correctOutput = "messagetoencodexxxxxx"; + output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed no whitespace whitespace decoding.", correctOutput, output); + + //Test symbol decoding + inputString = "edxeoxm@te-acxgoxsnxsex"; + keyword = "keyword"; + correctOutput = "message@to-encodexxxxxx"; + output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed no whitespace symbol decoding.", correctOutput, output); + + //Test mixed case, whitespace, symbol decoding + inputString = "Edxeoxm te*acxgoxsnxsex"; + keyword = "keyword"; + correctOutput = "Messageto*encodexxxxxx"; + output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed no whitespace whitespace decoding.", correctOutput, output); + } + @Test + public void testNoSymbolDecode() throws InvalidCharacterException, InvalidKeywordException, InvalidInputException{ + Columnar cipher = new Columnar(true, true, false, false); + + //Test lowercase decoding + String inputString = "edxeoxmteacxgoxsnxsex"; + String keyword = "keyword"; + String correctOutput = "messagetoencodexxxxxx"; + String output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed no symbol lowercase decoding.", correctOutput, output); + //Test uppercase decoding + inputString = "EDXEOXMTEACXGOXsnxsex"; + keyword = "keyword"; + correctOutput = "MESSAGETOENCODExxxxxx"; + output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed no symbol uppercase decoding.", correctOutput, output); + + //Test whitespace decoding + inputString = "edxeoxm te acxgoxsnxsex"; + keyword = "keyword"; + correctOutput = "message to encodexxxxxx"; + output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed no symbol whitespace decoding.", correctOutput, output); + + //Test symbol decoding + inputString = "edxeoxm@te-acxgoxsnxsex"; + keyword = "keyword"; + correctOutput = "messagetoencodexxxxxx"; + output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed no symbol symbol decoding.", correctOutput, output); + + //Test mixed case, whitespace, symbol decoding + inputString = "Edxeoxm te*acxgoxsnxsex"; + keyword = "keyword"; + correctOutput = "Message toencodexxxxxx"; + output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed no symbol whitespace decoding.", correctOutput, output); + } + @Test + public void testNoPaddingDecoding() throws InvalidCharacterException, InvalidKeywordException, InvalidInputException{ + Columnar cipher = new Columnar(true, true, true, true); + + //Test lowercase decoding + String inputString = "edeomteacgosnse"; + String keyword = "keyword"; + String correctOutput = "messagetoencode"; + String output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed no padding lowercase decoding.", correctOutput, output); + //Test uppercase decoding + inputString = "EDEOMTEACGOSNSE"; + keyword = "keyword"; + correctOutput = "MESSAGETOENCODE"; + output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed no padding uppercase decoding.", correctOutput, output); + + //Test whitespace decoding + inputString = "edeomte ac gosnse"; + keyword = "keyword"; + correctOutput = "message to encode"; + output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed no padding whitespace decoding.", correctOutput, output); + + //Test symbol decoding + inputString = "edeomte@ac-gosnse"; + keyword = "keyword"; + correctOutput = "message@to-encode"; + output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed no padding symbol decoding.", correctOutput, output); + + //Test mixed case, whitespace, symbol decoding + inputString = "Edeomte ac*gosnse"; + keyword = "keyword"; + correctOutput = "Message to*encode"; + output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed no padding whitespace decoding.", correctOutput, output); + } + @Test + public void testNoCapitalWhitespaceSymbolDecode() throws InvalidCharacterException, InvalidKeywordException, InvalidInputException{ + Columnar cipher = new Columnar(false, false, false, false); + + //Test lowercase decoding + String inputString = "edxeoxmteacxgoxsnxsex"; + String keyword = "keyword"; + String correctOutput = "MESSAGETOENCODEXXXXXX"; + String output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed secure lowercase decoding.", correctOutput, output); + //Test uppercase decoding + inputString = "EDXEOXMTEACXGOXsnxsex"; + keyword = "keyword"; + correctOutput = "MESSAGETOENCODEXXXXXX"; + output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed secure uppercase decoding.", correctOutput, output); + + //Test whitespace decoding + inputString = "edxeoxm te acxgoxsnxsex"; + keyword = "keyword"; + correctOutput = "MESSAGETOENCODEXXXXXX"; + output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed secure whitespace decoding.", correctOutput, output); + + //Test symbol decoding + inputString = "edxeoxm@te-acxgoxsnxsex"; + keyword = "keyword"; + correctOutput = "MESSAGETOENCODEXXXXXX"; + output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed secure symbol decoding.", correctOutput, output); + + //Test mixed case, whitespace, symbol decoding + inputString = "Edxeoxm te*acxgoxsnxsex"; + keyword = "keyword"; + correctOutput = "MESSAGETOENCODEXXXXXX"; + output = cipher.decode(keyword, inputString); + assertEquals("Columnar failed secure whitespace decoding.", correctOutput, output); } }