Updated more tests

This commit is contained in:
2023-04-28 20:01:09 -04:00
parent 59885b8df6
commit 3966f46024
15 changed files with 2861 additions and 1606 deletions

View File

@@ -1,7 +1,7 @@
//MattrixwvWebsite/src/main/java/com/mattrixwv/CipherStreamJava/polySubstitution/Columnar.java
//Mattrixwv
// Created: 01-16-22
//Modified: 07-09-22
//Modified: 04-26-23
package com.mattrixwv.cipherstream.polysubstitution;
@@ -18,7 +18,7 @@ import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException;
public class Columnar{
protected static final Logger logger = LoggerFactory.getLogger(Columnar.class);
protected static Logger logger = LoggerFactory.getLogger(Columnar.class);
//Fields
protected String inputString; //The message that needs to be encoded/decoded
@@ -108,7 +108,7 @@ public class Columnar{
inputString = inputString.replaceAll("\\s", "");
}
if(!preserveSymbols){
logger.debug("Remoing symbols");
logger.debug("Removing symbols");
inputString = inputString.replaceAll("[^a-zA-Z\\s]", "");
}
@@ -158,7 +158,7 @@ public class Columnar{
if(!preserveWhitespace){
logger.debug("Removing whitespace");
inputString = inputString.replaceAll("[\\s]", "");
inputString = inputString.replaceAll("\\s", "");
}
if(!preserveSymbols){
logger.debug("Removing symbols");
@@ -271,8 +271,8 @@ public class Columnar{
}
//Save and return the output
logger.debug("Output string '{}'", output);
outputString = output.toString();
logger.debug("Output string '{}'", output.toString());
}
protected void createOutputStringFromRows(){
logger.debug("Creating output string for decoding");
@@ -315,15 +315,22 @@ public class Columnar{
continue;
}
logger.debug("Working character {}", gridOutput.charAt(outputLoc));
if(Character.isUpperCase(inputChar)){
logger.debug("Adding upper case");
output.append(Character.toUpperCase(gridOutput.charAt(outputLoc++)));
++row;
}
else if(Character.isLowerCase(inputChar)){
logger.debug("Adding lower case");
output.append(Character.toLowerCase(gridOutput.charAt(outputLoc++)));
++row;
}
else{
logger.debug("Adding symbol");
output.append(inputChar);
}
@@ -334,20 +341,21 @@ public class Columnar{
}
//Save and return the output
logger.debug("Decoded output string '{}'", output);
outputString = output.toString();
logger.debug("Decoded output string '{}'", outputString);
}
//Strips invalid characters from the keyword and creates the grid
protected void setKeyword(String keyword) throws InvalidKeywordException{
//Ensure the keyword isn't null
if(keyword == null){
throw new NullPointerException("Keyword cannot be null");
throw new InvalidKeywordException("Keyword cannot be null");
}
logger.debug("Original keyword {}", keyword);
//Strip all non-letter characters and change them to uppercase
this.keyword = keyword.toUpperCase().replaceAll("[^A-Z]", "");
keyword = keyword.toUpperCase().replaceAll("[^A-Z]", "");
this.keyword = keyword;
logger.debug("Cleaned keyword {}", keyword);
@@ -362,15 +370,14 @@ public class Columnar{
throw new InvalidCharacterException("Character to add must be a letter");
}
logger.debug("Setting character to add");
logger.debug("Setting character to add {}", characterToAdd);
if(!preserveCapitals){
this.characterToAdd = Character.toUpperCase(characterToAdd);
}
else{
this.characterToAdd = characterToAdd;
characterToAdd = Character.toUpperCase(characterToAdd);
}
this.characterToAdd = characterToAdd;
logger.debug("Character to add for padding {}", characterToAdd);
}
//Returns a list of integers that represents the location of the characters of the keyword in alphabetic order
@@ -409,7 +416,7 @@ public class Columnar{
}
//Returning the locations
logger.debug("Array of keyword letters {}", orderedLocations);
logger.debug("Array of keyword letters {}", originalOrder);
return originalOrder;
}
//Rearanges the grid based on the list of numbers given

View File

@@ -1,12 +1,15 @@
//CipherStreamJava/src/main/java/com/mattrixwv/CipherStreamJava/polySubstitution/Hill.java
//Mattrixwv
// Created: 01-31-22
//Modified: 02-17-22
//Modified: 04-27-23
package com.mattrixwv.cipherstream.polysubstitution;
import java.util.ArrayList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.mattrixwv.cipherstream.exceptions.InvalidCharacterException;
import com.mattrixwv.cipherstream.exceptions.InvalidInputException;
import com.mattrixwv.cipherstream.exceptions.InvalidKeyException;
@@ -16,28 +19,34 @@ import com.mattrixwv.matrix.exceptions.InvalidScalarException;
public class Hill{
private boolean preserveCapitals;
private boolean preserveWhitespace;
private boolean preserveSymbols;
private boolean removePadding;
private String inputString;
private String outputString;
private char characterToAdd;
private int charsAdded;
private ModMatrix key;
protected static Logger logger = LoggerFactory.getLogger(Hill.class);
protected boolean preserveCapitals;
protected boolean preserveWhitespace;
protected boolean preserveSymbols;
protected String inputString;
protected String outputString;
protected char characterToAdd;
protected ModMatrix key;
protected void setKey(ModMatrix key) throws InvalidKeyException{
logger.debug("Setting key");
private void setKey(ModMatrix key) throws InvalidKeyException{
//Make sure the mod is correct
logger.debug("Testing mod");
if(key.getMod() != 26){
throw new InvalidKeyException("This algorithm uses the english alphabet, so the mod for the key must be 26");
}
//Make sure the matrix is square
logger.debug("Testing square");
if(!key.isSquare()){
throw new InvalidKeyException("The key must be a square matrix");
}
//Make sure the matrix is invertable
logger.debug("Testing invertable");
try{
key.inverse();
}
@@ -46,25 +55,37 @@ public class Hill{
}
//Set the key
logger.debug("key = {}", key);
this.key = new ModMatrix(key);
}
private void setInputString(String inputString) throws InvalidInputException{
//Remove anything that needs removed
protected void setInputStringEncode(String inputString) throws InvalidInputException{
logger.debug("Setting input string for encoding");
if(inputString == null){
throw new InvalidInputException("Input must not be null");
}
logger.debug("Original input string '{}'", inputString);
//Remove anything that needs removed
if(!preserveCapitals){
logger.debug("Removing capitals");
inputString = inputString.toUpperCase();
}
if(!preserveWhitespace){
logger.debug("Removing whitespace");
inputString = inputString.replaceAll("[\\s]", "");
}
if(!preserveSymbols){
logger.debug("Removing symbols");
inputString = inputString.replaceAll("[^a-zA-Z\\s]", "");
}
//Make sure the input is correct length
logger.debug("Checking length");
this.inputString = inputString;
int cleanLength = getCleanInputString().length();
int charsToAdd = (cleanLength % key.getNumRows());
@@ -73,12 +94,13 @@ public class Hill{
if(charsToAdd != 0){
charsToAdd = key.getNumRows() - charsToAdd;
}
logger.debug("Adding {} characters", charsToAdd);
for(int cnt = 0;cnt < charsToAdd;++cnt){
inputStringBuilder.append(characterToAdd);
}
charsAdded = charsToAdd;
inputString = inputStringBuilder.toString();
logger.debug("Cleaned input string '{}'", inputString);
this.inputString = inputString;
//Make sure the input isn't blank
@@ -86,10 +108,51 @@ public class Hill{
throw new InvalidInputException("Input cannot be blank");
}
}
private String getCleanInputString(){
return inputString.toUpperCase().replaceAll("[^A-Z]", "");
protected void setInputStringDecode(String inputString) throws InvalidInputException{
logger.debug("Setting input string for decoding");
if(inputString == null){
throw new InvalidInputException("Input must not be null");
}
logger.debug("Original input string '{}'", inputString);
//Remove anything that needs removed
if(!preserveCapitals){
logger.debug("Removing capitals");
inputString = inputString.toUpperCase();
}
if(!preserveWhitespace){
logger.debug("Removing whitespace");
inputString = inputString.replaceAll("[\\s]", "");
}
if(!preserveSymbols){
logger.debug("Removing symbols");
inputString = inputString.replaceAll("[^a-zA-Z\\s]", "");
}
logger.debug("Cleaned input string '{}'", inputString);
this.inputString = inputString;
logger.debug("Checking length");
if(getCleanInputString().isBlank() || ((getCleanInputString().length() % key.getNumRows()) != 0)){
throw new InvalidInputException("Length of input string must be a multiple of the number of rows in the key");
}
}
private void setCharacterToAdd(char characterToAdd) throws InvalidCharacterException{
protected String getCleanInputString(){
logger.debug("Cleaning inputString");
String cleanInputString = inputString.toUpperCase().replaceAll("[^A-Z]", "");
logger.debug("Clean input string '{}'", cleanInputString);
return cleanInputString;
}
protected void setCharacterToAdd(char characterToAdd) throws InvalidCharacterException{
logger.debug("Setting character to add {}", characterToAdd);
//Make sure the character is a letter
if(!Character.isAlphabetic(characterToAdd)){
throw new InvalidCharacterException("Character to add must be a letter");
@@ -97,37 +160,45 @@ public class Hill{
//Save the characterToAdd
if(!preserveCapitals){
this.characterToAdd = Character.toUpperCase(characterToAdd);
}
else{
this.characterToAdd = characterToAdd;
logger.debug("Removing capitals");
characterToAdd = Character.toUpperCase(characterToAdd);
}
logger.debug("Cleaned character {}", characterToAdd);
this.characterToAdd = characterToAdd;
}
private String polishOutputString(){
protected String polishOutputString(){
logger.debug("Polishing output string");
//Add the extra characters back to the output and remove the added characters
int outputCnt = 0;
StringBuilder outputBuilder = new StringBuilder();
for(char ch : inputString.toCharArray()){
logger.debug("Current char {}", ch);
if(Character.isUpperCase(ch)){
logger.debug("Uppercase");
outputBuilder.append(Character.toUpperCase(outputString.charAt(outputCnt++)));
}
else if(Character.isLowerCase(ch)){
logger.debug("Lowercase");
outputBuilder.append(Character.toLowerCase(outputString.charAt(outputCnt++)));
}
else{
logger.debug("Symbol");
outputBuilder.append(ch);
}
}
if(removePadding){
String tempString = outputBuilder.substring(0, outputBuilder.length() - charsAdded);
outputBuilder = new StringBuilder();
outputBuilder.append(tempString);
}
logger.debug("Polished string '{}'", outputBuilder.toString());
return outputBuilder.toString();
}
private ArrayList<ModMatrix> getInputVectors(){
protected ArrayList<ModMatrix> getInputVectors(){
logger.debug("Generating input vectors");
//Get the number of columns in the key
int numCols = key.getNumCols();
@@ -139,6 +210,7 @@ public class Hill{
for(int cnt = 0;cnt < cleanInput.length();cnt += numCols){
String subString = cleanInput.substring(cnt, cnt + numCols);
int[] grid = new int[numCols];
logger.debug("Current substring '{}'", subString);
//Subtract 65 from each character so that A=0, B=1, ...
for(int subCnt = 0;subCnt < subString.length();++subCnt){
@@ -148,6 +220,7 @@ public class Hill{
//Create a vector from the new values
ModMatrix vector = new ModMatrix(26);
vector.addCol(grid);
logger.debug("Current vector {}", vector);
//Add the vector to the array
vectors.add(vector);
@@ -156,10 +229,14 @@ public class Hill{
//Return the array of vectors
return vectors;
}
private String getOutputFromVectors(ArrayList<ModMatrix> outputVectors){
protected String getOutputFromVectors(ArrayList<ModMatrix> outputVectors){
logger.debug("Turning vectors into a string");
//Go through each element in the vector
StringBuilder outputBuilder = new StringBuilder();
for(ModMatrix vector : outputVectors){
logger.debug("Current vector {}", vector);
//Add 65 to each element and add it to the string
for(int cnt = 0;cnt < vector.getNumRows();++cnt){
outputBuilder.append((char)(vector.get(cnt, 0) + 65));
@@ -167,16 +244,24 @@ public class Hill{
}
//Return the new string
return outputBuilder.toString();
String convertedString = outputBuilder.toString();
logger.debug("Converted string '{}'", convertedString);
return convertedString;
}
private String encode(){
protected void encode(){
logger.debug("Encoding");
//Get an array of vectors that we are going to encode
ArrayList<ModMatrix> inputVectors = getInputVectors();
//Multiply the key by each vector and add the result to a new vector
logger.debug("Multiplying vectors");
ArrayList<ModMatrix> outputVectors = new ArrayList<>();
for(ModMatrix inputVector : inputVectors){
logger.debug("Current input vector {}", inputVector);
ModMatrix outputVector = key.multiply(inputVector);
logger.debug("Multiplied vector {}", outputVector);
outputVectors.add(outputVector);
}
@@ -185,19 +270,23 @@ public class Hill{
//Add the extra characters back to the output and remove the added characters
outputString = polishOutputString();
//Save the output
return outputString;
}
private String decode(){
protected void decode(){
logger.debug("Decoding");
//Get the array of vectors that we are going to decode
ArrayList<ModMatrix> inputVectors = getInputVectors();
//Multiply the inverse of the key by each vector and add the result to a new vector
logger.debug("Getting inverse of key");
ModMatrix inverseKey = key.inverse();
logger.debug("Inverse of key {}", inverseKey);
ArrayList<ModMatrix> outputVectors = new ArrayList<>();
for(ModMatrix inputVector : inputVectors){
logger.debug("Current input vector {}", inputVector);
ModMatrix outputVector = inverseKey.multiply(inputVector);
logger.debug("Multiplied vector {}", outputVector);
outputVectors.add(outputVector);
}
@@ -206,32 +295,26 @@ public class Hill{
//Add the extra characters back to the output and remove the added characters
outputString = polishOutputString();
//Save the output
return outputString;
}
public Hill() throws InvalidCharacterException{
preserveCapitals = false;
preserveWhitespace = false;
preserveSymbols = false;
removePadding = false;
setCharacterToAdd('x');
reset();
}
public Hill(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols, boolean removePadding) throws InvalidCharacterException{
public Hill(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols) throws InvalidCharacterException{
this.preserveCapitals = preserveCapitals;
this.preserveWhitespace = preserveWhitespace;
this.preserveSymbols = preserveSymbols;
this.removePadding = removePadding;
setCharacterToAdd('x');
reset();
}
public Hill(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols, boolean removePadding, char characterToAdd) throws InvalidCharacterException{
public Hill(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols, char characterToAdd) throws InvalidCharacterException{
this.preserveCapitals = preserveCapitals;
this.preserveWhitespace = preserveWhitespace;
this.preserveSymbols = preserveSymbols;
this.removePadding = removePadding;
setCharacterToAdd(characterToAdd);
reset();
}
@@ -241,22 +324,25 @@ public class Hill{
}
public String encode(ModMatrix key, String inputString) throws InvalidKeyException, InvalidInputException{
setKey(key);
setInputString(inputString);
return encode();
setInputStringEncode(inputString);
encode();
return outputString;
}
public String decode(int[][] key, String inputString) throws InvalidKeyException, InvalidInputException{
return decode(new ModMatrix(key, 26), inputString);
}
public String decode(ModMatrix key, String inputString) throws InvalidKeyException, InvalidInputException{
setKey(key);
setInputString(inputString);
return decode();
setInputStringDecode(inputString);
decode();
return outputString;
}
public void reset(){
logger.debug("Resetting fields");
inputString = "";
outputString = "";
key = new ModMatrix(26);
charsAdded = 0;
}
public String getInputString(){
return inputString;

View File

@@ -6,6 +6,7 @@ package com.mattrixwv.cipherstream.polysubstitution;
public class Morse{
//TODO: This needs updated to match new standards
//Holds the Morse representation of the alphanumeric characters
private static final String[] code = {
".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", //A-L

View File

@@ -1,7 +1,7 @@
//CipherStreamJava/src/main/java/com/mattrixwv/CipherStreamJava/polySubstitution/Playfair.java
//Matthew Ellison
// Created: 07-30-21
//Modified: 07-09-22
//Modified: 04-28-23
package com.mattrixwv.cipherstream.polysubstitution;
@@ -12,15 +12,16 @@ import org.slf4j.LoggerFactory;
import com.mattrixwv.cipherstream.exceptions.InvalidCharacterException;
import com.mattrixwv.cipherstream.exceptions.InvalidInputException;
import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException;
public class Playfair{
private static final Logger logger = LoggerFactory.getLogger(Playfair.class);
protected static Logger logger = LoggerFactory.getLogger(Playfair.class);
//A class representing the location of a character in the grid
private class CharLocation{
private int x;
private int y;
protected class CharLocation{
protected int x;
protected int y;
public CharLocation(int x, int y){
this.x = x;
this.y = y;
@@ -34,23 +35,122 @@ public class Playfair{
}
//Fields
private boolean preserveCapitals; //Whether to respect captials 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 char replaced; //The letter that will need to be replaced in the grid and any input string or keyword
private char replacer; //The letter that replaced replaced in the input string or keyword
private char doubled; //The letter that will be placed between double letters in the input string if necessary or to make the string length even
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
private char[][] grid; //The grid used to encode/decode the message
protected boolean preserveCapitals; //Whether to respect captials in the output string
protected boolean preserveWhitespace; //Whether to respect whitespace in the output string
protected boolean preserveSymbols; //Whether to respect symbols in the output string
protected char replaced; //The letter that will need to be replaced in the grid and any input string or keyword
protected char replacer; //The letter that replaced replaced in the input string or keyword
protected char doubled; //The letter that will be placed between double letters in the input string if necessary or to make the string length even
protected String inputString; //The message that needs to be encoded/decoded
protected String outputString; //The encoded/decoded message
protected String keyword; //The keyword used to create the grid
protected char[][] grid; //The grid used to encode/decode the message
//Set the doubled character
protected void setDoubled(char doubled) throws InvalidCharacterException{
logger.debug("Setting doubled");
logger.debug("Original character {}", doubled);
//Make sure the character is a letter
logger.debug("Checking letter");
if(!Character.isAlphabetic(doubled)){
throw new InvalidCharacterException("The double letter replacement must be a letter");
}
//Make sure the 2 replacers are the same
logger.debug("Checking same as replacer");
if(doubled == replacer){
throw new InvalidCharacterException("The double letter replacement cannot be the same as the regular replacer");
}
//Make sure the double letter replacement isn't the same as the letter being replaced
logger.debug("Checking same as replaced");
if(doubled == replaced){
throw new InvalidCharacterException("The double letter replacement cannot be the same as the letter replaced");
}
if(!preserveCapitals){
logger.debug("Removing capitals");
doubled = Character.toUpperCase(doubled);
}
logger.debug("Setting doubled to {}", doubled);
this.doubled = doubled;
}
//Set the replacer character
protected void setReplacer(char replacer) throws InvalidCharacterException{
logger.debug("Setting replacer");
logger.debug("Original character {}", replacer);
//Make sure the character is a letter
logger.debug("Checking letter");
if(!Character.isAlphabetic(replacer)){
throw new InvalidCharacterException("The replacer must be a letter");
}
//Make sure the character isn't the same as what it is supposed to replace
logger.debug("Checking same as replaced");
if(replacer == replaced){
throw new InvalidCharacterException("The replacer cannot be the same letter as what it is replacing");
}
//Make sure the replacer isn't the same as the double letter replacer
logger.debug("Checking same as doubled");
if(replacer == doubled){
throw new InvalidCharacterException("The replacer cannot be the same as the double letter replacer");
}
if(!preserveCapitals){
logger.debug("Removing capitals");
replacer = Character.toUpperCase(replacer);
}
logger.debug("Setting replacer to {}", replacer);
this.replacer = replacer;
}
//Set the replaced character
protected void setReplaced(char replaced) throws InvalidCharacterException{
logger.debug("Setting replaced");
logger.debug("Original character {}", replaced);
//Make sure the character is a letter
logger.debug("Checking letter");
if(!Character.isAlphabetic(replaced)){
throw new InvalidCharacterException("The replaced character must be a letter");
}
//Make sure the character isn't the same as what is replacing it
logger.debug("Checking same as replacer");
if(replaced == replacer){
throw new InvalidCharacterException("The replaced letter cannot be the same as the replacing letter");
}
//Make sure the replacer isn't the same as the double letter replacer
logger.debug("Checking same as doubled");
if(replaced == doubled){
throw new InvalidCharacterException("The replaced letter cannot be the same as the replacing letter");
}
if(!preserveCapitals){
logger.debug("Removing capitals");
replaced = Character.toUpperCase(replaced);
}
logger.debug("Setting replaced to {}", replaced);
this.replaced = replaced;
}
//Create the grid from the keyword
private void createGrid(){
protected void createGrid(){
logger.debug("Creating grid from keyword");
for(int row = 0;row < 5;++row){
for(int col = 0;col < 5;++col){
char letter = keyword.charAt((5 * row) + col);
logger.debug("Letter {} going to position [{}] [{}]", letter, row, col);
grid[row][col] = letter;
}
}
@@ -58,10 +158,12 @@ public class Playfair{
logger.debug("Grid\n{}", getGrid());
}
//Strips invalid characters from the string that needs encoded/decoded
private void setInputString(String inputString, boolean encoding) throws InvalidCharacterException, InvalidInputException{
protected void setInputString(String inputString, boolean encoding) throws InvalidCharacterException, InvalidInputException{
logger.debug("Setting input string");
//Make sure the input string is not null
if(inputString == null){
throw new NullPointerException("The input string cannot be null");
throw new InvalidInputException("The input string cannot be null");
}
logger.debug("Original input string {}", inputString);
@@ -83,18 +185,14 @@ public class Playfair{
inputString = inputString.replaceAll("[^a-zA-Z\\s]", "");
}
//Make replace all of the replacers with replaced
logger.debug("Replacing all {} with {}", replaced, replacer);
inputString = inputString.replace(Character.toString(replaced), Character.toString(replacer));
//If there is nothing in the input string throw an exception
if(inputString.isBlank()){
throw new InvalidCharacterException("The input string cannot be blank");
throw new InvalidInputException("The input string cannot be blank");
}
//If this is encoding parse it and clean up any problems
if(encoding){
setEncodingInputString(inputString);
setInputStringEncode(inputString);
}
//If this is decoding just add it without parsing it
else{
@@ -105,20 +203,28 @@ public class Playfair{
logger.debug("Clean input string '{}'", inputString);
this.inputString = inputString;
if((getPreparedInputString().length() % 2) == 1){
throw new InvalidInputException("Input length must be even");
}
}
if(this.inputString.isBlank() || getPreparedInputString().isBlank()){
if(getPreparedInputString().isBlank()){
throw new InvalidInputException("Input must have at least 1 letter");
}
}
private void setEncodingInputString(String inputString){
protected void setInputStringEncode(String inputString){
logger.debug("Cleaning up input string for encoding");
//Replace characters that need replaced
logger.debug("Replacing all {} with {}", replaced, replacer);
inputString = inputString.replace(Character.toString(replaced), Character.toString(replacer));
//Check if there are any doubled characters
StringBuilder cleanInput = new StringBuilder();
int letterCount = 0;
for(int cnt = 0;cnt < inputString.length();){
logger.debug("Starting at character {}", cnt);
//Advance until you find a letter, saving the input for inclusion
StringBuilder prepend = new StringBuilder();
while((cnt < inputString.length()) && !Character.isAlphabetic(inputString.charAt(cnt))){
@@ -151,6 +257,7 @@ public class Playfair{
}
//Add all of the gathered input to the cleaned up input
logger.debug("Adding to clean input: {} {} {} {}", prepend, firstLetter, middle, secondLetter);
cleanInput.append(prepend);
cleanInput.append(firstLetter);
cleanInput.append(middle);
@@ -160,7 +267,9 @@ public class Playfair{
}
//Check if there are an odd number of characters
logger.debug("Checking odd characters");
if((letterCount % 2) == 1){
logger.debug("Adding final character to make even");
int lastLetterLocation = cleanInput.length() - 1;
while(!Character.isAlphabetic(cleanInput.charAt(lastLetterLocation))){
--lastLetterLocation;
@@ -173,11 +282,11 @@ public class Playfair{
}
}
logger.debug("Cleaned input string '{}'", cleanInput);
this.inputString = cleanInput.toString();
logger.debug("Cleaned input string '{}'", this.inputString);
}
//Returns the input string ready for encoding
private String getPreparedInputString(){
protected String getPreparedInputString(){
logger.debug("Getting input string ready for encoding");
String cleanString = inputString.toUpperCase();
@@ -188,9 +297,11 @@ public class Playfair{
return cleanString;
}
//Strips invalid characters from the keyword and creates the grid
private void setKeyword(String keyword){
protected void setKeyword(String keyword) throws InvalidKeywordException{
logger.debug("Setting keyword");
if(keyword == null){
throw new NullPointerException("Keyword cannot be null");
throw new InvalidKeywordException("Keyword cannot be null");
}
logger.debug("Original keyword {}", keyword);
@@ -209,19 +320,20 @@ public class Playfair{
//Replace all replaced characters
logger.debug("Replacing {} with {}", replaced, replacer);
keyword = keyword.replaceAll(Character.toString(replaced), Character.toString(replacer));
keyword = keyword.replaceAll(Character.toString(Character.toUpperCase(replaced)), Character.toString(Character.toUpperCase(replacer)));
//Remove all duplicate chatacters
logger.debug("Removing duplicated characters");
logger.debug("Removing duplicate characters");
StringBuilder uniqueKey = new StringBuilder();
keyword.chars().distinct().forEach(c -> uniqueKey.append((char)c));
this.keyword = uniqueKey.toString();
logger.debug("Cleaned keyword {}", this.keyword);
//Create the grid from the sanitized keyword
createGrid();
}
//Returns the location of the given character in the grid
private CharLocation findChar(char letter) throws InvalidInputException{
protected CharLocation findChar(char letter) throws InvalidInputException{
logger.debug("Finding character in grid {}", letter);
for(int row = 0;row < grid.length;++row){
@@ -238,7 +350,7 @@ public class Playfair{
throw new InvalidInputException("The character '" + letter + "' was not found in the grid");
}
//Returns the location in the grid of x and y, adjusting for out of bounds
private char getGridChar(int x, int y){
protected char getGridChar(int x, int y){
logger.debug("Getting character from grid[{}][{}]", x, y);
if(x < 0){
@@ -253,7 +365,7 @@ public class Playfair{
return letter;
}
//Adds characters that aren't letters to the output
private void addCharactersToCleanString(String cleanString){
protected void addCharactersToCleanString(String cleanString){
logger.debug("Formatting output string");
int outputCnt = 0;
@@ -262,27 +374,27 @@ public class Playfair{
logger.debug("Working character {}", inputString.charAt(inputCnt));
if(Character.isUpperCase(inputString.charAt(inputCnt))){
logger.debug("Adjusting uppercase");
logger.debug("Appending uppercase");
fullOutput.append(cleanString.charAt(outputCnt++));
}
else if(Character.isLowerCase(inputString.charAt(inputCnt))){
logger.debug("Adjusting lowercase");
logger.debug("Appending lowercase");
fullOutput.append(Character.toLowerCase(cleanString.charAt(outputCnt++)));
}
else{
logger.debug("Inserting symbol");
logger.debug("Appending symbol");
fullOutput.append(inputString.charAt(inputCnt));
}
}
logger.debug("Formatted output '{}'", fullOutput);
outputString = fullOutput.toString();
logger.debug("Formatted output '{}'", outputString);
}
//Encodes inputString using the Playfair cipher and stores the result in outputString
private String encode() throws InvalidInputException{
protected void encode() throws InvalidInputException{
logger.debug("Encoding");
StringBuilder output = new StringBuilder();
@@ -324,12 +436,9 @@ public class Playfair{
//Add other characters to the output string
addCharactersToCleanString(output.toString());
//Return the output string
return outputString;
}
//Decodes inputString using the Playfair cipher and stores the result in outputString
private String decode() throws InvalidInputException{
protected void decode() throws InvalidInputException{
logger.debug("Decoding");
StringBuilder output = new StringBuilder();
@@ -348,17 +457,17 @@ public class Playfair{
//Decode the letters
if(firstLocation.getX() == secondLocation.getX()){
logger.debug("Decoding row");
logger.debug("Row decoding");
firstLetter = getGridChar(firstLocation.getX(), firstLocation.getY() - 1);
secondLetter = getGridChar(secondLocation.getX(), secondLocation.getY() - 1);
}
else if(firstLocation.getY() == secondLocation.getY()){
logger.debug("Decoding col");
logger.debug("Column decoding");
firstLetter = getGridChar(firstLocation.getX() - 1, firstLocation.getY());
secondLetter = getGridChar(secondLocation.getX() - 1, secondLocation.getY());
}
else{
logger.debug("Decoding corners");
logger.debug("Corner decoding");
firstLetter = getGridChar(firstLocation.getX(), secondLocation.getY());
secondLetter = getGridChar(secondLocation.getX(), firstLocation.getY());
}
@@ -371,9 +480,6 @@ public class Playfair{
//Add other characters to the output string
addCharactersToCleanString(output.toString());
//Return the output string
return outputString;
}
public Playfair() throws InvalidCharacterException{
@@ -381,18 +487,18 @@ public class Playfair{
preserveCapitals = false;
preserveWhitespace = false;
preserveSymbols = false;
setReplaced('J');
setReplacer('I');
setDoubled('X');
setReplaced('j');
setReplacer('i');
setDoubled('x');
}
public Playfair(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols) throws InvalidCharacterException{
reset();
this.preserveCapitals = preserveCapitals;
this.preserveWhitespace = preserveWhitespace;
this.preserveSymbols = preserveSymbols;
setReplaced('J');
setReplacer('I');
setDoubled('X');
setReplaced('j');
setReplacer('i');
setDoubled('x');
}
public Playfair(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols, char replaced, char replacer, char doubled) throws InvalidCharacterException{
reset();
@@ -408,14 +514,16 @@ public class Playfair{
reset();
setKeyword(keyword);
setInputString(input, true);
return encode();
encode();
return outputString;
}
//Sets the keyword and inputString and decodes the message
public String decode(String keyword, String input) throws InvalidCharacterException, InvalidInputException{
reset();
setKeyword(keyword);
setInputString(input, false);
return decode();
decode();
return outputString;
}
//Makes sure all variables are empty
@@ -431,64 +539,12 @@ public class Playfair{
public char getReplaced(){
return replaced;
}
public void setReplaced(char replaced) throws InvalidCharacterException{
if(!Character.isAlphabetic(replaced)){
throw new InvalidCharacterException("The replaced character must be a letter");
}
if(replaced == replacer){
throw new InvalidCharacterException("The replaced letter cannot be the same as the replacing letter");
}
if(replaced == doubled){
throw new InvalidCharacterException("The replaced letter cannot be the same as the replacing letter");
}
this.replaced = Character.toUpperCase(replaced);
}
public char getReplacer(){
return replacer;
}
public void setReplacer(char replacer) throws InvalidCharacterException{
//Make sure the character is a letter
if(!Character.isAlphabetic(replacer)){
throw new InvalidCharacterException("The replacer must be a letter");
}
//Make sure the character isn't the same as what it is supposed to replace
if(replacer == replaced){
throw new InvalidCharacterException("The replacer cannot be the same letter as what it is replacing");
}
//Make sure the replacer isn't the same as the double letter replacer
if(replacer == doubled){
throw new InvalidCharacterException("The replacer cannot be the same as the double letter replacer");
}
this.replacer = Character.toUpperCase(replacer);
}
public char getDoubled(){
return doubled;
}
public void setDoubled(char doubled) throws InvalidCharacterException{
//Make sure the character is a letter
if(!Character.isAlphabetic(doubled)){
throw new InvalidCharacterException("The double letter replacement must be a letter");
}
//Make sure the 2 replacers are the same
if(doubled == replacer){
throw new InvalidCharacterException("The double letter replacement cannot be the same as the regular replacer");
}
//Make sure the double letter replacement isn't the same as the letter being replaced
if(doubled == replaced){
throw new InvalidCharacterException("The double letter replacement cannot be the same as the letter replaced");
}
this.doubled = Character.toUpperCase(doubled);
}
public String getKeyword(){
return keyword;
}

View File

@@ -96,7 +96,7 @@ public class TestBaconian{
assertThrows(InvalidInputException.class, () -> {
cipher.setInputStringEncode("");
}, "Input must contain at least 1 letter");
});
assertEquals("", cipher.inputString);
verify(logger, times(1)).debug("Setting input string for encoding '{}'", "");
@@ -112,7 +112,7 @@ public class TestBaconian{
assertThrows(InvalidInputException.class, () -> {
cipher.setInputStringEncode(null);
}, "Input cannot be null");
});
assertEquals("", cipher.inputString);
verify(logger, never()).debug(anyString());
@@ -159,7 +159,7 @@ public class TestBaconian{
assertThrows(InvalidCharacterException.class, () -> {
cipher.setInputStringDecode("a");
}, "All Baconian letters contain exactly 5 characters: a");
});
assertEquals("", cipher.inputString);
verify(logger, times(1)).debug("Setting input string for decoding '{}'", "a");
@@ -178,7 +178,7 @@ public class TestBaconian{
assertThrows(InvalidCharacterException.class, () -> {
cipher.setInputStringDecode("ccccc");
}, "Baconian letters contain only a's and b's: ccccc");
});
assertEquals("", cipher.inputString);
verify(logger, times(1)).debug("Setting input string for decoding '{}'", "ccccc");
@@ -197,7 +197,7 @@ public class TestBaconian{
assertThrows(InvalidInputException.class, () -> {
cipher.setInputStringDecode("");
}, "Input cannot be empty");
});
assertEquals("", cipher.inputString);
verify(logger, never()).debug("Setting input string for decoding '{}'", "");
@@ -216,7 +216,7 @@ public class TestBaconian{
assertThrows(InvalidInputException.class, () -> {
cipher.setInputStringDecode(null);
}, "Input cannot be null");
});
assertEquals("", cipher.inputString);
verify(logger, never()).debug(anyString());

View File

@@ -76,7 +76,7 @@ public class TestBaseX{
public void testSetInputStringEncode_blank(){
assertThrows(InvalidInputException.class, () -> {
cipher.setInputStringEncode("");
}, "Input must contain at least 1 letter");
});
assertEquals("", cipher.inputString);
verify(logger, times(1)).debug("Setting input string for encoding '{}'", "");
@@ -88,7 +88,7 @@ public class TestBaseX{
public void testSetInputStringEncode_null(){
assertThrows(InvalidInputException.class, () -> {
cipher.setInputStringEncode(null);
}, "Input cannot be null");
});
assertEquals("", cipher.inputString);
verify(logger, never()).debug("Setting input string for encoding '{}'", decodedString);
@@ -116,7 +116,7 @@ public class TestBaseX{
assertThrows(InvalidCharacterException.class, () -> {
cipher.setInputStringDecode("G");
}, "inputString cannot contain anything except numbers 0-15, and whitespace");
});
assertEquals("", cipher.inputString);
verify(logger, times(1)).debug("Setting input string for decoding '{}'", "G");
@@ -132,7 +132,7 @@ public class TestBaseX{
assertThrows(InvalidInputException.class, () -> {
cipher.setInputStringDecode("");
}, "Input must contain at least 1 letter");
});
assertEquals("", cipher.inputString);
verify(logger, times(1)).debug("Setting input string for decoding '{}'", "");
@@ -148,7 +148,7 @@ public class TestBaseX{
assertThrows(InvalidInputException.class, () -> {
cipher.setInputStringDecode(null);
}, "Input cannot be null");
});
assertEquals("", cipher.inputString);
verify(logger, never()).debug(eq("Setting input string for decoding '{}'"), anyString());
@@ -172,7 +172,7 @@ public class TestBaseX{
public void testSetBase_min(){
assertThrows(InvalidBaseException.class, () -> {
cipher.setBase(Character.MIN_RADIX - 1);
}, "Base cannot be less than " + Character.MIN_RADIX);
});
assertEquals(2, cipher.base);
verify(logger, never()).debug(eq("Setting base {}"), anyInt());
@@ -184,7 +184,7 @@ public class TestBaseX{
public void testSetBase_max(){
assertThrows(InvalidBaseException.class, () -> {
cipher.setBase(Character.MAX_RADIX + 1);
}, "Base cannot be larger than " + Character.MAX_RADIX);
});
assertEquals(2, cipher.base);
verify(logger, never()).debug(eq("Setting base {}"), anyInt());
@@ -227,7 +227,7 @@ public class TestBaseX{
assertThrows(InvalidCharacterException.class, () -> {
cipher.decode();
}, "The base 16 string FFF is not a valid ASCII character");
});
verify(logger, times(1)).debug("Decoding");
verify(logger, times(1)).debug("Current number {}", "FFF");

View File

@@ -208,7 +208,7 @@ public class TestBeaufort{
assertThrows(InvalidInputException.class, () -> {
cipher.setInputString("");
}, "Input must contain at least 1 letter");
});
assertEquals("", cipher.inputString);
verify(logger, times(1)).debug("Original input string '{}'", "");
@@ -224,7 +224,7 @@ public class TestBeaufort{
public void testSetInputString_null(){
assertThrows(InvalidInputException.class, () -> {
cipher.setInputString(null);
}, "Input must conatin at least 1 letter");
});
assertEquals("", cipher.inputString);
verify(logger, never()).debug(eq("Original input string '{}'"), anyString());
@@ -266,7 +266,7 @@ public class TestBeaufort{
public void testSetKeyword_blank(){
assertThrows(InvalidKeywordException.class, () -> {
cipher.setKeyword("");
}, "Keyword must contain at least 2 letters");
});
assertEquals("", cipher.keyword);
verify(logger, times(1)).debug("Original keyword '{}'", "");
@@ -281,7 +281,7 @@ public class TestBeaufort{
public void testSetKeyword_short(){
assertThrows(InvalidKeywordException.class, () -> {
cipher.setKeyword("A");
}, "Keyword must contain at least 2 letters");
});
assertEquals("A", cipher.keyword);
verify(logger, times(1)).debug("Original keyword '{}'", "A");
@@ -296,7 +296,7 @@ public class TestBeaufort{
public void testSetKeyword_null(){
assertThrows(InvalidKeywordException.class, () -> {
cipher.setKeyword(null);
}, "Keyword cannot be null");
});
assertEquals("", cipher.keyword);
verify(logger, never()).debug(eq("Original keyword '{}'"), anyString());

View File

@@ -190,7 +190,7 @@ public class TestCaesar{
assertThrows(InvalidInputException.class, () -> {
cipher.setInputString("");
}, "Input must contain at least 1 letter");
});
assertEquals("", cipher.inputString);
verify(logger, times(1)).debug("Original input string '{}'", "");
@@ -208,7 +208,7 @@ public class TestCaesar{
assertThrows(InvalidInputException.class, () -> {
cipher.setInputString(null);
}, "Input must contain at least 1 letter");
});
assertEquals("", cipher.inputString);
verify(logger, never()).debug("Original input string '{}'", "");

View File

@@ -137,7 +137,7 @@ public class TestOneTimePad{
assertThrows(InvalidKeywordException.class, () -> {
cipher.encode("keyword", decodedString);
}, "Key must be at least as long as the input");
});
assertEquals("", cipher.inputString);
assertEquals("", cipher.keyword);

View File

@@ -107,7 +107,7 @@ public class TestPorta{
public void testSetKeyword_blank(){
assertThrows(InvalidKeywordException.class, () -> {
cipher.setKeyword("");
}, "Keyword must contain at least 2 letters");
});
assertEquals("", cipher.keyword);
verify(logger, times(1)).debug("Original keyword '{}'", "");
@@ -120,7 +120,7 @@ public class TestPorta{
public void testSetKeyword_short(){
assertThrows(InvalidKeywordException.class, () -> {
cipher.setKeyword("a");
}, "Keyword must contain at least 2 letters");
});
assertEquals("A", cipher.keyword);
verify(logger, times(1)).debug("Original keyword '{}'", "a");
@@ -133,7 +133,7 @@ public class TestPorta{
public void testSetKeyword_null(){
assertThrows(InvalidKeywordException.class, () -> {
cipher.setKeyword(null);
}, "Keyword cannot be null");
});
assertEquals("", cipher.keyword);
verify(logger, never()).debug(anyString());
@@ -223,7 +223,7 @@ public class TestPorta{
assertThrows(InvalidInputException.class, () -> {
cipher.setInputString("");
}, "Input must contain at least 1 letter");
});
assertEquals("", cipher.inputString);
verify(logger, times(1)).debug("Original input string {}", "");
@@ -241,7 +241,7 @@ public class TestPorta{
assertThrows(InvalidInputException.class, () -> {
cipher.setInputString(null);
}, "Input cannot be null");
});
assertEquals("", cipher.inputString);
verify(logger, never()).debug(anyString(), anyString());

View File

@@ -172,7 +172,7 @@ public class TestSubstitution{
public void testSetKey_invalidLength(){
assertThrows(InvalidKeywordException.class, () -> {
cipher.setKeyword("AB");
}, "The key must contain all letters and can contain all numbers");
});
assertEquals("", cipher.keyword);
verify(logger, times(1)).debug("Original key '{}'", "AB");
@@ -187,7 +187,7 @@ public class TestSubstitution{
public void testSetKey_null(){
assertThrows(InvalidKeywordException.class, () -> {
cipher.setKeyword(null);
}, "Key cannot be null");
});
assertEquals("", cipher.keyword);
verify(logger, never()).debug(eq("Original key '{}'"), anyString());
@@ -270,7 +270,7 @@ public class TestSubstitution{
assertThrows(InvalidInputException.class, () -> {
cipher.setInputString("");
}, "Input must contain at least 1 letter");
});
assertEquals("", cipher.inputString);
verify(logger, times(1)).debug("Original input string '{}'", "");
@@ -288,7 +288,7 @@ public class TestSubstitution{
assertThrows(InvalidInputException.class, () -> {
cipher.setInputString(null);
}, "Input cannot be null");
});
assertEquals("", cipher.inputString);
verify(logger, never()).debug(eq("Original input string '{}'"), anyString());

View File

@@ -194,7 +194,7 @@ public class TestVigenere{
assertThrows(InvalidInputException.class, () -> {
cipher.setInputString("");
}, "Input cannot be null");
});
assertEquals("", cipher.inputString);
verify(logger, times(1)).debug("Original input string '{}'", "");
@@ -214,7 +214,7 @@ public class TestVigenere{
assertThrows(InvalidInputException.class, () -> {
cipher.setInputString(null);
}, "Input must contain at least 1 letter");
});
assertEquals("", cipher.inputString);
verify(logger, never()).debug(eq("Original input string '{}'"), anyString());
@@ -240,7 +240,7 @@ public class TestVigenere{
public void testSetKeyword_blank(){
assertThrows(InvalidKeywordException.class, () -> {
cipher.setKeyword("");
}, "Keyword must contain at least 2 letters");
});
assertEquals("", cipher.keyword);
assertEquals(new ArrayList<>(), cipher.offset);
@@ -254,7 +254,7 @@ public class TestVigenere{
public void testSetKeyword_null(){
assertThrows(InvalidKeywordException.class, () -> {
cipher.setKeyword(null);
}, "Keyword must contain at least 2 letters");
});
assertEquals("", cipher.keyword);
assertEquals(new ArrayList<>(), cipher.offset);