From 1c747de30745d7b4d1e812de49d7b0db001e0c35 Mon Sep 17 00:00:00 2001 From: Matthew Ellison Date: Thu, 27 Jan 2022 15:37:23 +0000 Subject: [PATCH] Affine.java created online with Bitbucket --- .../monoSubstitution/Affine.java | 202 ++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 src/main/java/com/mattrixwv/CipherStreamJava/monoSubstitution/Affine.java diff --git a/src/main/java/com/mattrixwv/CipherStreamJava/monoSubstitution/Affine.java b/src/main/java/com/mattrixwv/CipherStreamJava/monoSubstitution/Affine.java new file mode 100644 index 0000000..49770f8 --- /dev/null +++ b/src/main/java/com/mattrixwv/CipherStreamJava/monoSubstitution/Affine.java @@ -0,0 +1,202 @@ +//CipherStreamJava/src/main/java/com/mattrixwv/CipherStreamJava/polySubstitution/Affine.java +//Mattrixwv +// Created: 01-26-22 +//Modified: 01-26-22 +package com.mattrixwv.CipherStreamJava.monoSubstitution; + + +import com.mattrixwv.CipherStreamJava.exceptions.InvalidInputException; +import com.mattrixwv.CipherStreamJava.exceptions.InvalidKeywordException; + + +public class Affine{ + private boolean preserveCapitals; + private boolean preserveSymbols; + private boolean preserveWhitespace; + private String inputString; + private String outputString; + private int key1; //Key1 must be relatively prime to 26 + private int key2; + + private void setKey1(int key1) throws InvalidKeywordException{ + //If the key is negative change it to possitive + if(key1 < 0){ + key1 %= 26; + key1 += 26; + } + + //Make sure the key is relatively prime to 26 (The number of letters) + if(gcd(key1, 26) != 1){ + throw new InvalidKeywordException("Key 1 must be relatively prime to 26"); + } + + //Save the key + this.key1 = key1; + } + private void setKey2(int key2){ + //If the key is negative change it to possitive + if(key2 < 0){ + key2 %= 26; + key2 += 26; + } + + //Save the key + this.key2 = key2; + } + private void setInputString(String inputString) throws InvalidInputException{ + if(inputString == null){ + throw new InvalidInputException("Input must not be null"); + } + + if(!preserveCapitals){ + inputString = inputString.toLowerCase(); + } + if(!preserveWhitespace){ + inputString = inputString.replaceAll("\\s+", ""); + } + if(!preserveSymbols){ + inputString = inputString.replaceAll("[^a-zA-Z\\s]", ""); + } + + this.inputString = inputString; + + if(this.inputString.isBlank()){ + throw new InvalidInputException("Input cannot be blank"); + } + } + private String encode(){ + //Step through every character in the input and encode it if needed + StringBuilder output = new StringBuilder(); + for(char ch : inputString.toCharArray()){ + //Encode all letters + if(Character.isUpperCase(ch)){ + //Change the character to a number + int letter = ch - 65; + //Encode the number + letter = ((key1 * letter) + key2) % 26; + //Change the new number back to a character and append it to the output + char newChar = (char)(letter + 65); + output.append(newChar); + } + else if(Character.isLowerCase(ch)){ + //Change the character to a number + int letter = ch - 97; + //Encode the number + letter = ((key1 * letter) + key2) % 26; + //Change the new number back to a character and append it to the output + char newChar = (char)(letter + 97); + output.append(newChar); + } + //Pass all other characters through + else{ + output.append(ch); + } + } + + //Save and return the output + outputString = output.toString(); + return outputString; + } + private String decode(){ + //Find the multiplicative inverse of key1 + int key1I = 1; + while(((key1 * key1I) % 26) != 1){ + ++key1I; + } + + //Step through every character in the input and decode it if needed + StringBuilder output = new StringBuilder(); + for(char ch : inputString.toCharArray()){ + //Encode all letters + if(Character.isUpperCase(ch)){ + //Change the letter to a number + int letter = ch - 65; + //Encode the number + letter = (key1I * (letter - key2)) % 26; + if(letter < 0){ + letter += 26; + } + //Change the new number back to a character and append it to the output + char newChar = (char)(letter + 65); + output.append(newChar); + } + else if(Character.isLowerCase(ch)){ + //Change the letter to a number + int letter = ch - 97; + //Encode the number + letter = (key1I * (letter - key2)) % 26; + if(letter < 0){ + letter += 26; + } + //Change the new number back to a character and append it to the output + char newChar = (char)(letter + 97); + output.append(newChar); + } + //Pass all other characters through + else{ + output.append(ch); + } + } + + //Save and return the output + outputString = output.toString(); + return outputString; + } + + public Affine(){ + preserveCapitals = false; + preserveSymbols = false; + preserveWhitespace = false; + reset(); + } + public Affine(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols){ + this.preserveCapitals = preserveCapitals; + this.preserveSymbols = preserveSymbols; + this.preserveWhitespace = preserveWhitespace; + reset(); + } + public String encode(int key1, int key2, String inputString) throws InvalidKeywordException, InvalidInputException{ + setKey1(key1); + setKey2(key2); + setInputString(inputString); + return encode(); + } + public String decode(int key1, int key2, String inputString) throws InvalidKeywordException, InvalidInputException{ + setKey1(key1); + setKey2(key2); + setInputString(inputString); + return decode(); + } + + public void reset(){ + inputString = ""; + outputString = ""; + key1 = 0; + key2 = 0; + } + public String getInputString(){ + return inputString; + } + public String getOutputString(){ + return outputString; + } + public int getKey1(){ + return key1; + } + public int getKey2(){ + return key2; + } + //TODO: Change to my library's version + //This function returns the GCD of the two numbers sent to it + public static int gcd(int num1, int num2){ + while((num1 != 0) && (num2 != 0)){ + if(num1 > num2){ + num1 %= num2; + } + else{ + num2 %= num1; + } + } + return num1 | num2; + } +}