210 lines
7.4 KiB
Java
210 lines
7.4 KiB
Java
//CipherStreamJava/src/main/java/com/mattrixwv/CipherStreamJava/Autokey.java
|
|
//Mattrixwv
|
|
// Created: 07-25-21
|
|
//Modified: 08-11-24
|
|
/*
|
|
Copyright (C) 2024 Mattrixwv
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Lesser General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
package com.mattrixwv.cipherstream.monosubstitution;
|
|
|
|
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
import com.mattrixwv.cipherstream.exceptions.InvalidInputException;
|
|
import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException;
|
|
|
|
|
|
/**
|
|
* Implements the Autokey cipher, an extension of the Vigenère cipher that uses a keyword combined with the plaintext itself as the key.
|
|
* The Autokey cipher adds the plaintext to the end of the keyword to create a longer key, which helps to make the encryption stronger.
|
|
* This class inherits from the {@code Vigenere} class and overrides methods to handle encoding and decoding with the Autokey cipher.
|
|
*
|
|
* <p>
|
|
* The Autokey cipher is symmetric, meaning that encoding and decoding are essentially the same process, but with a different key setup for decoding.
|
|
* </p>
|
|
*/
|
|
public class Autokey extends Vigenere{
|
|
private static final Logger logger = LoggerFactory.getLogger(Autokey.class);
|
|
|
|
|
|
/**
|
|
* Sets up the keyword and input string for encoding, generating a longer key that includes the plaintext.
|
|
* This method is used internally to prepare the cipher for encoding.
|
|
*
|
|
* @param keyword the keyword used for encoding
|
|
* @param inputString the string to be encoded
|
|
* @throws InvalidKeywordException if the keyword is invalid
|
|
* @throws InvalidInputException if the input string is invalid
|
|
*/
|
|
protected void encodeSet(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{
|
|
logger.debug("Setting fields for encoding");
|
|
|
|
//Set the input
|
|
setInputString(inputString);
|
|
|
|
StringBuilder newKey = new StringBuilder();
|
|
//Remove all unneccessary elements from the key
|
|
logger.debug("Setting keyword");
|
|
setKeyword(keyword);
|
|
newKey.append(keyword);
|
|
//Remove all unneccessary elements from the input
|
|
logger.debug("Adding input to keyword");
|
|
setKeyword(inputString);
|
|
newKey.append(getKeyword());
|
|
|
|
//Make sure the key is not any longer than the input
|
|
logger.debug("Removing last letters in the keyword");
|
|
keyword = newKey.substring(0, getKeyword().length());
|
|
|
|
//Set the new keyword
|
|
setKeyword(keyword);
|
|
|
|
//Make sure to update the offset
|
|
offset.clear();
|
|
setOffset();
|
|
}
|
|
/**
|
|
* Sets up the keyword and input string for decoding. The keyword is used to decode the input string.
|
|
* This method is used internally to prepare the cipher for decoding.
|
|
*
|
|
* @param keyword the keyword used for decoding
|
|
* @param inputString the string to be decoded
|
|
* @throws InvalidKeywordException if the keyword is invalid
|
|
* @throws InvalidInputException if the input string is invalid
|
|
*/
|
|
protected void decodeSet(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{
|
|
logger.debug("Setting fields for decoding");
|
|
|
|
//Remove all unneccessary elements from the key
|
|
logger.debug("Setting keyword");
|
|
setKeyword(keyword);
|
|
|
|
//Remove all unneccessary elements from the input
|
|
logger.debug("Setting input string");
|
|
setInputString(inputString);
|
|
}
|
|
/**
|
|
* Decodes the input string using the Autokey cipher.
|
|
* This method is overridden to handle decoding with the Autokey cipher, which involves using the key and updating it with decoded characters.
|
|
*/
|
|
@Override
|
|
protected void decode(){
|
|
logger.debug("Decoding");
|
|
|
|
//Decode what the key will allow, add that to the key and continue
|
|
StringBuilder currentOutput = new StringBuilder();
|
|
StringBuilder fullOutput = new StringBuilder();
|
|
|
|
//Step through every character in the inputString and advance it the correct amount, according to offset
|
|
int offsetCnt = 0;
|
|
for(int letterCnt = 0;letterCnt < inputString.length();++letterCnt){
|
|
//If we have reached the end of the keyword add what we have to it and continue
|
|
if(offsetCnt == keyword.length()){
|
|
logger.debug("Appending partial output to keyword");
|
|
|
|
setKeyword(keyword + currentOutput.toString());
|
|
fullOutput.append(currentOutput);
|
|
currentOutput = new StringBuilder();
|
|
}
|
|
|
|
char letter = inputString.charAt(letterCnt);
|
|
logger.debug("Working character {}", letter);
|
|
|
|
if(Character.isUpperCase(letter)){
|
|
logger.debug("Appending uppercase");
|
|
|
|
letter -= offset.get((offsetCnt++) % offset.size());
|
|
if(letter < 'A'){
|
|
logger.debug("Wrapping around to Z");
|
|
|
|
letter += 26;
|
|
}
|
|
}
|
|
else if(Character.isLowerCase(letter)){
|
|
logger.debug("Appending lowercase");
|
|
|
|
letter -= offset.get((offsetCnt++) % offset.size());
|
|
if(letter < 'a'){
|
|
logger.debug("Wrapping around to z");
|
|
|
|
letter += 26;
|
|
}
|
|
}
|
|
|
|
logger.debug("Decoded letter {}", letter);
|
|
currentOutput.append(letter);
|
|
}
|
|
//Empty the last character that were decoded
|
|
fullOutput.append(currentOutput);
|
|
|
|
//Save and return the results
|
|
outputString = fullOutput.toString();
|
|
logger.debug("Saving output string '{}'", outputString);
|
|
}
|
|
|
|
|
|
//?Constructor
|
|
/**
|
|
* Constructs a new {@code Autokey} instance with default settings for preserving capitals, whitespace, and symbols.
|
|
*/
|
|
public Autokey(){
|
|
super();
|
|
}
|
|
/**
|
|
* Constructs a new {@code Autokey} instance with specified settings for preserving capitals, whitespace, and symbols.
|
|
*
|
|
* @param preserveCapitals whether to preserve capital letters in the output
|
|
* @param preserveWhitespace whether to preserve whitespace in the output
|
|
* @param preserveSymbols whether to preserve symbols in the output
|
|
*/
|
|
public Autokey(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols){
|
|
super(preserveCapitals, preserveWhitespace, preserveSymbols);
|
|
}
|
|
/**
|
|
* Encodes the input string using the Autokey cipher with the provided keyword.
|
|
*
|
|
* @param keyword the keyword used for encoding
|
|
* @param inputString the string to be encoded
|
|
* @return the encoded string
|
|
* @throws InvalidKeywordException if the keyword is invalid
|
|
* @throws InvalidInputException if the input string is invalid
|
|
*/
|
|
@Override
|
|
public String encode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{
|
|
reset();
|
|
encodeSet(keyword, inputString);
|
|
encode();
|
|
return outputString;
|
|
}
|
|
/**
|
|
* Decodes the input string using the Autokey cipher with the provided keyword.
|
|
*
|
|
* @param keyword the keyword used for decoding
|
|
* @param inputString the string to be decoded
|
|
* @return the decoded string
|
|
* @throws InvalidKeywordException if the keyword is invalid
|
|
* @throws InvalidInputException if the input string is invalid
|
|
*/
|
|
@Override
|
|
public String decode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{
|
|
reset();
|
|
decodeSet(keyword, inputString);
|
|
decode();
|
|
return outputString;
|
|
}
|
|
}
|