3 Commits

Author SHA1 Message Date
c10df8e5df Added Javadoc comments to the classes 2024-08-11 23:48:02 -04:00
b16956b184 Update dependencies 2024-08-11 21:43:49 -04:00
028138677b Update snapshot version 2024-08-08 22:22:45 -04:00
29 changed files with 3276 additions and 438 deletions

165
LICENSE Normal file
View File

@@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

15
pom.xml
View File

@@ -19,14 +19,14 @@
</developers> </developers>
<scm> <scm>
<connection>scm:git:git://bitbucket.org/Mattrixwv/Matrix.git</connection> <connection>scm:git:git://bitbucket.org/Mattrixwv/CipherStreamJava.git</connection>
<developerConnection>scm:git:ssh://bitbucket.org:Mattrixwv/Matrix.git</developerConnection> <developerConnection>scm:git:ssh://bitbucket.org:Mattrixwv/CipherStreamJava.git</developerConnection>
<url>https://bitbucket.org/Mattrixwv/Matrix/src</url> <url>https://bitbucket.org/Mattrixwv/CipherStreamJava/src</url>
</scm> </scm>
<groupId>com.mattrixwv</groupId> <groupId>com.mattrixwv</groupId>
<artifactId>cipher-stream-java</artifactId> <artifactId>cipher-stream-java</artifactId>
<version>1.3.5</version> <version>1.3.6</version>
<name>CipherStreamJava</name> <name>CipherStreamJava</name>
<description>A library to encrypt and decrypt simple ciphers</description> <description>A library to encrypt and decrypt simple ciphers</description>
@@ -55,19 +55,19 @@
<dependency> <dependency>
<groupId>com.mattrixwv</groupId> <groupId>com.mattrixwv</groupId>
<artifactId>myClasses</artifactId> <artifactId>myClasses</artifactId>
<version>1.3.5</version> <version>1.3.6</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.mattrixwv</groupId> <groupId>com.mattrixwv</groupId>
<artifactId>matrix</artifactId> <artifactId>matrix</artifactId>
<version>1.1.3</version> <version>1.2.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId> <artifactId>slf4j-api</artifactId>
<version>2.0.15</version> <version>2.0.16</version>
</dependency> </dependency>
<!--Test--> <!--Test-->
@@ -302,7 +302,6 @@
</goals> </goals>
<configuration> <configuration>
<keyname>${gpg.keyname}</keyname> <keyname>${gpg.keyname}</keyname>
<passphraseServerId>${gpg.keyname}</passphraseServerId>
</configuration> </configuration>
</execution> </execution>
</executions> </executions>

View File

@@ -1,7 +1,23 @@
//CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/combination/ADFGVX.java //CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/combination/ADFGVX.java
//Mattrixwv //Mattrixwv
// Created: 01-26-22 // Created: 01-26-22
//Modified: 05-04-23 //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.combination; package com.mattrixwv.cipherstream.combination;
@@ -15,23 +31,49 @@ import com.mattrixwv.cipherstream.polysubstitution.Columnar;
import com.mattrixwv.cipherstream.polysubstitution.LargePolybiusSquare; import com.mattrixwv.cipherstream.polysubstitution.LargePolybiusSquare;
/**
* Implements the ADFGVX cipher, which is a combination of a Polybius square and a columnar transposition cipher.
* This class provides methods to encode and decode strings using the ADFGVX cipher.
*
* <p>
* The cipher involves two main steps:
* </p>
* <ol>
* <li>Encoding/decoding with a Polybius square (LargePolybiusSquare)</li>
* <li>Encoding/decoding with a columnar transposition cipher (Columnar)</li>
* </ol>
*/
public class ADFGVX{ public class ADFGVX{
private static final Logger logger = LoggerFactory.getLogger(ADFGVX.class); private static final Logger logger = LoggerFactory.getLogger(ADFGVX.class);
//Fields //?Fields
protected String inputString; //The string that needs encoded/decoded /** The string that needs encoded/decoded */
protected String outputString; //The string that is output after encoding/decoding protected String inputString;
protected String squareKeyword; //The keyword used in the Polybius Square /** The string that is output after encoding/decoding */
protected String keyword; //The Keyword used in the Columnar cipher protected String outputString;
//Settings /** The keyword used in the Polybius Square */
protected boolean preserveCapitals; //Persist capitals in the output string protected String squareKeyword;
protected boolean preserveWhitespace; //Persist whitespace in the output string /** The Keyword used in the Columnar cipher */
protected boolean preserveSymbols; //Persist symbols in the output string protected String keyword;
//Internal ciphers //?Settings
protected LargePolybiusSquare largePolybiusSquare; //The first step in encoding /** Persist capitals in the output string */
protected Columnar columnar; //The second step in encoding protected boolean preserveCapitals;
/** Persist whitespace in the output string */
protected boolean preserveWhitespace;
/** Persist symbols in the output string */
protected boolean preserveSymbols;
//?Internal ciphers
/** The first step in encoding */
protected LargePolybiusSquare largePolybiusSquare;
/** The second step in encoding */
protected Columnar columnar;
//Ensures Polybius keyword constraints /**
* Sets the Polybius square keyword and validates it.
*
* @param squareKeyword the keyword for the Polybius square
* @throws InvalidKeywordException if the keyword is null
*/
protected void setSquareKeyword(String squareKeyword) throws InvalidKeywordException{ protected void setSquareKeyword(String squareKeyword) throws InvalidKeywordException{
if(squareKeyword == null){ if(squareKeyword == null){
throw new InvalidKeywordException("Square Keyword cannot be null"); throw new InvalidKeywordException("Square Keyword cannot be null");
@@ -40,7 +82,13 @@ public class ADFGVX{
logger.debug("squareKeyword '{}'", squareKeyword); logger.debug("squareKeyword '{}'", squareKeyword);
this.squareKeyword = squareKeyword; this.squareKeyword = squareKeyword;
} }
//Ensures Columnar keyword constraints
/**
* Sets the columnar cipher keyword and validates it.
*
* @param keyword the keyword for the columnar cipher
* @throws InvalidKeywordException if the keyword is null
*/
protected void setKeyword(String keyword) throws InvalidKeywordException{ protected void setKeyword(String keyword) throws InvalidKeywordException{
if(keyword == null){ if(keyword == null){
throw new InvalidKeywordException("Keyword cannot be null"); throw new InvalidKeywordException("Keyword cannot be null");
@@ -49,7 +97,14 @@ public class ADFGVX{
logger.debug("keyword '{}'", keyword); logger.debug("keyword '{}'", keyword);
this.keyword = keyword; this.keyword = keyword;
} }
//Ensures inputString constraints
/**
* Sets and sanitizes the input string according to the preservation settings.
*
* @param inputString the string to be processed
* @throws InvalidInputException if the input string is null or blank after processing
*/
protected void setInputString(String inputString) throws InvalidInputException{ protected void setInputString(String inputString) throws InvalidInputException{
if(inputString == null){ if(inputString == null){
throw new InvalidInputException("Input cannot be null"); throw new InvalidInputException("Input cannot be null");
@@ -81,7 +136,11 @@ public class ADFGVX{
throw new InvalidInputException("Input cannot be blank"); throw new InvalidInputException("Input cannot be blank");
} }
} }
//Format the output string with capitals, symbols, and numbers that are in the input string
/**
* Formats the output string to match the original input string when encoding.
*/
protected void formatOutputStringEncode(){ protected void formatOutputStringEncode(){
logger.debug("Formatting output string to match input string"); logger.debug("Formatting output string to match input string");
@@ -111,6 +170,9 @@ public class ADFGVX{
outputString = output.toString(); outputString = output.toString();
logger.debug("Saving output string '{}'", outputString); logger.debug("Saving output string '{}'", outputString);
} }
/**
* Formats the output string to match the original input string when decoding.
*/
protected void formatOutputStringDecode(){ protected void formatOutputStringDecode(){
logger.debug("Formatting output string to match input string"); logger.debug("Formatting output string to match input string");
@@ -141,7 +203,16 @@ public class ADFGVX{
outputString = output.toString(); outputString = output.toString();
logger.debug("Saving output string '{}'", outputString); logger.debug("Saving output string '{}'", outputString);
} }
//Encodes the inputString and stores the result in outputString
/**
* Encodes the input string using the Polybius square and columnar cipher.
* Stores the result in outputString.
*
* @return the encoded string
* @throws InvalidCharacterException if there are invalid characters in the ciphers
* @throws InvalidInputException if the input string is invalid
* @throws InvalidKeywordException if any of the keywords are invalid
*/
protected String encode() throws InvalidCharacterException, InvalidInputException, InvalidKeywordException{ protected String encode() throws InvalidCharacterException, InvalidInputException, InvalidKeywordException{
//Encode the input with polybius //Encode the input with polybius
logger.debug("Encoding using Polybius Square"); logger.debug("Encoding using Polybius Square");
@@ -160,7 +231,16 @@ public class ADFGVX{
return outputString; return outputString;
} }
//Decodes the inputString and stores the result in outputString
/**
* Decodes the input string using the columnar cipher and Polybius square.
* Stores the result in outputString.
*
* @return the decoded string
* @throws InvalidKeywordException if any of the keywords are invalid
* @throws InvalidCharacterException if there are invalid characters in the ciphers
* @throws InvalidInputException if the input string is invalid
*/
protected String decode() throws InvalidKeywordException, InvalidCharacterException, InvalidInputException{ protected String decode() throws InvalidKeywordException, InvalidCharacterException, InvalidInputException{
//Decode the input with columnar //Decode the input with columnar
logger.debug("Decoding using columnar"); logger.debug("Decoding using columnar");
@@ -181,13 +261,27 @@ public class ADFGVX{
} }
//Constructor //?Constructor
/**
* Constructs a new {@code ADFGVX} instance with default settings:
* capitals, whitespace, and symbols are not preserved.
*
* @throws InvalidCharacterException if there are invalid characters in the ciphers
*/
public ADFGVX() throws InvalidCharacterException{ public ADFGVX() throws InvalidCharacterException{
preserveCapitals = false; preserveCapitals = false;
preserveWhitespace = false; preserveWhitespace = false;
preserveSymbols = false; preserveSymbols = false;
reset(); reset();
} }
/**
* Constructs a new {@code ADFGVX} 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
* @throws InvalidCharacterException if there are invalid characters in the ciphers
*/
public ADFGVX(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols) throws InvalidCharacterException{ public ADFGVX(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols) throws InvalidCharacterException{
this.preserveCapitals = preserveCapitals; this.preserveCapitals = preserveCapitals;
this.preserveWhitespace = preserveWhitespace; this.preserveWhitespace = preserveWhitespace;
@@ -195,14 +289,37 @@ public class ADFGVX{
reset(); reset();
} }
//Encodes inputString using keyword and returns the result
/**
* Encodes the provided input string using the specified keywords and returns the encoded result.
*
* @param squareKeyword the keyword for the Polybius square
* @param keyword the keyword for the columnar cipher
* @param inputString the string to be encoded
* @return the encoded string
* @throws InvalidKeywordException if any of the keywords are invalid
* @throws InvalidInputException if the input string is invalid
* @throws InvalidCharacterException if the input contains invalid characters
*/
public String encode(String squareKeyword, String keyword, String inputString) throws InvalidKeywordException, InvalidInputException, InvalidCharacterException{ public String encode(String squareKeyword, String keyword, String inputString) throws InvalidKeywordException, InvalidInputException, InvalidCharacterException{
setSquareKeyword(squareKeyword); setSquareKeyword(squareKeyword);
setKeyword(keyword); setKeyword(keyword);
setInputString(inputString); setInputString(inputString);
return encode(); return encode();
} }
//Decodes inputString using keyword and returns the result
/**
* Decodes the provided input string using the specified keywords and returns the decoded result.
*
* @param squareKeyword the keyword for the Polybius square
* @param keyword the keyword for the columnar cipher
* @param inputString the string to be decoded
* @return the decoded string
* @throws InvalidKeywordException if any of the keywords are invalid
* @throws InvalidInputException if the input string is invalid
* @throws InvalidCharacterException if the input contains invalid characters
*/
public String decode(String squareKeyword, String keyword, String inputString) throws InvalidKeywordException, InvalidInputException, InvalidCharacterException{ public String decode(String squareKeyword, String keyword, String inputString) throws InvalidKeywordException, InvalidInputException, InvalidCharacterException{
setSquareKeyword(squareKeyword); setSquareKeyword(squareKeyword);
setKeyword(keyword); setKeyword(keyword);
@@ -210,20 +327,47 @@ public class ADFGVX{
return decode(); return decode();
} }
//Getters
//?Getters
/**
* Returns the current input string.
*
* @return the input string
*/
public String getInputString(){ public String getInputString(){
return inputString; return inputString;
} }
/**
* Returns the current output string.
*
* @return the output string
*/
public String getOutputString(){ public String getOutputString(){
return outputString; return outputString;
} }
/**
* Returns the current Polybius square keyword.
*
* @return the Polybius square keyword
*/
public String getSquareKeyword(){ public String getSquareKeyword(){
return squareKeyword; return squareKeyword;
} }
/**
* Returns the current columnar cipher keyword.
*
* @return the columnar cipher keyword
*/
public String getKeyword(){ public String getKeyword(){
return keyword; return keyword;
} }
//Makes sure all variables are empty
/**
* Resets all fields to their default values and re-initializes the internal ciphers.
*
* @throws InvalidCharacterException if there are invalid characters in the ciphers
*/
public void reset() throws InvalidCharacterException{ public void reset() throws InvalidCharacterException{
logger.debug("Resetting fields"); logger.debug("Resetting fields");

View File

@@ -1,7 +1,23 @@
//CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/combination/ADFGX.java //CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/combination/ADFGX.java
//Mattrixwv //Mattrixwv
// Created: 01-25-22 // Created: 01-25-22
//Modified: 05-04-23 //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.combination; package com.mattrixwv.cipherstream.combination;
@@ -15,24 +31,50 @@ import com.mattrixwv.cipherstream.polysubstitution.Columnar;
import com.mattrixwv.cipherstream.polysubstitution.PolybiusSquare; import com.mattrixwv.cipherstream.polysubstitution.PolybiusSquare;
/**
* Implements the ADFGX cipher, which is a combination of a Polybius square and a columnar transposition cipher.
* This class provides methods to encode and decode strings using the ADFGX cipher.
*
* <p>
* The cipher involves two main steps:
* </p>
* <ol>
* <li>Encoding/decoding with a Polybius square (PolybiusSquare)</li>
* <li>Encoding/decoding with a columnar transposition cipher (Columnar)</li>
* </ol>
*/
public class ADFGX{ public class ADFGX{
private static final Logger logger = LoggerFactory.getLogger(ADFGX.class); private static final Logger logger = LoggerFactory.getLogger(ADFGX.class);
//Internal fields //?Internal fields
protected String inputString; //The string that needs encoded/decoded /** The string that needs encoded/decoded */
protected String outputString; //The string that is output after encoding/decoding protected String inputString;
protected String squareKeyword; //The keyword used in the Polybius Square /** The string that is output after encoding/decoding */
protected String keyword; //The keyword used in the Columnar cipher protected String outputString;
//Settings /** The keyword used in the Polybius Square */
protected boolean preserveCapitals; //Persist capitals in the output string protected String squareKeyword;
protected boolean preserveWhitespace; //Persist whitespace in the output string /** The keyword used in the Columnar cipher */
protected boolean preserveSymbols; //Persist symbols in the output string protected String keyword;
//Internal ciphers //?Settings
protected PolybiusSquare polybiusSquare; //The first step in encoding /** Persist capitals in the output string */
protected Columnar columnar; //The second step in encoding protected boolean preserveCapitals;
/** Persist whitespace in the output string */
protected boolean preserveWhitespace;
/** Persist symbols in the output string */
protected boolean preserveSymbols;
//?Internal ciphers
/** The first step in encoding */
protected PolybiusSquare polybiusSquare;
/** The second step in encoding */
protected Columnar columnar;
//Ensures Polybius keyword constraints /**
* Sets the Polybius square keyword and validates it.
*
* @param squareKeyword the keyword for the Polybius square
* @throws InvalidKeywordException if the keyword is null
*/
protected void setSquareKeyword(String squareKeyword) throws InvalidKeywordException{ protected void setSquareKeyword(String squareKeyword) throws InvalidKeywordException{
if(squareKeyword == null){ if(squareKeyword == null){
throw new InvalidKeywordException("Square keyword cannot be null"); throw new InvalidKeywordException("Square keyword cannot be null");
@@ -41,7 +83,12 @@ public class ADFGX{
logger.debug("Square keyword '{}'", squareKeyword); logger.debug("Square keyword '{}'", squareKeyword);
this.squareKeyword = squareKeyword; this.squareKeyword = squareKeyword;
} }
//Ensures Columnar keyword constraints /**
* Sets the columnar cipher keyword and validates it.
*
* @param keyword the keyword for the columnar cipher
* @throws InvalidKeywordException if the keyword is null
*/
protected void setKeyword(String keyword) throws InvalidKeywordException{ protected void setKeyword(String keyword) throws InvalidKeywordException{
if(keyword == null){ if(keyword == null){
throw new InvalidKeywordException("Keyword cannot be null"); throw new InvalidKeywordException("Keyword cannot be null");
@@ -50,7 +97,12 @@ public class ADFGX{
logger.debug("Keyword '{}'", keyword); logger.debug("Keyword '{}'", keyword);
this.keyword = keyword; this.keyword = keyword;
} }
//Ensures inputString constraints /**
* Sets and sanitizes the input string according to the preservation settings.
*
* @param inputString the string to be processed
* @throws InvalidInputException if the input string is null or blank after processing
*/
protected void setInputString(String inputString) throws InvalidInputException{ protected void setInputString(String inputString) throws InvalidInputException{
if(inputString == null){ if(inputString == null){
throw new InvalidInputException("Input cannot be null"); throw new InvalidInputException("Input cannot be null");
@@ -80,7 +132,9 @@ public class ADFGX{
throw new InvalidInputException("Input cannot be blank"); throw new InvalidInputException("Input cannot be blank");
} }
} }
//Format the output string with capitals, symbols, and numbers that are in the input string /**
* Formats the output string to match the original input string when encoding.
*/
protected void formatOutputStringEncode(){ protected void formatOutputStringEncode(){
logger.debug("Formatting output string to match input string"); logger.debug("Formatting output string to match input string");
@@ -110,6 +164,9 @@ public class ADFGX{
outputString = output.toString(); outputString = output.toString();
logger.debug("Saving output string '{}'", outputString); logger.debug("Saving output string '{}'", outputString);
} }
/**
* Formats the output string to match the original input string when decoding.
*/
protected void formatOutputStringDecode(){ protected void formatOutputStringDecode(){
logger.debug("Formatting output string to match input string"); logger.debug("Formatting output string to match input string");
StringBuilder output = new StringBuilder(); StringBuilder output = new StringBuilder();
@@ -139,7 +196,13 @@ public class ADFGX{
outputString = output.toString(); outputString = output.toString();
logger.debug("Saving output string '{}'", outputString); logger.debug("Saving output string '{}'", outputString);
} }
//Encodes the inputString and stores the result in outputString /**
* Encodes the input string using the Polybius square and columnar cipher.
*
* @throws InvalidCharacterException if there are invalid characters in the ciphers
* @throws InvalidInputException if the input string is invalid
* @throws InvalidKeywordException if any of the keywords are invalid
*/
protected void encode() throws InvalidCharacterException, InvalidInputException, InvalidKeywordException{ protected void encode() throws InvalidCharacterException, InvalidInputException, InvalidKeywordException{
//Encode the input with polybius //Encode the input with polybius
logger.debug("Encoding using Polybius Square"); logger.debug("Encoding using Polybius Square");
@@ -158,7 +221,13 @@ public class ADFGX{
//Add whatever is needed to the output string //Add whatever is needed to the output string
formatOutputStringEncode(); formatOutputStringEncode();
} }
//Decodes the inputString and stores the result in outputString /**
* Decodes the input string using the columnar cipher and Polybius square.
*
* @throws InvalidKeywordException if any of the keywords are invalid
* @throws InvalidCharacterException if there are invalid characters in the ciphers
* @throws InvalidInputException if the input string is invalid
*/
protected void decode() throws InvalidKeywordException, InvalidCharacterException, InvalidInputException{ protected void decode() throws InvalidKeywordException, InvalidCharacterException, InvalidInputException{
//Decode the input with columnar //Decode the input with columnar
logger.debug("Decoding using columnar"); logger.debug("Decoding using columnar");
@@ -179,13 +248,27 @@ public class ADFGX{
} }
//Constructor //?Constructor
/**
* Constructs a new {@code ADFGX} instance with default settings:
* capitals, whitespace, and symbols are not preserved.
*
* @throws InvalidCharacterException if there are invalid characters in the ciphers
*/
public ADFGX() throws InvalidCharacterException{ public ADFGX() throws InvalidCharacterException{
preserveCapitals = false; preserveCapitals = false;
preserveWhitespace = false; preserveWhitespace = false;
preserveSymbols = false; preserveSymbols = false;
reset(); reset();
} }
/**
* Constructs a new {@code ADFGX} 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
* @throws InvalidCharacterException if there are invalid characters in the ciphers
*/
public ADFGX(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols) throws InvalidCharacterException{ public ADFGX(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols) throws InvalidCharacterException{
this.preserveCapitals = preserveCapitals; this.preserveCapitals = preserveCapitals;
this.preserveWhitespace = preserveWhitespace; this.preserveWhitespace = preserveWhitespace;
@@ -193,7 +276,17 @@ public class ADFGX{
reset(); reset();
} }
//Encodes inputString using keyword and returns the result /**
* Encodes the provided input string using the specified keywords and returns the encoded result.
*
* @param squareKeyword the keyword for the Polybius square
* @param keyword the keyword for the columnar cipher
* @param inputString the string to be encoded
* @return the encoded string
* @throws InvalidKeywordException if any of the keywords are invalid
* @throws InvalidInputException if the input string is invalid
* @throws InvalidCharacterException if the input contains invalid characters
*/
public String encode(String squareKeyword, String keyword, String inputString) throws InvalidKeywordException, InvalidInputException, InvalidCharacterException{ public String encode(String squareKeyword, String keyword, String inputString) throws InvalidKeywordException, InvalidInputException, InvalidCharacterException{
setSquareKeyword(squareKeyword); setSquareKeyword(squareKeyword);
setKeyword(keyword); setKeyword(keyword);
@@ -201,7 +294,17 @@ public class ADFGX{
encode(); encode();
return outputString; return outputString;
} }
//Decodes inputString using keyword and returns the result /**
* Decodes the provided input string using the specified keywords and returns the decoded result.
*
* @param squareKeyword the keyword for the Polybius square
* @param keyword the keyword for the columnar cipher
* @param inputString the string to be decoded
* @return the decoded string
* @throws InvalidKeywordException if any of the keywords are invalid
* @throws InvalidInputException if the input string is invalid
* @throws InvalidCharacterException if the input contains invalid characters
*/
public String decode(String squareKeyword, String keyword, String inputString) throws InvalidKeywordException, InvalidInputException, InvalidCharacterException{ public String decode(String squareKeyword, String keyword, String inputString) throws InvalidKeywordException, InvalidInputException, InvalidCharacterException{
setSquareKeyword(squareKeyword); setSquareKeyword(squareKeyword);
setKeyword(keyword); setKeyword(keyword);
@@ -210,20 +313,44 @@ public class ADFGX{
return outputString; return outputString;
} }
//Getters //?Getters
/**
* Returns the current input string.
*
* @return the input string
*/
public String getInputString(){ public String getInputString(){
return inputString; return inputString;
} }
/**
* Returns the current output string.
*
* @return the output string
*/
public String getOutputString(){ public String getOutputString(){
return outputString; return outputString;
} }
/**
* Returns the current Polybius square keyword.
*
* @return the Polybius square keyword
*/
public String getSquareKeyword(){ public String getSquareKeyword(){
return squareKeyword; return squareKeyword;
} }
/**
* Returns the current columnar cipher keyword.
*
* @return the columnar cipher keyword
*/
public String getKeyword(){ public String getKeyword(){
return keyword; return keyword;
} }
//Makes sure all variables are empty /**
* Resets all fields to their default values and reinitializes the internal ciphers.
*
* @throws InvalidCharacterException if there are invalid characters in the ciphers
*/
public void reset() throws InvalidCharacterException{ public void reset() throws InvalidCharacterException{
logger.debug("Resetting fields"); logger.debug("Resetting fields");

View File

@@ -1,20 +1,58 @@
//CipherStreamJava/src/main/java/com/mattrixwv/CipherStreamJava/Exceptions/InvalidBaseException.java //CipherStreamJava/src/main/java/com/mattrixwv/CipherStreamJava/Exceptions/InvalidBaseException.java
//Mattrixwv //Mattrixwv
// Created: 01-09-22 // Created: 01-09-22
//Modified: 01-09-22 //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.exceptions; package com.mattrixwv.cipherstream.exceptions;
/**
* Thrown to indicate that a problem has occurred related to the base or group size.
*/
public class InvalidBaseException extends RuntimeException{ public class InvalidBaseException extends RuntimeException{
/**
* Constructs a new {@code InvalidBaseException} with {@code null} as its detail message.
*/
public InvalidBaseException(){ public InvalidBaseException(){
super(); super();
} }
/**
* Constructs a new {@code InvalidBaseException} with the specified detail message.
*
* @param message the detail message, which is saved for later retrieval by the {@link #getMessage()} method
*/
public InvalidBaseException(String message){ public InvalidBaseException(String message){
super(message); super(message);
} }
/**
* Constructs a new {@code InvalidBaseException} with the specified cause.
*
* @param error the cause, which is saved for later retrieval by the {@link #getCause()} method
*/
public InvalidBaseException(Throwable error){ public InvalidBaseException(Throwable error){
super(error); super(error);
} }
/**
* Constructs a new {@code InvalidBaseException} with the specified detail message and cause.
*
* @param message the detail message, which is saved for later retrieval by the {@link #getMessage()} method
* @param error the cause, which is saved for later retrieval by the {@link #getCause()} method
*/
public InvalidBaseException(String message, Throwable error){ public InvalidBaseException(String message, Throwable error){
super(message, error); super(message, error);
} }

View File

@@ -1,20 +1,58 @@
//CipherStreamJava/src/main/java/com/mattrixwv/CipherStreamJava/Exceptions/InvalidCharacterException.java //CipherStreamJava/src/main/java/com/mattrixwv/CipherStreamJava/Exceptions/InvalidCharacterException.java
//Mattrixwv //Mattrixwv
// Created: 01-04-22 // Created: 01-04-22
//Modified: 01-04-22 //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.exceptions; package com.mattrixwv.cipherstream.exceptions;
/**
* Thrown to indicate that a problem has occurred related to an invalid character.
*/
public class InvalidCharacterException extends RuntimeException{ public class InvalidCharacterException extends RuntimeException{
/**
* Constructs a new {@code InvalidCharacterException} with {@code null} as its detail message.
*/
public InvalidCharacterException(){ public InvalidCharacterException(){
super(); super();
} }
/**
* Constructs a new {@code InvalidCharacterException} with the specified detail message.
*
* @param message the detail message, which is saved for later retrieval by the {@link #getMessage()} method
*/
public InvalidCharacterException(String message){ public InvalidCharacterException(String message){
super(message); super(message);
} }
/**
* Constructs a new {@code InvalidCharacterException} with the specified cause.
*
* @param error the cause, which is saved for later retrieval by the {@link #getCause()} method
*/
public InvalidCharacterException(Throwable error){ public InvalidCharacterException(Throwable error){
super(error); super(error);
} }
/**
* Constructs a new {@code InvalidCharacterException} with the specified detail message and cause.
*
* @param message the detail message, which is saved for later retrieval by the {@link #getMessage()} method
* @param error the cause, which is saved for later retrieval by the {@link #getCause()} method
*/
public InvalidCharacterException(String message, Throwable error){ public InvalidCharacterException(String message, Throwable error){
super(message, error); super(message, error);
} }

View File

@@ -1,20 +1,58 @@
//CipherStreamJava/src/main/java/com/mattrixwv/CipherStreamJava/Exceptions/InvalidInputException.java //CipherStreamJava/src/main/java/com/mattrixwv/CipherStreamJava/Exceptions/InvalidInputException.java
//Mattrixwv //Mattrixwv
// Created: 01-09-22 // Created: 01-09-22
//Modified: 01-09-22 //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.exceptions; package com.mattrixwv.cipherstream.exceptions;
/**
* Thrown to indicate that a problem has occurred related to invalid input.
*/
public class InvalidInputException extends RuntimeException{ public class InvalidInputException extends RuntimeException{
/**
* Constructs a new {@code InvalidInputException} with {@code null} as its detail message.
*/
public InvalidInputException(){ public InvalidInputException(){
super(); super();
} }
/**
* Constructs a new {@code InvalidInputException} with the specified detail message.
*
* @param message the detail message, which is saved for later retrieval by the {@link #getMessage()} method
*/
public InvalidInputException(String message){ public InvalidInputException(String message){
super(message); super(message);
} }
/**
* Constructs a new {@code InvalidInputException} with the specified cause.
*
* @param error the cause, which is saved for later retrieval by the {@link #getCause()} method
*/
public InvalidInputException(Throwable error){ public InvalidInputException(Throwable error){
super(error); super(error);
} }
/**
* Constructs a new {@code InvalidInputException} with the specified detail message and cause.
*
* @param message the detail message, which is saved for later retrieval by the {@link #getMessage()} method
* @param error the cause, which is saved for later retrieval by the {@link #getCause()} method
*/
public InvalidInputException(String message, Throwable error){ public InvalidInputException(String message, Throwable error){
super(message, error); super(message, error);
} }

View File

@@ -1,20 +1,58 @@
//CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/exceptions/InvalidKeyException.java //CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/exceptions/InvalidKeyException.java
//Matrixwv //Matrixwv
// Created: 07-09-22 // Created: 07-09-22
//Modified: 07-09-22 //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.exceptions; package com.mattrixwv.cipherstream.exceptions;
/**
* Thrown to indicate that a problem has occurred related to an invalid key.
*/
public class InvalidKeyException extends RuntimeException{ public class InvalidKeyException extends RuntimeException{
/**
* Constructs a new {@code InvalidKeyException} with {@code null} as its detail message.
*/
public InvalidKeyException(){ public InvalidKeyException(){
super(); super();
} }
/**
* Constructs a new {@code InvalidKeyException} with the specified detail message.
*
* @param message the detail message, which is saved for later retrieval by the {@link #getMessage()} method
*/
public InvalidKeyException(String message){ public InvalidKeyException(String message){
super(message); super(message);
} }
/**
* Constructs a new {@code InvalidKeyException} with the specified cause.
*
* @param error the cause, which is saved for later retrieval by the {@link #getCause()} method
*/
public InvalidKeyException(Throwable error){ public InvalidKeyException(Throwable error){
super(error); super(error);
} }
/**
* Constructs a new {@code InvalidKeyException} with the specified detail message and cause.
*
* @param message the detail message, which is saved for later retrieval by the {@link #getMessage()} method
* @param error the cause, which is saved for later retrieval by the {@link #getCause()} method
*/
public InvalidKeyException(String message, Throwable error){ public InvalidKeyException(String message, Throwable error){
super(message, error); super(message, error);
} }

View File

@@ -1,20 +1,58 @@
//CipherStreamJava/src/main/java/com/mattrixwv/CipherStreamJava/Exceptions/InvalidKeywordException.java //CipherStreamJava/src/main/java/com/mattrixwv/CipherStreamJava/Exceptions/InvalidKeywordException.java
//Mattrixwv //Mattrixwv
// Created: 01-09-22 // Created: 01-09-22
//Modified: 01-09-22 //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.exceptions; package com.mattrixwv.cipherstream.exceptions;
/**
* Thrown to indicate that a problem has occurred related to an invalid keyword.
*/
public class InvalidKeywordException extends RuntimeException{ public class InvalidKeywordException extends RuntimeException{
/**
* Constructs a new {@code InvalidKeywordException} with {@code null} as its detail message.
*/
public InvalidKeywordException(){ public InvalidKeywordException(){
super(); super();
} }
/**
* Constructs a new {@code InvalidKeywordException} with the specified detail message.
*
* @param message the detail message, which is saved for later retrieval by the {@link #getMessage()} method
*/
public InvalidKeywordException(String message){ public InvalidKeywordException(String message){
super(message); super(message);
} }
/**
* Constructs a new {@code InvalidKeywordException} with the specified cause.
*
* @param error the cause, which is saved for later retrieval by the {@link #getCause()} method
*/
public InvalidKeywordException(Throwable error){ public InvalidKeywordException(Throwable error){
super(error); super(error);
} }
/**
* Constructs a new {@code InvalidKeywordException} with the specified detail message and cause.
*
* @param message the detail message, which is saved for later retrieval by the {@link #getMessage()} method
* @param error the cause, which is saved for later retrieval by the {@link #getCause()} method
*/
public InvalidKeywordException(String message, Throwable error){ public InvalidKeywordException(String message, Throwable error){
super(message, error); super(message, error);
} }

View File

@@ -1,7 +1,23 @@
//CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Affine.java //CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Affine.java
//Mattrixwv //Mattrixwv
// Created: 01-26-22 // Created: 01-26-22
//Modified: 05-04-23 //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; package com.mattrixwv.cipherstream.monosubstitution;
@@ -13,20 +29,44 @@ import com.mattrixwv.cipherstream.exceptions.InvalidInputException;
import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException; import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException;
/**
* Implements the Affine cipher, which is a monoalphabetic substitution cipher based on linear algebra.
* This class provides methods to encode and decode strings using the Affine cipher with a specified key.
*
* <p>
* The Affine cipher uses two keys:
* </p>
* <ul>
* <li><strong>Key1</strong>: The multiplicative key (must be relatively prime to 26)</li>
* <li><strong>Key2</strong>: The additive key</li>
* </ul>
*/
public class Affine{ public class Affine{
private static final Logger logger = LoggerFactory.getLogger(Affine.class); private static final Logger logger = LoggerFactory.getLogger(Affine.class);
//Fields //?Fields
protected String inputString; //The string that needs encoded/decoded /** The string that needs encoded/decoded */
protected String outputString; //The string that is output after encoding/decoding protected String inputString;
protected int key1; //The multiplicative key. Key1 must be relatively prime to 26 /** The string that is output after encoding/decoding */
protected int key2; //The additive key protected String outputString;
//Settings /** The multiplicative key. Key1 must be relatively prime to 26 */
protected boolean preserveCapitals; //Persist capitals in the output string protected int key1;
protected boolean preserveSymbols; //Persist symbols in the output string /** The additive key */
protected boolean preserveWhitespace; //Persist whitespace in the output string protected int key2;
//?Settings
/** Persist capitals in the output string */
protected boolean preserveCapitals;
/** Persist symbols in the output string */
protected boolean preserveSymbols;
/** Persist whitespace in the output string */
protected boolean preserveWhitespace;
//Ensures key1 constraints /**
* Sets the multiplicative key and validates it.
*
* @param key1 the multiplicative key
* @throws InvalidKeywordException if the key1 is not relatively prime to 26
*/
protected void setKey1(int key1) throws InvalidKeywordException{ protected void setKey1(int key1) throws InvalidKeywordException{
logger.debug("Setting key1 {}", key1); logger.debug("Setting key1 {}", key1);
@@ -48,7 +88,11 @@ public class Affine{
logger.debug("Cleaned key1 {}", key1); logger.debug("Cleaned key1 {}", key1);
} }
//Ensures key2 constraints /**
* Sets the additive key.
*
* @param key2 the additive key
*/
protected void setKey2(int key2){ protected void setKey2(int key2){
logger.debug("Setting key2 {}", key2); logger.debug("Setting key2 {}", key2);
@@ -65,7 +109,12 @@ public class Affine{
logger.debug("Cleaned key2 {}", key2); logger.debug("Cleaned key2 {}", key2);
} }
//Ensures inputString constraints /**
* Sets and sanitizes the input string according to the preservation settings.
*
* @param inputString the string to be processed
* @throws InvalidInputException if the input string is null or blank after processing
*/
protected void setInputString(String inputString) throws InvalidInputException{ protected void setInputString(String inputString) throws InvalidInputException{
if(inputString == null){ if(inputString == null){
throw new InvalidInputException("Input must not be null"); throw new InvalidInputException("Input must not be null");
@@ -97,7 +146,9 @@ public class Affine{
throw new InvalidInputException("Input cannot be blank"); throw new InvalidInputException("Input cannot be blank");
} }
} }
//Encodes the inputString and stores the result in outputString /**
* Encodes the input string using the affine cipher.
*/
protected void encode(){ protected void encode(){
logger.debug("Encoding"); logger.debug("Encoding");
@@ -138,7 +189,9 @@ public class Affine{
outputString = output.toString(); outputString = output.toString();
logger.debug("Saving output string '{}'", outputString); logger.debug("Saving output string '{}'", outputString);
} }
//Decodes the inputString and stores the result in outputString /**
* Decodes the input string using the affine cipher.
*/
protected void decode(){ protected void decode(){
logger.debug("Decoding"); logger.debug("Decoding");
@@ -194,13 +247,24 @@ public class Affine{
} }
//Constructor //?Constructor
/**
* Constructs a new {@code Affine} instance with default settings:
* capitals, symbols, and whitespace are not preserved.
*/
public Affine(){ public Affine(){
preserveCapitals = false; preserveCapitals = false;
preserveSymbols = false; preserveSymbols = false;
preserveWhitespace = false; preserveWhitespace = false;
reset(); reset();
} }
/**
* Constructs a new {@code Affine} instance with specified settings for preserving capitals, symbols, and whitespace.
*
* @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 Affine(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols){ public Affine(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols){
this.preserveCapitals = preserveCapitals; this.preserveCapitals = preserveCapitals;
this.preserveSymbols = preserveSymbols; this.preserveSymbols = preserveSymbols;
@@ -208,7 +272,16 @@ public class Affine{
reset(); reset();
} }
//Encodes inputString using key1 and key2 and returns the result /**
* Encodes the provided input string using the specified keys and returns the encoded result.
*
* @param key1 the multiplicative key (must be relatively prime to 26)
* @param key2 the additive key
* @param inputString the string to be encoded
* @return the encoded string
* @throws InvalidKeywordException if key1 is not relatively prime to 26
* @throws InvalidInputException if the input string is invalid
*/
public String encode(int key1, int key2, String inputString) throws InvalidKeywordException, InvalidInputException{ public String encode(int key1, int key2, String inputString) throws InvalidKeywordException, InvalidInputException{
setKey1(key1); setKey1(key1);
setKey2(key2); setKey2(key2);
@@ -216,7 +289,16 @@ public class Affine{
encode(); encode();
return outputString; return outputString;
} }
//Decodes inputString using key1 and key2 and returns the result /**
* Decodes the provided input string using the specified keys and returns the decoded result.
*
* @param key1 the multiplicative key (must be relatively prime to 26)
* @param key2 the additive key
* @param inputString the string to be decoded
* @return the decoded string
* @throws InvalidKeywordException if key1 is not relatively prime to 26
* @throws InvalidInputException if the input string is invalid
*/
public String decode(int key1, int key2, String inputString) throws InvalidKeywordException, InvalidInputException{ public String decode(int key1, int key2, String inputString) throws InvalidKeywordException, InvalidInputException{
setKey1(key1); setKey1(key1);
setKey2(key2); setKey2(key2);
@@ -225,20 +307,42 @@ public class Affine{
return outputString; return outputString;
} }
//Getters //?Getters
/**
* Returns the current input string.
*
* @return the input string
*/
public String getInputString(){ public String getInputString(){
return inputString; return inputString;
} }
/**
* Returns the current output string.
*
* @return the output string
*/
public String getOutputString(){ public String getOutputString(){
return outputString; return outputString;
} }
/**
* Returns the current multiplicative key.
*
* @return the multiplicative key
*/
public int getKey1(){ public int getKey1(){
return key1; return key1;
} }
/**
* Returns the current additive key.
*
* @return the additive key
*/
public int getKey2(){ public int getKey2(){
return key2; return key2;
} }
//Makes sure all of the variables are empty /**
* Resets all fields to their default values.
*/
public void reset(){ public void reset(){
logger.debug("Resetting fields"); logger.debug("Resetting fields");

View File

@@ -1,7 +1,23 @@
//CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/monosubstitution/Atbash.java //CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/monosubstitution/Atbash.java
//Mattrixwv //Mattrixwv
// Created: 07-25-21 // Created: 07-25-21
//Modified: 05-04-23 //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; package com.mattrixwv.cipherstream.monosubstitution;
@@ -11,18 +27,34 @@ import org.slf4j.LoggerFactory;
import com.mattrixwv.cipherstream.exceptions.InvalidInputException; import com.mattrixwv.cipherstream.exceptions.InvalidInputException;
/**
* Implements the Atbash cipher, a simple substitution cipher where each letter of the alphabet is mapped to its reverse.
* For example, 'A' is mapped to 'Z', 'B' to 'Y', and so on.
* This class provides methods to encode and decode strings using the Atbash cipher.
*
* <p>
* The Atbash cipher is symmetric, meaning that encoding and decoding are the same operation.
* </p>
*/
public class Atbash{ public class Atbash{
private static final Logger logger = LoggerFactory.getLogger(Atbash.class); private static final Logger logger = LoggerFactory.getLogger(Atbash.class);
//Fields //?Fields
protected String inputString; //Holds the string that needs encoded or decoded /** Holds the string that needs encoded or decoded */
protected String outputString; //The encoded/decoded string protected String inputString;
//Settings /** The encoded/decoded string */
protected boolean preserveCapitals; //Persist capitals in the output string protected String outputString;
protected boolean preserveWhitespace; //Persist whitespace in the output string //?Settings
protected boolean preserveSymbols; //Persist symbols in the output string /** Persist capitals in the output string */
protected boolean preserveCapitals;
/** Persist whitespace in the output string */
protected boolean preserveWhitespace;
/** Persist symbols in the output string */
protected boolean preserveSymbols;
//Encodes inputString and stores in outputString /**
* Encodes the input string using the Atbash cipher.
*/
protected void encode(){ protected void encode(){
logger.debug("Encoding"); logger.debug("Encoding");
StringBuilder output = new StringBuilder(); StringBuilder output = new StringBuilder();
@@ -57,7 +89,12 @@ public class Atbash{
outputString = output.toString(); outputString = output.toString();
logger.debug("Saving output string '{}'", outputString); logger.debug("Saving output string '{}'", outputString);
} }
//Removes all invalid characters and sets inputString /**
* Sets and sanitizes the input string according to the preservation settings.
*
* @param inputString the string to be processed
* @throws InvalidInputException if the input string is null or blank after processing
*/
protected void setInputString(String inputString) throws InvalidInputException{ protected void setInputString(String inputString) throws InvalidInputException{
if(inputString == null){ if(inputString == null){
throw new InvalidInputException("Input cannot be null"); throw new InvalidInputException("Input cannot be null");
@@ -95,13 +132,24 @@ public class Atbash{
} }
//Constructor //?Constructor
/**
* Constructs a new {@code Atbash} instance with default settings:
* capitals, symbols, and whitespace are not preserved.
*/
public Atbash(){ public Atbash(){
reset(); reset();
preserveCapitals = false; preserveCapitals = false;
preserveWhitespace = false; preserveWhitespace = false;
preserveSymbols = false; preserveSymbols = false;
} }
/**
* Constructs a new {@code Atbash} 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 Atbash(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols){ public Atbash(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols){
reset(); reset();
this.preserveCapitals = preserveCapitals; this.preserveCapitals = preserveCapitals;
@@ -109,7 +157,13 @@ public class Atbash{
this.preserveSymbols = preserveSymbols; this.preserveSymbols = preserveSymbols;
} }
//Encodes inputString and returns the result /**
* Encodes the provided input string using the Atbash cipher and returns the encoded result.
*
* @param inputString the string to be encoded
* @return the encoded string
* @throws InvalidInputException if the input string is invalid
*/
public String encode(String inputString) throws InvalidInputException{ public String encode(String inputString) throws InvalidInputException{
//Make sure everything is empty before you begin //Make sure everything is empty before you begin
reset(); reset();
@@ -117,19 +171,38 @@ public class Atbash{
encode(); encode();
return outputString; return outputString;
} }
//Decodes inputString and returns the result /**
* Decodes the provided input string using the Atbash cipher and returns the decoded result.
* Since the Atbash cipher is symmetric, this method performs the same operation as encoding.
*
* @param inputString the string to be decoded
* @return the decoded string
* @throws InvalidInputException if the input string is invalid
*/
public String decode(String inputString) throws InvalidInputException{ public String decode(String inputString) throws InvalidInputException{
return encode(inputString); return encode(inputString);
} }
//Getters //?Getters
/**
* Returns the current input string.
*
* @return the input string
*/
public String getInputString(){ public String getInputString(){
return inputString; return inputString;
} }
/**
* Returns the current output string.
*
* @return the output string
*/
public String getOutputString(){ public String getOutputString(){
return outputString; return outputString;
} }
//Makes sure all variables are empty /**
* Resets all fields to their default values.
*/
public void reset(){ public void reset(){
logger.debug("Resetting fields"); logger.debug("Resetting fields");

View File

@@ -1,7 +1,23 @@
//CipherStreamJava/src/main/java/com/mattrixwv/CipherStreamJava/Autokey.java //CipherStreamJava/src/main/java/com/mattrixwv/CipherStreamJava/Autokey.java
//Mattrixwv //Mattrixwv
// Created: 07-25-21 // Created: 07-25-21
//Modified: 05-04-23 //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; package com.mattrixwv.cipherstream.monosubstitution;
@@ -12,11 +28,28 @@ import com.mattrixwv.cipherstream.exceptions.InvalidInputException;
import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException; 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{ public class Autokey extends Vigenere{
private static final Logger logger = LoggerFactory.getLogger(Autokey.class); private static final Logger logger = LoggerFactory.getLogger(Autokey.class);
//Special rules for setting the strings for encoding /**
* 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{ protected void encodeSet(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{
logger.debug("Setting fields for encoding"); logger.debug("Setting fields for encoding");
@@ -44,7 +77,15 @@ public class Autokey extends Vigenere{
offset.clear(); offset.clear();
setOffset(); setOffset();
} }
//Setting the strings for decoding /**
* 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{ protected void decodeSet(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{
logger.debug("Setting fields for decoding"); logger.debug("Setting fields for decoding");
@@ -56,7 +97,10 @@ public class Autokey extends Vigenere{
logger.debug("Setting input string"); logger.debug("Setting input string");
setInputString(inputString); setInputString(inputString);
} }
//Decodes the 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 @Override
protected void decode(){ protected void decode(){
logger.debug("Decoding"); logger.debug("Decoding");
@@ -113,14 +157,32 @@ public class Autokey extends Vigenere{
} }
//Constructor //?Constructor
/**
* Constructs a new {@code Autokey} instance with default settings for preserving capitals, whitespace, and symbols.
*/
public Autokey(){ public Autokey(){
super(); 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){ public Autokey(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols){
super(preserveCapitals, preserveWhitespace, preserveSymbols); super(preserveCapitals, preserveWhitespace, preserveSymbols);
} }
//Encodes inputString using the Autokey cipher /**
* 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 @Override
public String encode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{ public String encode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{
reset(); reset();
@@ -128,7 +190,15 @@ public class Autokey extends Vigenere{
encode(); encode();
return outputString; return outputString;
} }
//Decodes inputString using the Autokey cipher /**
* 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 @Override
public String decode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{ public String decode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{
reset(); reset();

View File

@@ -1,7 +1,23 @@
//CipherStreamJava/src/test/java/com/mattrixwv/CipherStreamJava/Baconian.java //CipherStreamJava/src/test/java/com/mattrixwv/CipherStreamJava/Baconian.java
//Mattrixwv //Mattrixwv
// Created: 01-12-22 // Created: 01-12-22
//Modified: 04-19-24 //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; package com.mattrixwv.cipherstream.monosubstitution;
@@ -16,20 +32,38 @@ import com.mattrixwv.cipherstream.exceptions.InvalidCharacterException;
import com.mattrixwv.cipherstream.exceptions.InvalidInputException; import com.mattrixwv.cipherstream.exceptions.InvalidInputException;
/**
* Implements the Baconian cipher, a method of steganography where each letter of the alphabet is represented by a unique sequence of five characters ('a' or 'b').
* The Baconian cipher is a simple substitution cipher that can encode and decode text based on these sequences.
*
* <p>
* The cipher uses a predefined list of five-character strings to represent each letter of the alphabet (A-Z). The input string is converted to these sequences for encoding,
* and sequences are converted back to letters for decoding.
* </p>
*/
public class Baconian{ public class Baconian{
private static final Logger logger = LoggerFactory.getLogger(Baconian.class); private static final Logger logger = LoggerFactory.getLogger(Baconian.class);
//Conversions //?Conversions
/** Predefined code for Baconian cipher (5-character strings for A-Z) */
protected static final ArrayList<String> code = new ArrayList<>(Arrays.asList( protected static final ArrayList<String> code = new ArrayList<>(Arrays.asList(
"aaaaa", "aaaab", "aaaba", "aaabb", "aabaa", "aabab", "aabba","aabbb", "abaaa", "abaaa", "abaab", "ababa", "ababb", //A-M "aaaaa", "aaaab", "aaaba", "aaabb", "aabaa", "aabab", "aabba","aabbb", "abaaa", "abaaa", "abaab", "ababa", "ababb", //A-M
"abbaa", "abbab", "abbba", "abbbb", "baaaa", "baaab", "baaba", "baabb", "baabb", "babaa", "babab", "babba", "babbb" //N-Z "abbaa", "abbab", "abbba", "abbbb", "baaaa", "baaab", "baaba", "baabb", "baabb", "babaa", "babab", "babba", "babbb" //N-Z
)); ));
protected String inputString; //The string that needs encoded/decoded /** The string that needs encoded/decoded */
protected String outputString; //The encoded/decoded string protected String inputString;
protected boolean preserveCapitals; //Persist capitals in the output string /** The encoded/decoded string */
protected String outputString;
/** Persist capitals in the output string */
protected boolean preserveCapitals;
//Sets the input string /**
* Sets the input string for encoding, removing whitespace and symbols, and handling capitalization based on the flag.
*
* @param inputString the string to be encoded
* @throws InvalidInputException if the input string is null, empty, or invalid
*/
protected void setInputStringEncode(String inputString) throws InvalidInputException{ protected void setInputStringEncode(String inputString) throws InvalidInputException{
if(inputString == null){ if(inputString == null){
throw new InvalidInputException("Input cannot be null"); throw new InvalidInputException("Input cannot be null");
@@ -53,6 +87,13 @@ public class Baconian{
throw new InvalidInputException("Input must contain at least 1 letter"); throw new InvalidInputException("Input must contain at least 1 letter");
} }
} }
/**
* Sets the input string for decoding, ensuring it contains only valid Baconian characters (a's and b's) with a length of 5.
*
* @param inputString the string to be decoded
* @throws InvalidCharacterException if the input string contains invalid Baconian characters
* @throws InvalidInputException if the input string is null or empty
*/
protected void setInputStringDecode(String inputString) throws InvalidCharacterException, InvalidInputException{ protected void setInputStringDecode(String inputString) throws InvalidCharacterException, InvalidInputException{
if(inputString == null){ if(inputString == null){
throw new InvalidInputException("Input cannot be null"); throw new InvalidInputException("Input cannot be null");
@@ -91,7 +132,10 @@ public class Baconian{
logger.debug("Cleaned input string '{}'", inputString); logger.debug("Cleaned input string '{}'", inputString);
} }
//Encodes the inputString and stores the result in outputString /**
* Encodes the input string using the Baconian cipher.
* Each character in the input string is converted to its corresponding Baconian sequence.
*/
protected void encode(){ protected void encode(){
logger.debug("Encoding"); logger.debug("Encoding");
StringJoiner output = new StringJoiner(" "); StringJoiner output = new StringJoiner(" ");
@@ -121,7 +165,10 @@ public class Baconian{
outputString = output.toString(); outputString = output.toString();
logger.debug("Saving output string '{}'", outputString); logger.debug("Saving output string '{}'", outputString);
} }
//Decodes the inputString and stores the result in outputString /**
* Decodes the input string using the Baconian cipher.
* Each Baconian sequence in the input string is converted back to its corresponding character.
*/
protected void decode(){ protected void decode(){
logger.debug("Decoding"); logger.debug("Decoding");
@@ -157,24 +204,45 @@ public class Baconian{
logger.debug("Saving output string '{}'", outputString); logger.debug("Saving output string '{}'", outputString);
} }
//Constructor //?Constructor
/**
* Constructs a new {@code Baconian} instance with default settings for preserving capitals.
*/
public Baconian(){ public Baconian(){
reset(); reset();
preserveCapitals = false; preserveCapitals = false;
} }
/**
* Constructs a new {@code Baconian} instance with a specified setting for preserving capitals.
*
* @param preserveCapitals whether to preserve capital letters in the output
*/
public Baconian(boolean preserveCapitals){ public Baconian(boolean preserveCapitals){
reset(); reset();
this.preserveCapitals = preserveCapitals; this.preserveCapitals = preserveCapitals;
} }
//Sets the inputString and encodes the message /**
* Encodes the input string using the Baconian cipher.
*
* @param inputString the string to be encoded
* @return the encoded string
* @throws InvalidInputException if the input string is invalid
*/
public String encode(String inputString) throws InvalidInputException{ public String encode(String inputString) throws InvalidInputException{
reset(); reset();
setInputStringEncode(inputString); setInputStringEncode(inputString);
encode(); encode();
return outputString; return outputString;
} }
//Sets the inputString and decodes the message /**
* Decodes the input string using the Baconian cipher.
*
* @param inputString the string to be decoded
* @return the decoded string
* @throws InvalidCharacterException if the input string contains invalid Baconian characters
* @throws InvalidInputException if the input string is invalid
*/
public String decode(String inputString) throws InvalidCharacterException, InvalidInputException{ public String decode(String inputString) throws InvalidCharacterException, InvalidInputException{
reset(); reset();
setInputStringDecode(inputString); setInputStringDecode(inputString);
@@ -182,14 +250,26 @@ public class Baconian{
return outputString; return outputString;
} }
//Getters //?Getters
/**
* Gets the current input string.
*
* @return the input string
*/
public String getInputString(){ public String getInputString(){
return inputString; return inputString;
} }
/**
* Gets the current output string.
*
* @return the output string
*/
public String getOutputString(){ public String getOutputString(){
return outputString; return outputString;
} }
//Makes sure all variables are empty /**
* Resets the input and output strings to empty.
*/
public void reset(){ public void reset(){
logger.debug("Resetting fields"); logger.debug("Resetting fields");

View File

@@ -1,7 +1,23 @@
//CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/monosubstitution/BaseX.java //CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/monosubstitution/BaseX.java
//Mattrixwv //Mattrixwv
// Created: 01-08-22 // Created: 01-08-22
//Modified: 05-04-23 //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; package com.mattrixwv.cipherstream.monosubstitution;
@@ -15,16 +31,35 @@ import com.mattrixwv.cipherstream.exceptions.InvalidCharacterException;
import com.mattrixwv.cipherstream.exceptions.InvalidInputException; import com.mattrixwv.cipherstream.exceptions.InvalidInputException;
/**
* A class for encoding and decoding strings using a specified numerical base.
* The BaseX class allows encoding and decoding of strings where characters are represented in a given base.
* The base can be set to any value between Character.MIN_RADIX and Character.MAX_RADIX.
*
* <p>
* This class supports encoding and decoding of ASCII characters into their base-X representations,
* where X is the base provided by the user. It ensures that input strings are valid and within the acceptable range
* for the specified base.
* </p>
*/
public class BaseX{ public class BaseX{
private static final Logger logger = LoggerFactory.getLogger(BaseX.class); private static final Logger logger = LoggerFactory.getLogger(BaseX.class);
//Fields //?Fields
protected String inputString; //The string that needs encoded/decoded /** The string that needs encoded/decoded */
protected String outputString; //The encoded/decoded string protected String inputString;
//Settings /** The encoded/decoded string */
protected int base; //The base that the number will be encoded at protected String outputString;
//?Settings
/** The base that the number will be encoded at */
protected int base;
//Sets the input string /**
* Sets the input string for encoding, ensuring it is not null and contains at least one letter.
*
* @param inputString the string to be encoded
* @throws InvalidInputException if the input string is null or blank
*/
protected void setInputStringEncode(String inputString) throws InvalidInputException{ protected void setInputStringEncode(String inputString) throws InvalidInputException{
if(inputString == null){ if(inputString == null){
throw new InvalidInputException("Input cannot be null"); throw new InvalidInputException("Input cannot be null");
@@ -38,6 +73,13 @@ public class BaseX{
throw new InvalidInputException("Input must contain at least 1 letter"); throw new InvalidInputException("Input must contain at least 1 letter");
} }
} }
/**
* Sets the input string for decoding, ensuring it is not null, does not contain invalid characters, and is properly formatted.
*
* @param inputString the string to be decoded
* @throws InvalidCharacterException if the input string contains invalid characters
* @throws InvalidInputException if the input string is null or blank
*/
protected void setInputStringDecode(String inputString) throws InvalidCharacterException, InvalidInputException{ protected void setInputStringDecode(String inputString) throws InvalidCharacterException, InvalidInputException{
if(inputString == null){ if(inputString == null){
throw new InvalidInputException("Input cannot be null"); throw new InvalidInputException("Input cannot be null");
@@ -68,7 +110,12 @@ public class BaseX{
throw new InvalidInputException("Input must contain at least 1 letter"); throw new InvalidInputException("Input must contain at least 1 letter");
} }
} }
//Sets the numeric base /**
* Sets the base for encoding and decoding, ensuring it is within valid range.
*
* @param base the base to be set
* @throws InvalidBaseException if the base is less than Character.MIN_RADIX or greater than Character.MAX_RADIX
*/
protected void setBase(int base) throws InvalidBaseException{ protected void setBase(int base) throws InvalidBaseException{
if(base < Character.MIN_RADIX){ if(base < Character.MIN_RADIX){
throw new InvalidBaseException("Base cannot be less than " + Character.MIN_RADIX); throw new InvalidBaseException("Base cannot be less than " + Character.MIN_RADIX);
@@ -81,7 +128,9 @@ public class BaseX{
this.base = base; this.base = base;
} }
//Encode inputString, store it in outputString, and return it /**
* Encodes the input string using the specified base.
*/
protected void encode(){ protected void encode(){
logger.debug("Encoding"); logger.debug("Encoding");
@@ -102,7 +151,11 @@ public class BaseX{
outputString = output.toString().toUpperCase(); outputString = output.toString().toUpperCase();
logger.debug("Saving output string '{}'", outputString); logger.debug("Saving output string '{}'", outputString);
} }
//Decode inputString, store it in outputString, and return it /**
* Decodes the input string from the specified base.
*
* @throws InvalidCharacterException if the input string contains invalid characters for the base
*/
protected void decode() throws InvalidCharacterException{ protected void decode() throws InvalidCharacterException{
logger.debug("Decoding"); logger.debug("Decoding");
@@ -129,23 +182,49 @@ public class BaseX{
logger.debug("Saving output string '{}'", outputString); logger.debug("Saving output string '{}'", outputString);
} }
//Constructor //?Constructor
/**
* Constructs a new {@code BaseX} instance with the default base of 2.
*
* @throws InvalidBaseException if the default base is invalid
*/
public BaseX() throws InvalidBaseException{ public BaseX() throws InvalidBaseException{
reset(); reset();
setBase(2); setBase(2);
} }
/**
* Constructs a new {@code BaseX} instance with the specified base.
*
* @param base the base to be used for encoding and decoding
* @throws InvalidBaseException if the base is invalid
*/
public BaseX(int base) throws InvalidBaseException{ public BaseX(int base) throws InvalidBaseException{
reset(); reset();
setBase(base); setBase(base);
} }
//Sets the inputString and encodes the message /**
* Encodes the given input string using the current base.
*
* @param inputString the string to be encoded
* @return the encoded string
* @throws InvalidInputException if the input string is invalid
*/
public String encode(String inputString) throws InvalidInputException{ public String encode(String inputString) throws InvalidInputException{
reset(); reset();
setInputStringEncode(inputString); setInputStringEncode(inputString);
encode(); encode();
return outputString; return outputString;
} }
/**
* Encodes the given input string using the specified base.
*
* @param base the base to use for encoding
* @param inputString the string to be encoded
* @return the encoded string
* @throws InvalidBaseException if the base is invalid
* @throws InvalidInputException if the input string is invalid
*/
public String encode(int base, String inputString) throws InvalidBaseException, InvalidInputException{ public String encode(int base, String inputString) throws InvalidBaseException, InvalidInputException{
reset(); reset();
setBase(base); setBase(base);
@@ -153,13 +232,30 @@ public class BaseX{
encode(); encode();
return outputString; return outputString;
} }
//Sets the inputString and decodes the message /**
* Decodes the given input string using the current base.
*
* @param inputString the string to be decoded
* @return the decoded string
* @throws InvalidCharacterException if the input string contains invalid characters
* @throws InvalidInputException if the input string is invalid
*/
public String decode(String inputString) throws InvalidCharacterException, InvalidInputException{ public String decode(String inputString) throws InvalidCharacterException, InvalidInputException{
reset(); reset();
setInputStringDecode(inputString); setInputStringDecode(inputString);
decode(); decode();
return outputString; return outputString;
} }
/**
* Decodes the given input string using the specified base.
*
* @param base the base to use for decoding
* @param inputString the string to be decoded
* @return the decoded string
* @throws InvalidBaseException if the base is invalid
* @throws InvalidCharacterException if the input string contains invalid characters
* @throws InvalidInputException if the input string is invalid
*/
public String decode(int base, String inputString) throws InvalidBaseException, InvalidCharacterException, InvalidInputException{ public String decode(int base, String inputString) throws InvalidBaseException, InvalidCharacterException, InvalidInputException{
reset(); reset();
setBase(base); setBase(base);
@@ -168,17 +264,34 @@ public class BaseX{
return outputString; return outputString;
} }
//Getters //?Getters
/**
* Gets the current input string.
*
* @return the input string
*/
public String getInputString(){ public String getInputString(){
return inputString; return inputString;
} }
/**
* Gets the current output string.
*
* @return the output string
*/
public String getOutputString(){ public String getOutputString(){
return outputString; return outputString;
} }
/**
* Gets the current base.
*
* @return the base
*/
public int getBase(){ public int getBase(){
return base; return base;
} }
//Makes sure all variables are empty /**
* Resets the input and output strings to empty.
*/
public void reset(){ public void reset(){
logger.debug("Resetting fields"); logger.debug("Resetting fields");

View File

@@ -1,7 +1,23 @@
//CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/monosubstitution/Beaufort.java //CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/monosubstitution/Beaufort.java
//Mattrixwv //Mattrixwv
// Created: 02-23-22 // Created: 02-23-22
//Modified: 05-04-23 //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; package com.mattrixwv.cipherstream.monosubstitution;
@@ -12,23 +28,53 @@ import com.mattrixwv.cipherstream.exceptions.InvalidInputException;
import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException; import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException;
/**
* A class for encoding and decoding strings using the Beaufort cipher,
* which is a variant of the Vigenère cipher with additional steps.
*
* <p>
* The Beaufort cipher consists of three main steps:
* </p>
* <ul>
* <li>Atbash cipher for reversing the string</li>
* <li>Caesar cipher for shifting characters by a fixed amount</li>
* <li>Vigenère cipher for applying a keyword-based shift</li>
* </ul>
* This class allows you to encode and decode strings with options to preserve
* capitalization, whitespace, and symbols.
*/
public class Beaufort{ public class Beaufort{
private static final Logger logger = LoggerFactory.getLogger(Beaufort.class); private static final Logger logger = LoggerFactory.getLogger(Beaufort.class);
//Fields //?Fields
protected String inputString; //This is the string that needs encoded/decoded /** This is the string that needs encoded/decoded */
protected String outputString; //This is the string that is output after encoding/decoding protected String inputString;
protected String keyword; //This is the keyword that is responsible for determining the offsets that you change each character by /** This is the string that is output after encoding/decoding */
//Settings protected String outputString;
protected boolean preserveCapitals; //Persist capitals in the output string /** This is the keyword that is responsible for determining the offsets that you change each character by */
protected boolean preserveWhitespace; //Persist whitespace in the output string protected String keyword;
protected boolean preserveSymbols; //Persist symbols in the output string //?Settings
//Internal ciphers /** Persist capitals in the output string */
protected Atbash atbash; //The first step in encoding/decoding the cipher protected boolean preserveCapitals;
protected Caesar caesar; //The second step in encoding/decoding the cipher /** Persist whitespace in the output string */
protected Vigenere vigenere; //The third step in encoding/decoding the cipher protected boolean preserveWhitespace;
/** Persist symbols in the output string */
protected boolean preserveSymbols;
//?Internal ciphers
/** The first step in encoding/decoding the cipher */
protected Atbash atbash;
/** The second step in encoding/decoding the cipher */
protected Caesar caesar;
/** The third step in encoding/decoding the cipher */
protected Vigenere vigenere;
//Ensures inputString constraints /**
* Sets the input string for encoding or decoding, applying removal options
* for case, whitespace, and symbols.
*
* @param inputString the string to be processed
* @throws InvalidInputException if the input string is null or blank after processing
*/
public void setInputString(String inputString) throws InvalidInputException{ public void setInputString(String inputString) throws InvalidInputException{
//Make sure the input isn't null //Make sure the input isn't null
if(inputString == null){ if(inputString == null){
@@ -63,7 +109,13 @@ public class Beaufort{
throw new InvalidInputException("Input must contain at least 1 letter"); throw new InvalidInputException("Input must contain at least 1 letter");
} }
} }
//Ensures keyword constraints /**
* Sets the keyword for encoding or decoding, ensuring it contains only
* uppercase letters and is at least 2 letters long.
*
* @param keyword the keyword for the Vigenère cipher
* @throws InvalidKeywordException if the keyword is null, blank, or less than 2 letters
*/
public void setKeyword(String keyword) throws InvalidKeywordException{ public void setKeyword(String keyword) throws InvalidKeywordException{
//Make sure the keyword isn't null //Make sure the keyword isn't null
if(keyword == null){ if(keyword == null){
@@ -88,20 +140,38 @@ public class Beaufort{
throw new InvalidKeywordException("Keyword must contain at least 2 letters"); throw new InvalidKeywordException("Keyword must contain at least 2 letters");
} }
} }
//Encodes the inputString and stores the result in outputString /**
* Encodes the input string using the Beaufort cipher and stores the result in {@code outputString}.
*
* @throws InvalidKeywordException if the keyword is invalid
* @throws InvalidInputException if the input string is invalid
*/
protected void encode() throws InvalidKeywordException, InvalidInputException{ protected void encode() throws InvalidKeywordException, InvalidInputException{
logger.debug("Encoding"); logger.debug("Encoding");
code(); code();
} }
//Decodes the inputString and stores the result in outputString /**
* Decodes the input string using the Beaufort cipher and stores the result in {@code outputString}.
* Decoding is the same process as encoding in this cipher.
*
* @throws InvalidKeywordException if the keyword is invalid
* @throws InvalidInputException if the input string is invalid
*/
protected void decode() throws InvalidKeywordException, InvalidInputException{ protected void decode() throws InvalidKeywordException, InvalidInputException{
logger.debug("Decoding"); logger.debug("Decoding");
//Decoding is just encoding again //Decoding is just encoding again
code(); code();
} }
//Codes input and saves to output /**
* Performs the Beaufort cipher encoding/decoding process:
* <ul>
* <li>Encodes the input string using the Atbash cipher</li>
* <li>Shifts the result by 1 using the Caesar cipher</li>
* <li>Applies the Vigenère cipher using the keyword</li>
* </ul>
*/
protected void code(){ protected void code(){
//Reverse the string //Reverse the string
logger.debug("Encoding with Atbash"); logger.debug("Encoding with Atbash");
@@ -120,7 +190,10 @@ public class Beaufort{
} }
//Constructor //?Constructor
/**
* Constructs a new {@code Beaufort} instance with default settings.
*/
public Beaufort(){ public Beaufort(){
preserveCapitals = false; preserveCapitals = false;
preserveWhitespace = false; preserveWhitespace = false;
@@ -130,6 +203,13 @@ public class Beaufort{
vigenere = new Vigenere(false, false, false); vigenere = new Vigenere(false, false, false);
reset(); reset();
} }
/**
* Constructs a new {@code Beaufort} instance with specified settings.
*
* @param preserveCapitals whether to preserve capitalization in the output
* @param preserveWhitespace whether to preserve whitespace in the output
* @param preserveSymbols whether to preserve symbols in the output
*/
public Beaufort(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols){ public Beaufort(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols){
this.preserveCapitals = preserveCapitals; this.preserveCapitals = preserveCapitals;
this.preserveWhitespace = preserveWhitespace; this.preserveWhitespace = preserveWhitespace;
@@ -140,7 +220,15 @@ public class Beaufort{
reset(); reset();
} }
//Encodes inputString using keyword and returns the result /**
* Encodes the input string using the specified keyword.
*
* @param keyword the keyword for the Vigenère cipher
* @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
*/
public String encode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{ public String encode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{
//Set the parameters //Set the parameters
setKeyword(keyword); setKeyword(keyword);
@@ -150,7 +238,15 @@ public class Beaufort{
encode(); encode();
return outputString; return outputString;
} }
//Decodes inputString using keyword and returns the result /**
* Decodes the input string using the specified keyword.
*
* @param keyword the keyword for the Vigenère cipher
* @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
*/
public String decode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{ public String decode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{
//Set the parameters //Set the parameters
setKeyword(keyword); setKeyword(keyword);
@@ -161,17 +257,34 @@ public class Beaufort{
return outputString; return outputString;
} }
//Getters //?Getters
/**
* Gets the current input string.
*
* @return the input string
*/
public String getInputString(){ public String getInputString(){
return inputString; return inputString;
} }
/**
* Gets the current output string.
*
* @return the output string
*/
public String getOutputString(){ public String getOutputString(){
return outputString; return outputString;
} }
/**
* Gets the current keyword.
*
* @return the keyword
*/
public String getKeyword(){ public String getKeyword(){
return keyword; return keyword;
} }
//Makes sure all variables are empty /**
* Resets the input string, output string, and keyword to empty.
*/
public void reset(){ public void reset(){
logger.debug("Resetting fields"); logger.debug("Resetting fields");

View File

@@ -1,7 +1,23 @@
//CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/monosubstitution/Caesar.java //CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/monosubstitution/Caesar.java
//Matthew Ellison //Matthew Ellison
// Created: 07-25-21 // Created: 07-25-21
//Modified: 05-04-23 //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; package com.mattrixwv.cipherstream.monosubstitution;
@@ -11,19 +27,39 @@ import org.slf4j.LoggerFactory;
import com.mattrixwv.cipherstream.exceptions.InvalidInputException; import com.mattrixwv.cipherstream.exceptions.InvalidInputException;
/**
* A class for encoding and decoding strings using the Caesar cipher.
*
* <p>
* The Caesar cipher is a substitution cipher where each letter in the
* plaintext is shifted a fixed number of places down or up the alphabet.
* This class allows you to encode and decode strings with options to preserve
* capitalization, whitespace, and symbols.
* </p>
*/
public class Caesar{ public class Caesar{
private static final Logger logger = LoggerFactory.getLogger(Caesar.class); private static final Logger logger = LoggerFactory.getLogger(Caesar.class);
//Fields //?Fields
protected String inputString; //The string that needs encoded/decoded /** The string that needs encoded/decoded */
protected String outputString; //The encoded/decoded string protected String inputString;
protected int shift; //The amount that you need to shift each letter /** The encoded/decoded string */
//Settings protected String outputString;
protected boolean preserveCapitals; //Persist capitals in the output string /** The amount that you need to shift each letter */
protected boolean preserveWhitespace; //Persist whitespace in the output string protected int shift;
protected boolean preserveSymbols; //Persist symbols in the output string //?Settings
/** Persist capitals in the output string */
protected boolean preserveCapitals;
/** Persist whitespace in the output string */
protected boolean preserveWhitespace;
/** Persist symbols in the output string */
protected boolean preserveSymbols;
//Sets shift and makes sure it is within the propper bounds /**
* Sets the shift amount and ensures it is within the proper bounds (0-25).
*
* @param shiftAmount the amount to shift each letter
*/
protected void setShift(int shiftAmount){ protected void setShift(int shiftAmount){
logger.debug("Setting shift {}", shiftAmount); logger.debug("Setting shift {}", shiftAmount);
@@ -32,7 +68,13 @@ public class Caesar{
logger.debug("Cleaned shift {}", shift); logger.debug("Cleaned shift {}", shift);
} }
//Sets the input string /**
* Sets the input string for encoding or decoding, applying removal options
* for case, whitespace, and symbols.
*
* @param inputString the string to be processed
* @throws InvalidInputException if the input string is null or blank after processing
*/
protected void setInputString(String inputString) throws InvalidInputException{ protected void setInputString(String inputString) throws InvalidInputException{
if(inputString == null){ if(inputString == null){
throw new InvalidInputException("Input cannot be null"); throw new InvalidInputException("Input cannot be null");
@@ -63,7 +105,9 @@ public class Caesar{
throw new InvalidInputException("Input must contain at least 1 letter"); throw new InvalidInputException("Input must contain at least 1 letter");
} }
} }
//Encodes the inputString and stores the result in outputString /**
* Encodes the input string by shifting letters according to the Caesar cipher.
*/
protected void encode(){ protected void encode(){
logger.debug("Encoding"); logger.debug("Encoding");
@@ -111,7 +155,9 @@ public class Caesar{
outputString = output.toString(); outputString = output.toString();
logger.debug("Saving encoded string '{}'", outputString); logger.debug("Saving encoded string '{}'", outputString);
} }
//Decodes the inputString and stores the result in outputString /**
* Decodes the input string by reversing the shift applied during encoding.
*/
protected void decode(){ protected void decode(){
logger.debug("Decoding"); logger.debug("Decoding");
@@ -164,13 +210,23 @@ public class Caesar{
logger.debug("Saving decoded string '{}'", outputString); logger.debug("Saving decoded string '{}'", outputString);
} }
//Constructor //?Constructor
/**
* Constructs a new {@code Caesar} instance with default settings.
*/
public Caesar(){ public Caesar(){
reset(); reset();
preserveCapitals = false; preserveCapitals = false;
preserveWhitespace = false; preserveWhitespace = false;
preserveSymbols = false; preserveSymbols = false;
} }
/**
* Constructs a new {@code Caesar} instance with specified settings.
*
* @param preserveCapitals whether to preserve capitalization in the output
* @param preserveWhitespace whether to preserve whitespace in the output
* @param preserveSymbols whether to preserve symbols in the output
*/
public Caesar(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols){ public Caesar(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols){
reset(); reset();
this.preserveCapitals = preserveCapitals; this.preserveCapitals = preserveCapitals;
@@ -178,7 +234,14 @@ public class Caesar{
this.preserveSymbols = preserveSymbols; this.preserveSymbols = preserveSymbols;
} }
//Sets the shift and inputString and encodes the message /**
* Encodes the input string with the specified shift amount.
*
* @param shiftAmount the amount to shift each letter
* @param inputString the string to be encoded
* @return the encoded string
* @throws InvalidInputException if the input string is invalid
*/
public String encode(int shiftAmount, String inputString) throws InvalidInputException{ public String encode(int shiftAmount, String inputString) throws InvalidInputException{
reset(); reset();
setShift(shiftAmount); setShift(shiftAmount);
@@ -186,7 +249,14 @@ public class Caesar{
encode(); encode();
return outputString; return outputString;
} }
//Sets the shift and inputString and decodes the message /**
* Decodes the input string with the specified shift amount.
*
* @param shiftAmount the amount to shift each letter
* @param inputString the string to be decoded
* @return the decoded string
* @throws InvalidInputException if the input string is invalid
*/
public String decode(int shiftAmount, String inputString) throws InvalidInputException{ public String decode(int shiftAmount, String inputString) throws InvalidInputException{
reset(); reset();
setShift(shiftAmount); setShift(shiftAmount);
@@ -195,17 +265,34 @@ public class Caesar{
return outputString; return outputString;
} }
//Getters //?Getters
/**
* Gets the current input string.
*
* @return the input string
*/
public String getInputString(){ public String getInputString(){
return inputString; return inputString;
} }
/**
* Gets the current shift amount.
*
* @return the shift amount
*/
public int getShift(){ public int getShift(){
return shift; return shift;
} }
/**
* Gets the current output string.
*
* @return the output string
*/
public String getOutputString(){ public String getOutputString(){
return outputString; return outputString;
} }
//Makes sure all variables are empty /**
* Resets the internal fields to their default values.
*/
public void reset(){ public void reset(){
logger.debug("Resetting fields"); logger.debug("Resetting fields");

View File

@@ -1,7 +1,23 @@
//CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/monosubstitution/OneTimePad.java //CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/monosubstitution/OneTimePad.java
//Mattrixwv //Mattrixwv
// Created: 02-23-22 // Created: 02-23-22
//Modified: 05-04-23 //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; package com.mattrixwv.cipherstream.monosubstitution;
@@ -12,21 +28,51 @@ import com.mattrixwv.cipherstream.exceptions.InvalidInputException;
import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException; import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException;
/**
* A class for encoding and decoding strings using the One-Time Pad cipher,
* which is a special case of the Vigenère cipher where the key is as long as
* the input message and used only once.
*
* <p>
* The One-Time Pad cipher provides perfect secrecy when the key is truly random,
* as long as the key length is equal to or greater than the length of the message
* and the key is used only once.
* </p>
*/
public class OneTimePad extends Vigenere{ public class OneTimePad extends Vigenere{
private static final Logger logger = LoggerFactory.getLogger(OneTimePad.class); private static final Logger logger = LoggerFactory.getLogger(OneTimePad.class);
//?Add some kind of entropy calculator? //?Add some kind of entropy calculator?
//Constructor //?Constructor
/**
* Constructs a new {@code OneTimePad} instance with default settings.
*/
public OneTimePad(){ public OneTimePad(){
super(); super();
} }
/**
* Constructs a new {@code OneTimePad} instance with specified settings.
*
* @param preserveCapitals whether to preserve capitalization in the output
* @param preserveWhitespace whether to preserve whitespace in the output
* @param preserveSymbols whether to preserve symbols in the output
*/
public OneTimePad(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols){ public OneTimePad(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols){
super(preserveCapitals, preserveWhitespace, preserveSymbols); super(preserveCapitals, preserveWhitespace, preserveSymbols);
} }
//Encodes input using key and returns the result /**
* Encodes the input string using the One-Time Pad cipher with the provided key.
* The key must be at least as long as the input string.
*
* @param keyword the key to use for encoding
* @param inputString the string to be encoded
* @return the encoded string
* @throws InvalidKeywordException if the key is shorter than the input string
* @throws InvalidInputException if the input string is invalid
*/
@Override @Override
public String encode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{ public String encode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{
if(keyword.length() < inputString.length()){ if(keyword.length() < inputString.length()){
@@ -37,7 +83,16 @@ public class OneTimePad extends Vigenere{
return super.encode(keyword, inputString); return super.encode(keyword, inputString);
} }
//Decodes input using key and returns the result /**
* Decodes the input string using the One-Time Pad cipher with the provided key.
* The key must be at least as long as the input string.
*
* @param keyword the key to use for decoding
* @param inputString the string to be decoded
* @return the decoded string
* @throws InvalidKeywordException if the key is shorter than the input string
* @throws InvalidInputException if the input string is invalid
*/
@Override @Override
public String decode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{ public String decode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{
if(keyword.length() < inputString.length()){ if(keyword.length() < inputString.length()){

View File

@@ -1,7 +1,23 @@
//CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/monosubstitution/Porta.java //CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/monosubstitution/Porta.java
//Mattrixwv //Mattrixwv
// Created: 02-28-22 // Created: 02-28-22
//Modified: 05-04-23 //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; package com.mattrixwv.cipherstream.monosubstitution;
@@ -12,9 +28,22 @@ import com.mattrixwv.cipherstream.exceptions.InvalidInputException;
import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException; import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException;
/**
* A class for encoding and decoding strings using the Porta cipher,
* which is a variant of the Vigenère cipher that uses a tableau of
* alphabets to encode and decode messages.
*
* <p>
* The Porta cipher uses a series of Caesar ciphers based on a repeating
* keyword, with a pre-defined set of alphabetic shifts. This implementation
* allows for encoding and decoding of messages while preserving or removing
* certain characters based on configuration settings.
* </p>
*/
public class Porta{ public class Porta{
private static final Logger logger = LoggerFactory.getLogger(Porta.class); private static final Logger logger = LoggerFactory.getLogger(Porta.class);
/** Predefined alphabetic tableau used for encoding and decoding */
private static final String[] tableau = { private static final String[] tableau = {
"NOPQRSTUVWXYZABCDEFGHIJKLM", //A-B "NOPQRSTUVWXYZABCDEFGHIJKLM", //A-B
"OPQRSTUVWXYZNMABCDEFGHIJKL", //C-D "OPQRSTUVWXYZNMABCDEFGHIJKL", //C-D
@@ -31,17 +60,28 @@ public class Porta{
"ZNOPQRSTUVWXYBCDEFGHIJKLMA" //Y-Z "ZNOPQRSTUVWXYBCDEFGHIJKLMA" //Y-Z
}; };
//Fields //?Fields
protected String inputString; //The string that needs encoded/decoded /** The string that needs encoded/decoded */
protected String outputString; //The encoded/decoded string protected String inputString;
protected String keyword; //The keyword used to encode the input string /** The encoded/decoded string */
//Settings protected String outputString;
protected boolean preserveCapitals; //Persist capitals in the output string /** The keyword used to encode the input string */
protected boolean preserveWhitespace; //Persist whitespace in the output string protected String keyword;
protected boolean preserveSymbols; //Persist symbols in the output string //?Settings
/** Persist capitals in the output string */
protected boolean preserveCapitals;
/** Persist whitespace in the output string */
protected boolean preserveWhitespace;
/** Persist symbols in the output string */
protected boolean preserveSymbols;
//Ensure all keyword constraints are followed /**
* Ensures all keyword constraints are followed.
*
* @param keyword the keyword to be used for encoding/decoding
* @throws InvalidKeywordException if the keyword is null, empty, or less than 2 characters
*/
protected void setKeyword(String keyword) throws InvalidKeywordException{ protected void setKeyword(String keyword) throws InvalidKeywordException{
//Make sure the keyword isn't null //Make sure the keyword isn't null
if(keyword == null){ if(keyword == null){
@@ -67,7 +107,12 @@ public class Porta{
throw new InvalidKeywordException("Keyword must contain at least 2 letters"); throw new InvalidKeywordException("Keyword must contain at least 2 letters");
} }
} }
//Ensure all input constraints are followed /**
* Ensures all input constraints are followed.
*
* @param inputString the string to be encoded/decoded
* @throws InvalidInputException if the input string is null or blank
*/
protected void setInputString(String inputString) throws InvalidInputException{ protected void setInputString(String inputString) throws InvalidInputException{
//Ensure the input isn't null //Ensure the input isn't null
if(inputString == null){ if(inputString == null){
@@ -102,7 +147,13 @@ public class Porta{
throw new InvalidInputException("Input must contain at least 1 letter"); throw new InvalidInputException("Input must contain at least 1 letter");
} }
} }
//Returns the letter that replaces the passed in letter /**
* Returns the letter that replaces the passed-in letter based on the keyword and tableau.
*
* @param keywordCnt the index of the keyword character to use
* @param letter the letter to be replaced
* @return the replacement letter
*/
protected char getReplacer(int keywordCnt, char letter){ protected char getReplacer(int keywordCnt, char letter){
logger.debug("Getting letter that replaces {} at {}", letter, keywordCnt); logger.debug("Getting letter that replaces {} at {}", letter, keywordCnt);
@@ -130,21 +181,30 @@ public class Porta{
logger.debug("Replacer {}", replacer); logger.debug("Replacer {}", replacer);
return replacer; return replacer;
} }
//Encodes the inputString and stores the result in outputString /**
* Encodes the inputString and stores the result in outputString.
* Encoding is the same as decoding for this cipher.
*/
protected void encode(){ protected void encode(){
logger.debug("Encoding"); logger.debug("Encoding");
//Encoding is the same as decoding //Encoding is the same as decoding
code(); code();
} }
//Decodes the inputString and stores the result in outputString /**
* Decodes the inputString and stores the result in outputString.
* Decoding is the same as encoding for this cipher.
*/
protected void decode(){ protected void decode(){
logger.debug("Decoding"); logger.debug("Decoding");
//Decoding is the same as encoding //Decoding is the same as encoding
code(); code();
} }
//Codes the inputString and stores the result in outputString /**
* Encodes or decodes the inputString based on the provided keyword.
* Uses the tableau to replace characters.
*/
protected void code(){ protected void code(){
StringBuilder output = new StringBuilder(); StringBuilder output = new StringBuilder();
@@ -175,13 +235,23 @@ public class Porta{
} }
//Constructor //?Constructor
/**
* Constructs a new {@code Porta} instance with default settings.
*/
public Porta(){ public Porta(){
preserveCapitals = false; preserveCapitals = false;
preserveWhitespace = false; preserveWhitespace = false;
preserveSymbols = false; preserveSymbols = false;
reset(); reset();
} }
/**
* Constructs a new {@code Porta} instance with specified settings.
*
* @param preserveCapitals whether to preserve capitalization in the output
* @param preserveWhitespace whether to preserve whitespace in the output
* @param preserveSymbols whether to preserve symbols in the output
*/
public Porta(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols){ public Porta(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols){
this.preserveCapitals = preserveCapitals; this.preserveCapitals = preserveCapitals;
this.preserveWhitespace = preserveWhitespace; this.preserveWhitespace = preserveWhitespace;
@@ -189,7 +259,15 @@ public class Porta{
reset(); reset();
} }
//Sets the keyword and inputString and encodes the message /**
* Sets the keyword and inputString and encodes the message.
*
* @param keyword the keyword to use 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
*/
public String encode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{ public String encode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{
//Set the parameters //Set the parameters
reset(); reset();
@@ -200,7 +278,15 @@ public class Porta{
encode(); encode();
return outputString; return outputString;
} }
//Sets the keyword and inputString and decodes the message /**
* Sets the keyword and inputString and decodes the message.
*
* @param keyword the keyword to use 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
*/
public String decode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{ public String decode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{
//Set the parameters //Set the parameters
reset(); reset();
@@ -212,17 +298,34 @@ public class Porta{
return outputString; return outputString;
} }
//Getters //?Getters
/**
* Gets the current input string.
*
* @return the input string
*/
public String getInputString(){ public String getInputString(){
return inputString; return inputString;
} }
/**
* Gets the current output string.
*
* @return the output string
*/
public String getOutputString(){ public String getOutputString(){
return outputString; return outputString;
} }
/**
* Gets the current keyword.
*
* @return the keyword
*/
public String getKeyword(){ public String getKeyword(){
return keyword; return keyword;
} }
//Makes sure all fields are empty /**
* Resets all fields to their default values.
*/
public void reset(){ public void reset(){
logger.debug("Resetting fields"); logger.debug("Resetting fields");

View File

@@ -1,7 +1,23 @@
//CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/monosubstitution/Substitution.java //CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/monosubstitution/Substitution.java
//Mattrixwv //Mattrixwv
// Created: 02-22-22 // Created: 02-22-22
//Modified: 05-04-23 //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; package com.mattrixwv.cipherstream.monosubstitution;
@@ -12,19 +28,41 @@ import com.mattrixwv.cipherstream.exceptions.InvalidInputException;
import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException; import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException;
/**
* A class for encoding and decoding strings using a substitution cipher.
* This cipher can handle both alphabetic and alphanumeric keys and supports
* preserving or removing capitalization, whitespace, and symbols.
*
* <p>
* The substitution cipher replaces each letter or digit in the input string
* with a corresponding character from a key. The key must contain all letters
* of the alphabet and optionally digits, without duplicates.
* </p>
*/
public class Substitution{ public class Substitution{
private static final Logger logger = LoggerFactory.getLogger(Substitution.class); private static final Logger logger = LoggerFactory.getLogger(Substitution.class);
//Fields //?Fields
protected String inputString; //The string that needs encoded/decoded /** The string that needs encoded/decoded */
protected String outputString; //The encoded/decoded string protected String inputString;
protected String keyword; //The keyword used to encode/decode the input /** The encoded/decoded string */
//Getters protected String outputString;
protected boolean preserveCapitals; //Persist capitals in the output string /** The keyword used to encode/decode the input */
protected boolean preserveWhitespace; //Persist whitespace in the output string protected String keyword;
protected boolean preserveSymbols; //Persist symbols in the output string //?Getters
/** Persist capitals in the output string */
protected boolean preserveCapitals;
/** Persist whitespace in the output string */
protected boolean preserveWhitespace;
/** Persist symbols in the output string */
protected boolean preserveSymbols;
//Ensures key constraints are followed /**
* Ensures all key constraints are followed.
*
* @param key the key to be used for encoding/decoding
* @throws InvalidKeywordException if the key is null, contains duplicates, or has invalid length
*/
protected void setKeyword(String key) throws InvalidKeywordException{ protected void setKeyword(String key) throws InvalidKeywordException{
if(key == null){ if(key == null){
throw new InvalidKeywordException("Key cannot be null"); throw new InvalidKeywordException("Key cannot be null");
@@ -71,7 +109,12 @@ public class Substitution{
logger.debug("Cleaned key '{}'", key); logger.debug("Cleaned key '{}'", key);
this.keyword = key; this.keyword = key;
} }
//Ensure intput constraints are followed /**
* Ensures all input constraints are followed.
*
* @param inputString the string to be encoded/decoded
* @throws InvalidInputException if the input string is null or blank
*/
protected void setInputString(String inputString) throws InvalidInputException{ protected void setInputString(String inputString) throws InvalidInputException{
if(inputString == null){ if(inputString == null){
throw new InvalidInputException("Input cannot be null"); throw new InvalidInputException("Input cannot be null");
@@ -105,7 +148,9 @@ public class Substitution{
throw new InvalidInputException("Input must contain at least 1 letter"); throw new InvalidInputException("Input must contain at least 1 letter");
} }
} }
//Encodes the inputString and stores the result in outputString /**
* Encodes the inputString using the provided key and stores the result in outputString.
*/
protected void encode(){ protected void encode(){
logger.debug("Encoding"); logger.debug("Encoding");
@@ -137,7 +182,9 @@ public class Substitution{
this.outputString = output.toString(); this.outputString = output.toString();
logger.debug("Encoded message '{}'", outputString); logger.debug("Encoded message '{}'", outputString);
} }
//Decodes the inputString and stores the result in outputString /**
* Decodes the inputString using the provided key and stores the result in outputString.
*/
protected void decode(){ protected void decode(){
logger.debug("Decoding"); logger.debug("Decoding");
@@ -173,13 +220,23 @@ public class Substitution{
logger.debug("Decoded message '{}'", outputString); logger.debug("Decoded message '{}'", outputString);
} }
//Constructors //?Constructors
/**
* Constructs a new {@code Substitution} instance with default settings.
*/
public Substitution(){ public Substitution(){
preserveCapitals = false; preserveCapitals = false;
preserveWhitespace = false; preserveWhitespace = false;
preserveSymbols = false; preserveSymbols = false;
reset(); reset();
} }
/**
* Constructs a new {@code Substitution} instance with specified settings.
*
* @param preserveCapitals whether to preserve capitalization in the output
* @param preserveWhitespace whether to preserve whitespace in the output
* @param preserveSymbols whether to preserve symbols in the output
*/
public Substitution(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols){ public Substitution(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols){
this.preserveCapitals = preserveCapitals; this.preserveCapitals = preserveCapitals;
this.preserveWhitespace = preserveWhitespace; this.preserveWhitespace = preserveWhitespace;
@@ -187,14 +244,30 @@ public class Substitution{
reset(); reset();
} }
//Encodes inputString using the provided key /**
* Encodes the inputString using the provided key.
*
* @param key the key to use for encoding
* @param inputString the string to be encoded
* @return the encoded string
* @throws InvalidKeywordException if the key is invalid
* @throws InvalidInputException if the input string is invalid
*/
public String encode(String key, String inputString) throws InvalidKeywordException, InvalidInputException{ public String encode(String key, String inputString) throws InvalidKeywordException, InvalidInputException{
setKeyword(key); setKeyword(key);
setInputString(inputString); setInputString(inputString);
encode(); encode();
return outputString; return outputString;
} }
//Decodes inputString using the provided key /**
* Decodes the inputString using the provided key.
*
* @param key the key to use for decoding
* @param inputString the string to be decoded
* @return the decoded string
* @throws InvalidKeywordException if the key is invalid
* @throws InvalidInputException if the input string is invalid
*/
public String decode(String key, String inputString) throws InvalidKeywordException, InvalidInputException{ public String decode(String key, String inputString) throws InvalidKeywordException, InvalidInputException{
setKeyword(key); setKeyword(key);
setInputString(inputString); setInputString(inputString);
@@ -202,17 +275,34 @@ public class Substitution{
return outputString; return outputString;
} }
//Getters //?Getters
/**
* Gets the current input string.
*
* @return the input string
*/
public String getInputString(){ public String getInputString(){
return inputString; return inputString;
} }
/**
* Gets the current output string.
*
* @return the output string
*/
public String getOutputString(){ public String getOutputString(){
return outputString; return outputString;
} }
/**
* Gets the current keyword.
*
* @return the keyword
*/
public String getKeyword(){ public String getKeyword(){
return keyword; return keyword;
} }
//Makes sure all variables are empty /**
* Resets all fields to their default values.
*/
public void reset(){ public void reset(){
logger.debug("Resetting fields"); logger.debug("Resetting fields");

View File

@@ -1,7 +1,23 @@
//CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/monosubstitution/Vigenere.java //CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/monosubstitution/Vigenere.java
//Matthew Ellison //Matthew Ellison
// Created: 07-25-21 // Created: 07-25-21
//Modified: 05-04-23 //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; package com.mattrixwv.cipherstream.monosubstitution;
@@ -15,20 +31,38 @@ import com.mattrixwv.cipherstream.exceptions.InvalidInputException;
import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException; import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException;
/**
* A class for encoding and decoding strings using the Vigenère cipher.
* This cipher uses a keyword to determine the shift for each character in the input string.
*
* <p>
* The Vigenère cipher applies a series of Caesar ciphers based on the letters of a keyword.
* The keyword determines the shift for each letter in the input string.
* </p>
*/
public class Vigenere{ public class Vigenere{
private static final Logger logger = LoggerFactory.getLogger(Vigenere.class); private static final Logger logger = LoggerFactory.getLogger(Vigenere.class);
//Fields //Fields
protected String inputString; //This is the string that needs encoded/decoded /** This is the string that needs encoded/decoded */
protected String outputString; //This is the string that is output after encoding/decoding protected String inputString;
protected String keyword; //This is the keyword that is resposible for determining the offsets that you change each character by /** This is the string that is output after encoding/decoding */
protected ArrayList<Integer> offset; //Holds the offsets coputed from each character in the keyword protected String outputString;
/** This is the keyword that is resposible for determining the offsets that you change each character by */
protected String keyword;
/** Holds the offsets coputed from each character in the keyword */
protected ArrayList<Integer> offset;
//Settings //Settings
protected boolean preserveCapitals; //Persist capitals in the output string /** Persist capitals in the output string */
protected boolean preserveWhitespace; //Persist whitespace in the output string protected boolean preserveCapitals;
protected boolean preserveSymbols; //Persist symbols in the output string /** Persist whitespace in the output string */
protected boolean preserveWhitespace;
/** Persist symbols in the output string */
protected boolean preserveSymbols;
//Uses keyword to calculate the offset for the Caesar cipher for each character /**
* Calculates the offsets for the Vigenère cipher from the keyword.
*/
protected void setOffset(){ protected void setOffset(){
logger.debug("Setting offset array from keyword"); logger.debug("Setting offset array from keyword");
@@ -43,7 +77,12 @@ public class Vigenere{
logger.debug("Offset {}", offset); logger.debug("Offset {}", offset);
} }
//Sets inputString /**
* Sets the input string and applies transformation settings.
*
* @param inputString the string to be encoded/decoded
* @throws InvalidInputException if the input string is null or blank
*/
protected void setInputString(String inputString) throws InvalidInputException{ protected void setInputString(String inputString) throws InvalidInputException{
if(inputString == null){ if(inputString == null){
throw new InvalidInputException("Input cannot be null"); throw new InvalidInputException("Input cannot be null");
@@ -74,7 +113,12 @@ public class Vigenere{
throw new InvalidInputException("Input must contain at least 1 letter"); throw new InvalidInputException("Input must contain at least 1 letter");
} }
} }
//Sets keyword /**
* Sets the keyword for the Vigenère cipher and computes the offsets.
*
* @param keyword the keyword to be used for encoding/decoding
* @throws InvalidKeywordException if the keyword is null, too short, or contains invalid characters
*/
protected void setKeyword(String keyword) throws InvalidKeywordException{ protected void setKeyword(String keyword) throws InvalidKeywordException{
if(keyword == null){ if(keyword == null){
throw new InvalidKeywordException("Keyword cannot be null"); throw new InvalidKeywordException("Keyword cannot be null");
@@ -102,7 +146,9 @@ public class Vigenere{
throw new InvalidKeywordException("Keyword must contain at least 2 letters"); throw new InvalidKeywordException("Keyword must contain at least 2 letters");
} }
} }
//Encodes inputString and stores the result in outputString /**
* Encodes the input string using the Vigenère cipher and stores the result.
*/
protected void encode(){ protected void encode(){
logger.debug("Encoding"); logger.debug("Encoding");
@@ -147,7 +193,9 @@ public class Vigenere{
outputString = output.toString(); outputString = output.toString();
logger.debug("Encoded message '{}'", outputString); logger.debug("Encoded message '{}'", outputString);
} }
//Decodes inputString and stores the result in outputString /**
* Decodes the input string using the Vigenère cipher and stores the result.
*/
protected void decode(){ protected void decode(){
logger.debug("Decoding"); logger.debug("Decoding");
@@ -194,7 +242,10 @@ public class Vigenere{
} }
//Constructor //?Constructor
/**
* Constructs a new {@code Vigenere} instance with default settings.
*/
public Vigenere(){ public Vigenere(){
offset = new ArrayList<>(); offset = new ArrayList<>();
reset(); reset();
@@ -202,6 +253,13 @@ public class Vigenere{
preserveWhitespace = false; preserveWhitespace = false;
preserveSymbols = false; preserveSymbols = false;
} }
/**
* Constructs a new {@code Vigenere} instance with specified settings.
*
* @param preserveCapitals whether to preserve capitalization in the output
* @param preserveWhitespace whether to preserve whitespace in the output
* @param preserveSymbols whether to preserve symbols in the output
*/
public Vigenere(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols){ public Vigenere(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols){
offset = new ArrayList<>(); offset = new ArrayList<>();
reset(); reset();
@@ -210,7 +268,15 @@ public class Vigenere{
this.preserveSymbols = preserveSymbols; this.preserveSymbols = preserveSymbols;
} }
//Encodes input using key and returns the result /**
* Encodes the input string using the provided keyword.
*
* @param keyword the keyword to use 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
*/
public String encode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{ public String encode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{
reset(); reset();
setKeyword(keyword); setKeyword(keyword);
@@ -218,7 +284,15 @@ public class Vigenere{
encode(); encode();
return outputString; return outputString;
} }
//Decodes input using key and returns the result /**
* Decodes the input string using the provided keyword.
*
* @param keyword the keyword to use 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
*/
public String decode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{ public String decode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{
reset(); reset();
setKeyword(keyword); setKeyword(keyword);
@@ -227,21 +301,42 @@ public class Vigenere{
return outputString; return outputString;
} }
//Getters //?Getters
/**
* Gets the current input string.
*
* @return the input string
*/
public String getInputString(){ public String getInputString(){
return inputString; return inputString;
} }
/**
* Gets the current output string.
*
* @return the output string
*/
public String getOutputString(){ public String getOutputString(){
return outputString; return outputString;
} }
/**
* Gets the current keyword.
*
* @return the keyword
*/
public String getKeyword(){ public String getKeyword(){
return keyword; return keyword;
} }
/**
* Gets the current offset list.
*
* @return the offset list
*/
public List<Integer> getOffsets(){ public List<Integer> getOffsets(){
return offset; return offset;
} }
/**
//Makes sure all variables are empty * Resets all fields to their default values.
*/
public void reset(){ public void reset(){
logger.debug("Resetting fields"); logger.debug("Resetting fields");

View File

@@ -1,7 +1,23 @@
//CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Bifid.java //CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Bifid.java
//Mattrixwv //Mattrixwv
// Created: 03-03-22 // Created: 03-03-22
//Modified: 05-04-23 //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.polysubstitution; package com.mattrixwv.cipherstream.polysubstitution;
@@ -13,21 +29,44 @@ import com.mattrixwv.cipherstream.exceptions.InvalidInputException;
import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException; import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException;
/**
* A class for encoding and decoding strings using the Bifid cipher.
* The Bifid cipher is a polygraphic substitution cipher that uses a Polybius square
* and applies a columnar transposition to encode or decode messages.
*
* <p>
* The Bifid cipher operates by converting the plaintext message into coordinates based on a
* Polybius square, then rearranges these coordinates using a transposition before converting
* them back into text.
* </p>
*/
public class Bifid{ public class Bifid{
private static final Logger logger = LoggerFactory.getLogger(Bifid.class); private static final Logger logger = LoggerFactory.getLogger(Bifid.class);
//Fields //?Fields
protected String inputString; //The message that needs to be encoded/decoded /** The message that needs to be encoded/decoded */
protected String outputString; //The encoded/decoded message protected String inputString;
protected String keyword; //The keyword used to create the grid /** The encoded/decoded message */
//Settings protected String outputString;
protected boolean preserveCapitals; //Persist capitals in the output string /** The keyword used to create the grid */
protected boolean preserveWhitespace; //Persist whitespace in the output string protected String keyword;
protected boolean preserveSymbols; //Persist symbols in the output string //?Settings
//Internal ciphers /** Persist capitals in the output string */
protected PolybiusSquare polybiusSquare; //Used to encode the message to numbers then back into letters protected boolean preserveCapitals;
/** Persist whitespace in the output string */
protected boolean preserveWhitespace;
/** Persist symbols in the output string */
protected boolean preserveSymbols;
//?Internal ciphers
/** Used to encode the message to numbers then back into letters */
protected PolybiusSquare polybiusSquare;
//Strips invalid characters from the keyword and creates the grid /**
* Sets the keyword for creating the Polybius square.
*
* @param keyword the keyword to use for the Polybius square
* @throws InvalidKeywordException if the keyword is null
*/
protected void setKeyword(String keyword) throws InvalidKeywordException{ protected void setKeyword(String keyword) throws InvalidKeywordException{
//Ensure the keyword isn't null //Ensure the keyword isn't null
if(keyword == null){ if(keyword == null){
@@ -39,7 +78,12 @@ public class Bifid{
//Save the key for polybius to deal with //Save the key for polybius to deal with
this.keyword = keyword; this.keyword = keyword;
} }
//Ensures inputString constraints /**
* Validates and preprocesses the input string based on the current settings.
*
* @param inputString the string to be encoded/decoded
* @throws InvalidInputException if the input string is null or blank
*/
protected void setInputString(String inputString) throws InvalidInputException{ protected void setInputString(String inputString) throws InvalidInputException{
//Ensure the input string isn't null //Ensure the input string isn't null
if(inputString == null){ if(inputString == null){
@@ -74,7 +118,11 @@ public class Bifid{
throw new InvalidInputException("Input must contain at least 1 letter"); throw new InvalidInputException("Input must contain at least 1 letter");
} }
} }
//Adds all non-letter characters back to the output string /**
* Formats the encoded/decoded output to match the input string's original format.
*
* @param outputString the encoded/decoded message to be formatted
*/
protected void formatOutput(String outputString){ protected void formatOutput(String outputString){
logger.debug("Formatting output"); logger.debug("Formatting output");
//Keep track of where you are in the output //Keep track of where you are in the output
@@ -104,7 +152,12 @@ public class Bifid{
this.outputString = output.toString(); this.outputString = output.toString();
logger.debug("Formatted output string '{}'", this.outputString); logger.debug("Formatted output string '{}'", this.outputString);
} }
//Encodes inputString using a polybius square and stores the result in outputString /**
* Encodes the input string using the Bifid cipher and stores the result in outputString.
*
* @throws InvalidCharacterException if there are invalid characters in the input
* @throws InvalidInputException if the input string is invalid
*/
protected void encode() throws InvalidCharacterException, InvalidInputException{ protected void encode() throws InvalidCharacterException, InvalidInputException{
logger.debug("Encoding"); logger.debug("Encoding");
@@ -140,7 +193,12 @@ public class Bifid{
//Format the output //Format the output
formatOutput(letterResult); formatOutput(letterResult);
} }
//Decodes inputString using a polybius square and stores the result in outputString /**
* Decodes the input string using the Bifid cipher and stores the result in outputString.
*
* @throws InvalidCharacterException if there are invalid characters in the input
* @throws InvalidInputException if the input string is invalid
*/
protected void decode() throws InvalidCharacterException, InvalidInputException{ protected void decode() throws InvalidCharacterException, InvalidInputException{
logger.debug("Decoding"); logger.debug("Decoding");
@@ -170,7 +228,12 @@ public class Bifid{
} }
//Constructors //?Constructors
/**
* Constructs a new {@code Bifid} instance with default settings.
*
* @throws InvalidCharacterException if initialization of PolybiusSquare fails
*/
public Bifid() throws InvalidCharacterException{ public Bifid() throws InvalidCharacterException{
preserveCapitals = false; preserveCapitals = false;
preserveWhitespace = false; preserveWhitespace = false;
@@ -178,6 +241,14 @@ public class Bifid{
polybiusSquare = new PolybiusSquare(false, false); polybiusSquare = new PolybiusSquare(false, false);
reset(); reset();
} }
/**
* Constructs a new {@code Bifid} instance with specified settings.
*
* @param preserveCapitals whether to preserve capitalization in the output
* @param preserveWhitespace whether to preserve whitespace in the output
* @param preserveSymbols whether to preserve symbols in the output
* @throws InvalidCharacterException if initialization of PolybiusSquare fails
*/
public Bifid(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols) throws InvalidCharacterException{ public Bifid(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols) throws InvalidCharacterException{
this.preserveCapitals = preserveCapitals; this.preserveCapitals = preserveCapitals;
this.preserveWhitespace = preserveWhitespace; this.preserveWhitespace = preserveWhitespace;
@@ -186,7 +257,16 @@ public class Bifid{
reset(); reset();
} }
//Encodes inputString using keyword and returns the result /**
* Encodes the input string using the provided keyword.
*
* @param keyword the keyword to use 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
* @throws InvalidCharacterException if the input contains invalid characters
*/
public String encode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException, InvalidCharacterException{ public String encode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException, InvalidCharacterException{
//Set the parameters //Set the parameters
reset(); reset();
@@ -197,7 +277,16 @@ public class Bifid{
encode(); encode();
return outputString; return outputString;
} }
//Decodes inputString using keyword and returns the result /**
* Decodes the input string using the provided keyword.
*
* @param keyword the keyword to use 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
* @throws InvalidCharacterException if the input contains invalid characters
*/
public String decode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException, InvalidCharacterException{ public String decode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException, InvalidCharacterException{
//Set the parameters //Set the parameters
reset(); reset();
@@ -209,18 +298,34 @@ public class Bifid{
return outputString; return outputString;
} }
//Getters //?Getters
/**
* Gets the current input string.
*
* @return the input string
*/
public String getInputString(){ public String getInputString(){
return inputString; return inputString;
} }
/**
* Gets the current output string.
*
* @return the output string
*/
public String getOutputString(){ public String getOutputString(){
return outputString; return outputString;
} }
/**
* Gets the current keyword.
*
* @return the keyword
*/
public String getKeyword(){ public String getKeyword(){
return keyword; return keyword;
} }
/**
//Makes sure all variables are empty * Resets all fields to their default values.
*/
public void reset(){ public void reset(){
logger.debug("Resetting fields"); logger.debug("Resetting fields");

View File

@@ -1,7 +1,23 @@
//MattrixwvWebsite/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Columnar.java //MattrixwvWebsite/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Columnar.java
//Mattrixwv //Mattrixwv
// Created: 01-16-22 // Created: 01-16-22
//Modified: 05-04-23 //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.polysubstitution; package com.mattrixwv.cipherstream.polysubstitution;
@@ -17,28 +33,54 @@ import com.mattrixwv.cipherstream.exceptions.InvalidInputException;
import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException; import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException;
/**
* This class implements the Columnar Transposition cipher for encoding and decoding messages.
* The Columnar Transposition cipher rearranges the letters of the plaintext based on a keyword,
* and then reads the message column-wise to produce the encoded output. For decoding, it reverses
* this process.
* <p>
* This class provides methods to configure the cipher, process input strings, and generate output.
* It also includes options to preserve capitalization, whitespace, symbols, and to handle padding characters.
* </p>
*/
public class Columnar{ public class Columnar{
private static final Logger logger = LoggerFactory.getLogger(Columnar.class); private static final Logger logger = LoggerFactory.getLogger(Columnar.class);
//Fields //?Fields
protected String inputString; //The message that needs to be encoded/decoded /** The message that needs to be encoded/decoded */
protected String outputString; //The encoded/decoded message protected String inputString;
protected String keyword; //The keyword used to create the grid /** The encoded/decoded message */
protected char characterToAdd; //The character that is added to the end of a string to bring it to the correct length protected String outputString;
protected int charsAdded; //The number of characters that were added to the end of the message /** The keyword used to create the grid */
protected ArrayList<ArrayList<Character>> grid; //The grid used to encode/decode the message protected String keyword;
//Settings /** The character that is added to the end of a string to bring it to the correct length */
protected boolean preserveCapitals; //Persist capitals in the output string protected char characterToAdd;
protected boolean preserveWhitespace; //Persist whitespace in the output string /** The number of characters that were added to the end of the message */
protected boolean preserveSymbols; //Persist symbols in the output string protected int charsAdded;
protected boolean removePadding; //Remove the padding letters added to the cipher /** The grid used to encode/decode the message */
protected ArrayList<ArrayList<Character>> grid;
//?Settings
/** Persist capitals in the output string */
protected boolean preserveCapitals;
/** Persist whitespace in the output string */
protected boolean preserveWhitespace;
/** Persist symbols in the output string */
protected boolean preserveSymbols;
/** Remove the padding letters added to the cipher */
protected boolean removePadding;
//Strip the inputString of all non-letter characters and change them to capitals /**
* Strip the inputString of all non-letter characters and change them to capitals
*
* @return The input string in capital letters with all non-letter characters removed
*/
protected String getCleanInputString(){ protected String getCleanInputString(){
logger.debug("Cleaning input string"); logger.debug("Cleaning input string");
return inputString.toUpperCase().replaceAll("[^A-Z]", ""); return inputString.toUpperCase().replaceAll("[^A-Z]", "");
} }
//Create the grid from the keyword /**
* Creates the grid used for encoding.
*/
protected void createGridEncode(){ protected void createGridEncode(){
logger.debug("Creating grid for encoding"); logger.debug("Creating grid for encoding");
@@ -58,6 +100,9 @@ public class Columnar{
))); )));
} }
} }
/**
* Creates the grid used for decoding.
*/
protected void createGridDecode(){ protected void createGridDecode(){
logger.debug("Creating grid for decoding"); logger.debug("Creating grid for decoding");
@@ -86,7 +131,12 @@ public class Columnar{
} }
} }
} }
//Strips invalid characters from the string that needs encoded/decoded /**
* Sets the input string for encoding, applying necessary modifications and padding.
*
* @param inputString the input string to encode
* @throws InvalidInputException if the input string is null or blank
*/
protected void setInputStringEncode(String inputString) throws InvalidInputException{ protected void setInputStringEncode(String inputString) throws InvalidInputException{
logger.debug("Setting input string for encoding"); logger.debug("Setting input string for encoding");
@@ -140,6 +190,12 @@ public class Columnar{
throw new InvalidInputException("Input cannot be blank"); throw new InvalidInputException("Input cannot be blank");
} }
} }
/**
* Sets the input string for decoding, applying necessary adjustments and padding.
*
* @param inputString the input string to decode
* @throws InvalidInputException if the input string is null or blank
*/
protected void setInputStringDecode(String inputString) throws InvalidInputException{ protected void setInputStringDecode(String inputString) throws InvalidInputException{
logger.debug("Setting input string for decoding"); logger.debug("Setting input string for decoding");
@@ -225,7 +281,9 @@ public class Columnar{
throw new InvalidInputException("Input cannot be blank"); throw new InvalidInputException("Input cannot be blank");
} }
} }
//Creates the output string from the grid /**
* Creates the output string by reading the columns of the grid.
*/
protected void createOutputStringFromColumns(){ protected void createOutputStringFromColumns(){
logger.debug("Creating output string for encoding"); logger.debug("Creating output string for encoding");
@@ -275,6 +333,9 @@ public class Columnar{
outputString = output.toString(); outputString = output.toString();
logger.debug("Output string '{}'", outputString); logger.debug("Output string '{}'", outputString);
} }
/**
* Creates the output string by reading the rows of the grid.
*/
protected void createOutputStringFromRows(){ protected void createOutputStringFromRows(){
logger.debug("Creating output string for decoding"); logger.debug("Creating output string for decoding");
@@ -345,7 +406,12 @@ public class Columnar{
outputString = output.toString(); outputString = output.toString();
logger.debug("Decoded output string '{}'", outputString); logger.debug("Decoded output string '{}'", outputString);
} }
//Strips invalid characters from the keyword and creates the grid /**
* Sets the keyword used for encoding or decoding.
*
* @param keyword the keyword to use
* @throws InvalidKeywordException if the keyword is null, contains less than 2 letters, or contains invalid characters
*/
protected void setKeyword(String keyword) throws InvalidKeywordException{ protected void setKeyword(String keyword) throws InvalidKeywordException{
//Ensure the keyword isn't null //Ensure the keyword isn't null
if(keyword == null){ if(keyword == null){
@@ -365,7 +431,12 @@ public class Columnar{
throw new InvalidKeywordException("The keyword must contain at least 2 letters"); throw new InvalidKeywordException("The keyword must contain at least 2 letters");
} }
} }
//Set the character that is added to the end of the string /**
* Sets the character used for padding.
*
* @param characterToAdd the padding character
* @throws InvalidCharacterException if the padding character is not a letter
*/
protected void setCharacterToAdd(char characterToAdd) throws InvalidCharacterException{ protected void setCharacterToAdd(char characterToAdd) throws InvalidCharacterException{
if(!Character.isAlphabetic(characterToAdd)){ if(!Character.isAlphabetic(characterToAdd)){
throw new InvalidCharacterException("Character to add must be a letter"); throw new InvalidCharacterException("Character to add must be a letter");
@@ -381,7 +452,11 @@ public class Columnar{
logger.debug("Character to add for padding {}", 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 /**
* Gets the positions of the keyword characters in alphabetical order.
*
* @return the list of positions of keyword characters in alphabetical order
*/
protected ArrayList<Integer> getKeywordAlphaLocations(){ protected ArrayList<Integer> getKeywordAlphaLocations(){
logger.debug("Creating an array of keyword letter locations"); logger.debug("Creating an array of keyword letter locations");
@@ -400,6 +475,11 @@ public class Columnar{
logger.debug("Array of keyword letters {}", orderedLocations); logger.debug("Array of keyword letters {}", orderedLocations);
return orderedLocations; return orderedLocations;
} }
/**
* Gets the original positions of the keyword characters.
*
* @return the list of original positions of keyword characters
*/
protected ArrayList<Integer> getKeywordOriginalLocations(){ protected ArrayList<Integer> getKeywordOriginalLocations(){
logger.debug("Creating array of original keyword locations"); logger.debug("Creating array of original keyword locations");
@@ -420,7 +500,11 @@ public class Columnar{
logger.debug("Array of keyword letters {}", originalOrder); logger.debug("Array of keyword letters {}", originalOrder);
return originalOrder; return originalOrder;
} }
//Rearanges the grid based on the list of numbers given /**
* Rearranges the grid based on the specified order.
*
* @param listOrder the order in which columns should be rearranged
*/
protected void rearangeGrid(ArrayList<Integer> listOrder){ protected void rearangeGrid(ArrayList<Integer> listOrder){
logger.debug("Rearanging grid"); logger.debug("Rearanging grid");
@@ -442,7 +526,9 @@ public class Columnar{
logger.debug("New grid {}", newGrid); logger.debug("New grid {}", newGrid);
grid = newGrid; grid = newGrid;
} }
//Encodes inputString using the Columnar cipher and stores the result in outputString /**
* Encodes the input string using the Columnar cipher.
*/
protected void encode(){ protected void encode(){
logger.debug("Encoding"); logger.debug("Encoding");
@@ -455,7 +541,9 @@ public class Columnar{
//Create the output //Create the output
createOutputStringFromColumns(); createOutputStringFromColumns();
} }
//Decodes inputString using the Columnar cipher and stores the result in outputString /**
* Decodes the input string using the Columnar cipher.
*/
protected void decode(){ protected void decode(){
logger.debug("Decoding"); logger.debug("Decoding");
@@ -468,7 +556,13 @@ public class Columnar{
createOutputStringFromRows(); createOutputStringFromRows();
} }
//Constructors //?Constructors
/**
* Constructs a new Columnar cipher instance with default settings.
* The default settings include preserving no capitalization, whitespace, or symbols, and using 'x' as the padding character.
*
* @throws InvalidCharacterException if the default padding character is invalid
*/
public Columnar() throws InvalidCharacterException{ public Columnar() throws InvalidCharacterException{
preserveCapitals = false; preserveCapitals = false;
preserveWhitespace = false; preserveWhitespace = false;
@@ -477,6 +571,15 @@ public class Columnar{
setCharacterToAdd('x'); setCharacterToAdd('x');
reset(); reset();
} }
/**
* Constructs a new Columnar cipher instance with customizable settings.
*
* @param preserveCapitals whether to preserve capitalization in the output
* @param preserveWhitespace whether to preserve whitespace in the output
* @param preserveSymbols whether to preserve symbols in the output
* @param removePadding whether to remove padding characters from the output
* @throws InvalidCharacterException if the default padding character is invalid
*/
public Columnar(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols, boolean removePadding) throws InvalidCharacterException{ public Columnar(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols, boolean removePadding) throws InvalidCharacterException{
this.preserveCapitals = preserveCapitals; this.preserveCapitals = preserveCapitals;
this.preserveWhitespace = preserveWhitespace; this.preserveWhitespace = preserveWhitespace;
@@ -485,6 +588,16 @@ public class Columnar{
setCharacterToAdd('x'); setCharacterToAdd('x');
reset(); reset();
} }
/**
* Constructs a new Columnar cipher instance with customizable settings and a specific padding character.
*
* @param preserveCapitals whether to preserve capitalization in the output
* @param preserveWhitespace whether to preserve whitespace in the output
* @param preserveSymbols whether to preserve symbols in the output
* @param removePadding whether to remove padding characters from the output
* @param characterToAdd the character to use for padding
* @throws InvalidCharacterException if the padding character is not a letter
*/
public Columnar(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols, boolean removePadding, char characterToAdd) throws InvalidCharacterException{ public Columnar(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols, boolean removePadding, char characterToAdd) throws InvalidCharacterException{
this.preserveCapitals = preserveCapitals; this.preserveCapitals = preserveCapitals;
this.preserveWhitespace = preserveWhitespace; this.preserveWhitespace = preserveWhitespace;
@@ -494,7 +607,15 @@ public class Columnar{
reset(); reset();
} }
//Encodes inputString using keyword and returns the result /**
* Encodes the given input string using the provided keyword.
*
* @param keyword the keyword used for encoding
* @param inputString the message to encode
* @return the encoded message
* @throws InvalidKeywordException if the keyword is invalid
* @throws InvalidInputException if the input string is invalid
*/
public String encode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{ public String encode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{
//Set the parameters //Set the parameters
reset(); reset();
@@ -505,7 +626,15 @@ public class Columnar{
encode(); encode();
return outputString; return outputString;
} }
//Encodes inputString using keyword and returns the result /**
* Decodes the given input string using the provided keyword.
*
* @param keyword the keyword used for decoding
* @param inputString the message to decode
* @return the decoded message
* @throws InvalidKeywordException if the keyword is invalid
* @throws InvalidInputException if the input string is invalid
*/
public String decode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{ public String decode(String keyword, String inputString) throws InvalidKeywordException, InvalidInputException{
//Set the parameters //Set the parameters
reset(); reset();
@@ -517,7 +646,9 @@ public class Columnar{
return outputString; return outputString;
} }
//Makes sure all variables are empty /**
* Resets all fields to their default values.
*/
public void reset(){ public void reset(){
logger.debug("Resetting fields"); logger.debug("Resetting fields");
@@ -528,13 +659,28 @@ public class Columnar{
charsAdded = 0; charsAdded = 0;
} }
//Getters //?Getters
/**
* Gets the current input string.
*
* @return the input string
*/
public String getInputString(){ public String getInputString(){
return inputString; return inputString;
} }
/**
* Gets the current output string.
*
* @return the output string
*/
public String getOutputString(){ public String getOutputString(){
return outputString; return outputString;
} }
/**
* Gets the current keyword.
*
* @return the keyword
*/
public String getKeyword(){ public String getKeyword(){
return keyword; return keyword;
} }

View File

@@ -1,7 +1,23 @@
//CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Hill.java //CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Hill.java
//Mattrixwv //Mattrixwv
// Created: 01-31-22 // Created: 01-31-22
//Modified: 05-04-23 //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.polysubstitution; package com.mattrixwv.cipherstream.polysubstitution;
@@ -18,20 +34,39 @@ import com.mattrixwv.matrix.exceptions.InvalidGeometryException;
import com.mattrixwv.matrix.exceptions.InvalidScalarException; import com.mattrixwv.matrix.exceptions.InvalidScalarException;
/**
* Implements the Hill cipher for encoding and decoding messages using matrix operations.
* <p>
* The Hill cipher is a polygraphic substitution cipher that uses linear algebra to encrypt and decrypt
* messages. It operates on blocks of text by representing them as vectors and applying matrix transformations.
* </p>
*/
public class Hill{ public class Hill{
private static final Logger logger = LoggerFactory.getLogger(Hill.class); private static final Logger logger = LoggerFactory.getLogger(Hill.class);
//Fields //?Fields
protected String inputString; //The message that needs to be encoded/decoded /** The message that needs to be encoded/decoded */
protected String outputString; //The encoded/decoded message protected String inputString;
protected char characterToAdd; //The keyword used to create the grid /** The encoded/decoded message */
protected ModMatrix key; //The matrix used perform the encoding/decoding protected String outputString;
//Settings /** The keyword used to create the grid */
protected boolean preserveCapitals; //Persist capitals in the output string protected char characterToAdd;
protected boolean preserveWhitespace; //Persist whitespace in the output string /** The matrix used perform the encoding/decoding */
protected boolean preserveSymbols; //Persist symbols in the output string protected ModMatrix key;
//?Settings
/** Persist capitals in the output string */
protected boolean preserveCapitals;
/** Persist whitespace in the output string */
protected boolean preserveWhitespace;
/** Persist symbols in the output string */
protected boolean preserveSymbols;
//Validate and set the key /**
* Sets the key matrix for the Hill cipher after validating it.
*
* @param key the matrix to be used for encoding/decoding
* @throws InvalidKeyException if the key is not a square matrix, or does not have an inverse modulo 26
*/
protected void setKey(ModMatrix key) throws InvalidKeyException{ protected void setKey(ModMatrix key) throws InvalidKeyException{
logger.debug("Setting key"); logger.debug("Setting key");
@@ -60,7 +95,13 @@ public class Hill{
logger.debug("key\n{}", key); logger.debug("key\n{}", key);
this.key = new ModMatrix(key); this.key = new ModMatrix(key);
} }
//Validate and set the input string /**
* Prepares and validates the input string for encoding by removing unwanted characters
* and ensuring the length is appropriate.
*
* @param inputString the message to be encoded
* @throws InvalidInputException if the input is null, blank, or its length is not a multiple of the matrix size
*/
protected void setInputStringEncode(String inputString) throws InvalidInputException{ protected void setInputStringEncode(String inputString) throws InvalidInputException{
logger.debug("Setting input string for encoding"); logger.debug("Setting input string for encoding");
@@ -111,6 +152,13 @@ public class Hill{
throw new InvalidInputException("Input cannot be blank"); throw new InvalidInputException("Input cannot be blank");
} }
} }
/**
* Prepares and validates the input string for decoding by removing unwanted characters
* and ensuring the length is appropriate.
*
* @param inputString the message to be decoded
* @throws InvalidInputException if the input is null, blank, or its length is not a multiple of the matrix size
*/
protected void setInputStringDecode(String inputString) throws InvalidInputException{ protected void setInputStringDecode(String inputString) throws InvalidInputException{
logger.debug("Setting input string for decoding"); logger.debug("Setting input string for decoding");
@@ -145,7 +193,11 @@ public class Hill{
throw new InvalidInputException("Length of input string must be a multiple of the number of rows in the key"); throw new InvalidInputException("Length of input string must be a multiple of the number of rows in the key");
} }
} }
//Get a perfectly clean copy of input string /**
* Returns a clean version of the input string with only uppercase letters.
*
* @return the cleaned input string
*/
protected String getCleanInputString(){ protected String getCleanInputString(){
logger.debug("Cleaning inputString"); logger.debug("Cleaning inputString");
@@ -154,7 +206,12 @@ public class Hill{
return cleanInputString; return cleanInputString;
} }
//Validate and set character to add /**
* Sets the character used for padding the input string.
*
* @param characterToAdd the character to be used for padding
* @throws InvalidCharacterException if the character is not a letter
*/
protected void setCharacterToAdd(char characterToAdd) throws InvalidCharacterException{ protected void setCharacterToAdd(char characterToAdd) throws InvalidCharacterException{
logger.debug("Setting character to add {}", characterToAdd); logger.debug("Setting character to add {}", characterToAdd);
@@ -173,7 +230,11 @@ public class Hill{
logger.debug("Cleaned character {}", characterToAdd); logger.debug("Cleaned character {}", characterToAdd);
this.characterToAdd = characterToAdd; this.characterToAdd = characterToAdd;
} }
//Add capitalization, whitespace, and symbols to the output based on the input /**
* Restores capitalization, whitespace, and symbols to the output string based on the original input string.
*
* @return the polished output string
*/
protected String polishOutputString(){ protected String polishOutputString(){
logger.debug("Polishing output string"); logger.debug("Polishing output string");
@@ -203,7 +264,11 @@ public class Hill{
logger.debug("Polished string '{}'", cleanString); logger.debug("Polished string '{}'", cleanString);
return cleanString; return cleanString;
} }
//Get vectors representing the input string /**
* Converts the cleaned input string into a list of column vectors based on the key matrix size.
*
* @return a list of vectors representing the input string
*/
protected ArrayList<ModMatrix> getInputVectors(){ protected ArrayList<ModMatrix> getInputVectors(){
logger.debug("Generating input vectors"); logger.debug("Generating input vectors");
@@ -237,7 +302,12 @@ public class Hill{
//Return the array of vectors //Return the array of vectors
return vectors; return vectors;
} }
//Get the string represented by the vectors that were passed in /**
* Converts a list of vectors back into a string representation.
*
* @param outputVectors the list of vectors to be converted
* @return the resulting string
*/
protected String getOutputFromVectors(ArrayList<ModMatrix> outputVectors){ protected String getOutputFromVectors(ArrayList<ModMatrix> outputVectors){
logger.debug("Turning vectors into a string"); logger.debug("Turning vectors into a string");
@@ -257,7 +327,9 @@ public class Hill{
logger.debug("Converted string '{}'", convertedString); logger.debug("Converted string '{}'", convertedString);
return convertedString; return convertedString;
} }
//Encode inputString and store the value in outputString /**
* Encodes the input string using the provided key matrix and stores the result in outputString.
*/
protected void encode(){ protected void encode(){
logger.debug("Encoding"); logger.debug("Encoding");
@@ -281,7 +353,9 @@ public class Hill{
//Add the extra characters back to the output and remove the added characters //Add the extra characters back to the output and remove the added characters
outputString = polishOutputString(); outputString = polishOutputString();
} }
//Decode inputString and store the value in outputString /**
* Decodes the input string using the provided key matrix and stores the result in outputString.
*/
protected void decode(){ protected void decode(){
logger.debug("Decoding"); logger.debug("Decoding");
@@ -308,7 +382,12 @@ public class Hill{
outputString = polishOutputString(); outputString = polishOutputString();
} }
//Constructors //?Constructors
/**
* Default constructor initializing the cipher with default settings.
*
* @throws InvalidCharacterException if the default padding character is invalid
*/
public Hill() throws InvalidCharacterException{ public Hill() throws InvalidCharacterException{
preserveCapitals = false; preserveCapitals = false;
preserveWhitespace = false; preserveWhitespace = false;
@@ -316,6 +395,14 @@ public class Hill{
setCharacterToAdd('x'); setCharacterToAdd('x');
reset(); reset();
} }
/**
* Constructor initializing the cipher with specified settings.
*
* @param preserveCapitals if true, preserves capitals in the output string
* @param preserveWhitespace if true, preserves whitespace in the output string
* @param preserveSymbols if true, preserves symbols in the output string
* @throws InvalidCharacterException if the default padding character is invalid
*/
public Hill(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols) throws InvalidCharacterException{ public Hill(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols) throws InvalidCharacterException{
this.preserveCapitals = preserveCapitals; this.preserveCapitals = preserveCapitals;
this.preserveWhitespace = preserveWhitespace; this.preserveWhitespace = preserveWhitespace;
@@ -323,6 +410,15 @@ public class Hill{
setCharacterToAdd('x'); setCharacterToAdd('x');
reset(); reset();
} }
/**
* Constructor initializing the cipher with specified settings and padding character.
*
* @param preserveCapitals if true, preserves capitals in the output string
* @param preserveWhitespace if true, preserves whitespace in the output string
* @param preserveSymbols if true, preserves symbols in the output string
* @param characterToAdd the character to use for padding
* @throws InvalidCharacterException if the padding character is invalid
*/
public Hill(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols, char characterToAdd) throws InvalidCharacterException{ public Hill(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols, char characterToAdd) throws InvalidCharacterException{
this.preserveCapitals = preserveCapitals; this.preserveCapitals = preserveCapitals;
this.preserveWhitespace = preserveWhitespace; this.preserveWhitespace = preserveWhitespace;
@@ -331,20 +427,54 @@ public class Hill{
reset(); reset();
} }
//Encode inputString using the provided key /**
* Encodes the input string using the provided key matrix and returns the encoded string.
*
* @param key the matrix to use for encoding
* @param inputString the message to encode
* @return the encoded message
* @throws InvalidKeyException if the key is invalid
* @throws InvalidInputException if the input is invalid
*/
public String encode(int[][] key, String inputString) throws InvalidKeyException, InvalidInputException{ public String encode(int[][] key, String inputString) throws InvalidKeyException, InvalidInputException{
return encode(new ModMatrix(key, 26), inputString); return encode(new ModMatrix(key, 26), inputString);
} }
/**
* Encodes the input string using the provided key matrix and returns the encoded string.
*
* @param key the matrix to use for encoding
* @param inputString the message to encode
* @return the encoded message
* @throws InvalidKeyException if the key is invalid
* @throws InvalidInputException if the input is invalid
*/
public String encode(ModMatrix key, String inputString) throws InvalidKeyException, InvalidInputException{ public String encode(ModMatrix key, String inputString) throws InvalidKeyException, InvalidInputException{
setKey(key); setKey(key);
setInputStringEncode(inputString); setInputStringEncode(inputString);
encode(); encode();
return outputString; return outputString;
} }
//Decode inputString using the provided key /**
* Decodes the input string using the provided key matrix and returns the decoded string.
*
* @param key the matrix to use for decoding
* @param inputString the message to decode
* @return the decoded message
* @throws InvalidKeyException if the key is invalid
* @throws InvalidInputException if the input is invalid
*/
public String decode(int[][] key, String inputString) throws InvalidKeyException, InvalidInputException{ public String decode(int[][] key, String inputString) throws InvalidKeyException, InvalidInputException{
return decode(new ModMatrix(key, 26), inputString); return decode(new ModMatrix(key, 26), inputString);
} }
/**
* Decodes the input string using the provided key matrix and returns the decoded string.
*
* @param key the matrix to use for decoding
* @param inputString the message to decode
* @return the decoded message
* @throws InvalidKeyException if the key is invalid
* @throws InvalidInputException if the input is invalid
*/
public String decode(ModMatrix key, String inputString) throws InvalidKeyException, InvalidInputException{ public String decode(ModMatrix key, String inputString) throws InvalidKeyException, InvalidInputException{
setKey(key); setKey(key);
setInputStringDecode(inputString); setInputStringDecode(inputString);
@@ -352,7 +482,9 @@ public class Hill{
return outputString; return outputString;
} }
//Makes sure all variables are empty /**
* Resets the Hill cipher by clearing all variables and setting the key to an empty matrix.
*/
public void reset(){ public void reset(){
logger.debug("Resetting fields"); logger.debug("Resetting fields");
@@ -361,13 +493,28 @@ public class Hill{
key = new ModMatrix(26); key = new ModMatrix(26);
} }
//Getters //?Getters
/**
* Returns the input string.
*
* @return the input string
*/
public String getInputString(){ public String getInputString(){
return inputString; return inputString;
} }
/**
* Returns the output string.
*
* @return the output string
*/
public String getOutputString(){ public String getOutputString(){
return outputString; return outputString;
} }
/**
* Returns the key matrix used for encoding or decoding.
*
* @return the key matrix
*/
public ModMatrix getKey(){ public ModMatrix getKey(){
return key; return key;
} }

View File

@@ -1,7 +1,23 @@
//CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/polysubstitution/LargePolybiusSquare.java //CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/polysubstitution/LargePolybiusSquare.java
//Mattrixwv //Mattrixwv
// Created: 04-21-23 // Created: 04-21-23
// Modified: 05-04-23 // 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.polysubstitution; package com.mattrixwv.cipherstream.polysubstitution;
@@ -15,11 +31,18 @@ import com.mattrixwv.cipherstream.exceptions.InvalidInputException;
import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException; import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException;
/**
* Represents the Polybius square cipher encryption and decryption.
* The Polybius square cipher is a classical encryption method that uses a 6x6 grid
* to encode and decode messages based on the positions of letters and numbers in the grid.
*/
public class LargePolybiusSquare extends PolybiusSquare{ public class LargePolybiusSquare extends PolybiusSquare{
private static final Logger logger = LoggerFactory.getLogger(LargePolybiusSquare.class); private static final Logger logger = LoggerFactory.getLogger(LargePolybiusSquare.class);
//Create the grid from the keyword /**
* Creates the grid from the keyword.
*/
@Override @Override
protected void createGrid(){ protected void createGrid(){
logger.debug("Creating grid"); logger.debug("Creating grid");
@@ -31,7 +54,13 @@ public class LargePolybiusSquare extends PolybiusSquare{
} }
} }
} }
//Strips invalid characters from the string that needs encoded/decoded /**
* Strips invalid characters from the string that needs encoding/decoding.
*
* @param inputString the input string to be cleaned
* @throws InvalidCharacterException if an invalid character is found
* @throws InvalidInputException if the input string is invalid
*/
@Override @Override
protected void setInputStringEncode(String inputString) throws InvalidCharacterException, InvalidInputException{ protected void setInputStringEncode(String inputString) throws InvalidCharacterException, InvalidInputException{
if(inputString == null){ if(inputString == null){
@@ -75,7 +104,11 @@ public class LargePolybiusSquare extends PolybiusSquare{
throw new InvalidInputException("Input must contain at least 1 letter"); throw new InvalidInputException("Input must contain at least 1 letter");
} }
} }
//Returns the input string ready for encoding /**
* Returns the input string ready for encoding.
*
* @return the prepared input string
*/
@Override @Override
protected String getPreparedInputStringEncode(){ protected String getPreparedInputStringEncode(){
logger.debug("Preparing input string for encoding"); logger.debug("Preparing input string for encoding");
@@ -87,7 +120,11 @@ public class LargePolybiusSquare extends PolybiusSquare{
return cleanString; return cleanString;
} }
//Strips invalid characters from the keyword and creates the grid /**
* Strips invalid characters from the keyword and creates the grid.
*
* @param keyword the keyword to be processed
*/
@Override @Override
protected void setKeyword(String keyword) throws InvalidKeywordException{ protected void setKeyword(String keyword) throws InvalidKeywordException{
if(keyword == null){ if(keyword == null){
@@ -116,7 +153,11 @@ public class LargePolybiusSquare extends PolybiusSquare{
//Create the grid from the sanitized keyword //Create the grid from the sanitized keyword
createGrid(); createGrid();
} }
//Adds characters that aren't letters to the output /**
* Adds characters that aren't letters to the output during encoding.
*
* @param cleanString the cleaned string to be formatted
*/
@Override @Override
protected void addCharactersToCleanStringEncode(String cleanString){ protected void addCharactersToCleanStringEncode(String cleanString){
logger.debug("Formatting output string"); logger.debug("Formatting output string");
@@ -144,6 +185,11 @@ public class LargePolybiusSquare extends PolybiusSquare{
outputString = fullOutput.toString(); outputString = fullOutput.toString();
logger.debug("Saving output string {}", outputString); logger.debug("Saving output string {}", outputString);
} }
/**
* Adds characters that aren't letters to the output during decoding.
*
* @param cleanString the cleaned string to be formatted
*/
@Override @Override
protected void addCharactersToCleanStringDecode(String cleanString){ protected void addCharactersToCleanStringDecode(String cleanString){
logger.debug("Formatting output string"); logger.debug("Formatting output string");
@@ -172,7 +218,9 @@ public class LargePolybiusSquare extends PolybiusSquare{
logger.debug("Saving output string {}", outputString); logger.debug("Saving output string {}", outputString);
} }
//Makes sure all variables are empty /**
* Resets all variables to their default values.
*/
@Override @Override
public void reset(){ public void reset(){
logger.debug("Resetting"); logger.debug("Resetting");
@@ -183,10 +231,22 @@ public class LargePolybiusSquare extends PolybiusSquare{
keyword = ""; keyword = "";
} }
//Constructors //?Constructors
/**
* Constructs a PolybiusSquare cipher instance with default settings.
*
* @throws InvalidCharacterException if default characters are invalid
*/
public LargePolybiusSquare() throws InvalidCharacterException{ public LargePolybiusSquare() throws InvalidCharacterException{
super(); super();
} }
/**
* Constructs a PolybiusSquare cipher instance with specified settings.
*
* @param preserveWhitespace whether to preserve whitespace
* @param preserveSymbols whether to preserve symbols
* @throws InvalidCharacterException if default characters are invalid
*/
public LargePolybiusSquare(boolean preserveWhitespace, boolean preserveSymbols) throws InvalidCharacterException{ public LargePolybiusSquare(boolean preserveWhitespace, boolean preserveSymbols) throws InvalidCharacterException{
super(preserveWhitespace, preserveSymbols); super(preserveWhitespace, preserveSymbols);
} }

View File

@@ -1,7 +1,23 @@
//CipherStreamJava/src/main/java/com/mattrixwv/CipherStreamJava/Morse.java //CipherStreamJava/src/main/java/com/mattrixwv/CipherStreamJava/Morse.java
//Mattrixwv //Mattrixwv
// Created: 07-28-21 // Created: 07-28-21
//Modified: 05-04-23 //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.polysubstitution; package com.mattrixwv.cipherstream.polysubstitution;
@@ -15,17 +31,28 @@ import org.slf4j.LoggerFactory;
import com.mattrixwv.cipherstream.exceptions.InvalidInputException; import com.mattrixwv.cipherstream.exceptions.InvalidInputException;
/**
* A class to handle encoding and decoding of Morse code.
* <p>
* This class provides methods to encode a string into Morse code and decode Morse code back into a string.
* It supports alphanumeric characters (A-Z, 0-9) and validates input to ensure it contains valid characters.
* </p>
*/
public class Morse{ public class Morse{
private static final Logger logger = LoggerFactory.getLogger(Morse.class); private static final Logger logger = LoggerFactory.getLogger(Morse.class);
//Code representations //?Code representations
/** Morse code representations for letters A-Z */
private static final String[] letters = { private static final String[] letters = {
".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", //A-L ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", //A-L
"--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--.." //M-Z "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--.." //M-Z
}; };
/** Morse code representations for digits 0-9 */
private static final String[] numbers = { private static final String[] numbers = {
"-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----." //0-9 "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----." //0-9
}; };
private static final Map<String, Character> map; //The map to help convert from Morse to letters and numbers /** The map to help convert from Morse to letters and numbers */
private static final Map<String, Character> map;
/** Initialize the Morse Code map */
static{ static{
//Setup the map //Setup the map
map = new HashMap<>(); map = new HashMap<>();
@@ -38,12 +65,22 @@ public class Morse{
map.put(number, (char)('0' + cnt)); map.put(number, (char)('0' + cnt));
} }
} }
//Fields //?Fields
protected String inputString; //The string that needs encoded/decoded /** The string that needs encoded/decoded */
protected String outputString; //The encoded/decoded message protected String inputString;
/** The encoded/decoded message */
protected String outputString;
//Validate and set the input string for encoding /**
* Validates and prepares the input string for encoding.
* <p>
* This method converts the input string to uppercase, removes all non-alphanumeric characters, and stores the cleaned string.
* </p>
*
* @param inputString the string to be encoded
* @throws InvalidInputException if the input string is null or contains invalid characters
*/
protected void setInputStringEncode(String inputString){ protected void setInputStringEncode(String inputString){
logger.debug("Setting input string for encoding '{}'", inputString); logger.debug("Setting input string for encoding '{}'", inputString);
@@ -70,7 +107,15 @@ public class Morse{
//Save the input //Save the input
this.inputString = inputString; this.inputString = inputString;
} }
//Validate and set the input string for decoding /**
* Validates and prepares the input string for decoding.
* <p>
* This method ensures that the input string contains only valid Morse code characters (dots, dashes, and spaces).
* </p>
*
* @param inputString the Morse code string to be decoded
* @throws InvalidInputException if the input string is null or contains invalid Morse code characters
*/
protected void setInputStringDecode(String inputString){ protected void setInputStringDecode(String inputString){
logger.debug("Setting input string for decoding '{}'", inputString); logger.debug("Setting input string for decoding '{}'", inputString);
@@ -94,7 +139,14 @@ public class Morse{
logger.debug("Saving"); logger.debug("Saving");
this.inputString = inputString; this.inputString = inputString;
} }
//Encodes the inputString and stores the result in outputString /**
* Encodes the {@code inputString} into Morse code.
* <p>
* This method converts each alphanumeric character in the input string to its Morse code representation and stores the result.
* </p>
*
* @throws InvalidInputException if the input string contains characters that cannot be encoded
*/
protected void encode(){ protected void encode(){
logger.debug("Encoding"); logger.debug("Encoding");
@@ -123,7 +175,14 @@ public class Morse{
this.outputString = output.toString(); this.outputString = output.toString();
logger.debug("Saving encoded string '{}'", outputString); logger.debug("Saving encoded string '{}'", outputString);
} }
//Decodes the inputString and stores the result in outputString /**
* Decodes the {@code inputString} from Morse code to plain text.
* <p>
* This method converts each Morse code sequence in the input string back to its corresponding alphanumeric character.
* </p>
*
* @throws InvalidInputException if the input string contains invalid Morse code sequences
*/
protected void decode(){ protected void decode(){
logger.debug("Decoding"); logger.debug("Decoding");
@@ -149,19 +208,40 @@ public class Morse{
} }
//Constructor //?Constructor
/**
* Resets the class by clearing the input and output strings.
*/
public Morse(){ public Morse(){
reset(); reset();
} }
//Sets the inputString and encodes the message /**
* Encodes the given input string into Morse code.
* <p>
* This method validates the input string, encodes it, and returns the Morse code representation.
* </p>
*
* @param inputString the string to be encoded
* @return the Morse code representation of the input string
* @throws InvalidInputException if the input string contains invalid characters
*/
public String encode(String inputString){ public String encode(String inputString){
setInputStringEncode(inputString); setInputStringEncode(inputString);
encode(); encode();
return outputString; return outputString;
} }
//Sets the inputString and decodes the message /**
* Decodes the given Morse code string into plain text.
* <p>
* This method validates the Morse code input, decodes it, and returns the plain text representation.
* </p>
*
* @param inputString the Morse code string to be decoded
* @return the decoded plain text representation
* @throws InvalidInputException if the input string contains invalid Morse code sequences
*/
public String decode(String inputString){ public String decode(String inputString){
setInputStringDecode(inputString); setInputStringDecode(inputString);
decode(); decode();
@@ -169,14 +249,26 @@ public class Morse{
} }
//Getters //?Getters
/**
* Returns the current input string.
*
* @return the current input string
*/
public String getInputString(){ public String getInputString(){
return inputString; return inputString;
} }
/**
* Returns the current output string.
*
* @return the current output string
*/
public String getOutputString(){ public String getOutputString(){
return outputString; return outputString;
} }
//Makes sure all variables are empty /**
* Resets the internal fields to their default values.
*/
public void reset(){ public void reset(){
logger.debug("Resetting"); logger.debug("Resetting");

View File

@@ -1,7 +1,23 @@
//CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Playfair.java //CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Playfair.java
//Matthew Ellison //Matthew Ellison
// Created: 07-30-21 // Created: 07-30-21
//Modified: 05-04-23 //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.polysubstitution; package com.mattrixwv.cipherstream.polysubstitution;
@@ -15,40 +31,77 @@ import com.mattrixwv.cipherstream.exceptions.InvalidInputException;
import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException; import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException;
/**
* Represents the Playfair cipher encryption and decryption.
* The Playfair cipher is a digraph substitution cipher that encrypts pairs of letters.
*/
public class Playfair{ public class Playfair{
private static final Logger logger = LoggerFactory.getLogger(Playfair.class); private static final Logger logger = LoggerFactory.getLogger(Playfair.class);
//A class representing the location of a character in the grid /** A class representing the location of a character in the grid */
protected class CharLocation{ protected class CharLocation{
/** The x location in the grid */
protected int x; protected int x;
/** The y location in the grid */
protected int y; protected int y;
/**
* Constructs a CharLocation with the specified x and y coordinates.
*
* @param x the x-coordinate of the character's location
* @param y the y-coordinate of the character's location
*/
public CharLocation(int x, int y){ public CharLocation(int x, int y){
this.x = x; this.x = x;
this.y = y; this.y = y;
} }
/**
* Returns the x-coordinate of the character's location.
*
* @return the x-coordinate
*/
public int getX(){ public int getX(){
return x; return x;
} }
/**
* Returns the y-coordinate of the character's location.
*
* @return the y-coordinate
*/
public int getY(){ public int getY(){
return y; return y;
} }
} }
//Fields //?Fields
protected String inputString; //The message that needs to be encoded/decoded /** The message that needs to be encoded/decoded */
protected String outputString; //The encoded/decoded message protected String inputString;
protected String keyword; //The keyword used to create the grid /** The encoded/decoded message */
protected char[][] grid; //The grid used to encode/decode the message protected String outputString;
protected char replaced; //The letter that will need to be replaced in the grid and any input string or keyword /** The keyword used to create the grid */
protected char replacer; //The letter that replaced replaced in the input string or keyword protected String 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 /** The grid used to encode/decode the message */
//Settings protected char[][] grid;
protected boolean preserveCapitals; //Persist captials in the output string /** The letter that will need to be replaced in the grid and any input string or keyword */
protected boolean preserveWhitespace; //Persist whitespace in the output string protected char replaced;
protected boolean preserveSymbols; //Persist symbols in the output string /** The letter that replaced replaced in the input string or keyword */
protected char replacer;
/** The letter that will be placed between double letters in the input string if necessary or to make the string length even */
protected char doubled;
//?Settings
/** Persist capitals in the output string */
protected boolean preserveCapitals;
/** Persist whitespace in the output string */
protected boolean preserveWhitespace;
/** Persist symbols in the output string */
protected boolean preserveSymbols;
//Set the doubled character /**
* Sets the doubled character.
*
* @param doubled the character to be used as the doubled character
* @throws InvalidCharacterException if the character is not a letter or is invalid
*/
protected void setDoubled(char doubled) throws InvalidCharacterException{ protected void setDoubled(char doubled) throws InvalidCharacterException{
logger.debug("Setting doubled"); logger.debug("Setting doubled");
logger.debug("Original character {}", doubled); logger.debug("Original character {}", doubled);
@@ -80,7 +133,12 @@ public class Playfair{
logger.debug("Setting doubled to {}", doubled); logger.debug("Setting doubled to {}", doubled);
this.doubled = doubled; this.doubled = doubled;
} }
//Set the replacer character /**
* Sets the replacer character.
*
* @param replacer the character to replace the replaced character
* @throws InvalidCharacterException if the character is not a letter or is invalid
*/
protected void setReplacer(char replacer) throws InvalidCharacterException{ protected void setReplacer(char replacer) throws InvalidCharacterException{
logger.debug("Setting replacer"); logger.debug("Setting replacer");
logger.debug("Original character {}", replacer); logger.debug("Original character {}", replacer);
@@ -112,7 +170,12 @@ public class Playfair{
logger.debug("Setting replacer to {}", replacer); logger.debug("Setting replacer to {}", replacer);
this.replacer = replacer; this.replacer = replacer;
} }
//Set the replaced character /**
* Sets the replaced character.
*
* @param replaced the character to be replaced
* @throws InvalidCharacterException if the character is not a letter or is invalid
*/
protected void setReplaced(char replaced) throws InvalidCharacterException{ protected void setReplaced(char replaced) throws InvalidCharacterException{
logger.debug("Setting replaced"); logger.debug("Setting replaced");
logger.debug("Original character {}", replaced); logger.debug("Original character {}", replaced);
@@ -144,7 +207,9 @@ public class Playfair{
logger.debug("Setting replaced to {}", replaced); logger.debug("Setting replaced to {}", replaced);
this.replaced = replaced; this.replaced = replaced;
} }
//Create the grid from the keyword /**
* Creates the grid from the keyword.
*/
protected void createGrid(){ protected void createGrid(){
logger.debug("Creating grid from keyword"); logger.debug("Creating grid from keyword");
@@ -158,7 +223,14 @@ public class Playfair{
logger.debug("Grid\n{}", getGrid()); logger.debug("Grid\n{}", getGrid());
} }
//Strips invalid characters from the string that needs encoded/decoded /**
* Strips invalid characters from the string that needs encoding/decoding.
*
* @param inputString the input string to be cleaned
* @param encoding true if encoding, false if decoding
* @throws InvalidCharacterException if an invalid character is found
* @throws InvalidInputException if the input string is invalid
*/
protected void setInputString(String inputString, boolean encoding) throws InvalidCharacterException, InvalidInputException{ protected void setInputString(String inputString, boolean encoding) throws InvalidCharacterException, InvalidInputException{
logger.debug("Setting input string"); logger.debug("Setting input string");
@@ -214,6 +286,11 @@ public class Playfair{
throw new InvalidInputException("Input must have at least 1 letter"); throw new InvalidInputException("Input must have at least 1 letter");
} }
} }
/**
* Cleans up the input string for encoding.
*
* @param inputString the input string to be cleaned
*/
protected void setInputStringEncode(String inputString){ protected void setInputStringEncode(String inputString){
logger.debug("Cleaning up input string for encoding"); logger.debug("Cleaning up input string for encoding");
@@ -286,7 +363,11 @@ public class Playfair{
this.inputString = cleanInput.toString(); this.inputString = cleanInput.toString();
logger.debug("Cleaned input string '{}'", this.inputString); logger.debug("Cleaned input string '{}'", this.inputString);
} }
//Returns the input string ready for encoding /**
* Returns the input string ready for encoding.
*
* @return the prepared input string
*/
protected String getPreparedInputString(){ protected String getPreparedInputString(){
logger.debug("Getting input string ready for encoding"); logger.debug("Getting input string ready for encoding");
@@ -297,7 +378,12 @@ public class Playfair{
return cleanString; return cleanString;
} }
//Strips invalid characters from the keyword and creates the grid /**
* Strips invalid characters from the keyword and creates the grid.
*
* @param keyword the keyword to be processed
* @throws InvalidKeywordException if the keyword is invalid
*/
protected void setKeyword(String keyword) throws InvalidKeywordException{ protected void setKeyword(String keyword) throws InvalidKeywordException{
logger.debug("Setting keyword"); logger.debug("Setting keyword");
@@ -333,7 +419,13 @@ public class Playfair{
//Create the grid from the sanitized keyword //Create the grid from the sanitized keyword
createGrid(); createGrid();
} }
//Returns the location of the given character in the grid /**
* Returns the location of the given character in the grid.
*
* @param letter the character whose location is to be found
* @return the location of the character in the grid
* @throws InvalidInputException if the character is not found in the grid
*/
protected CharLocation findChar(char letter) throws InvalidInputException{ protected CharLocation findChar(char letter) throws InvalidInputException{
logger.debug("Finding character in grid {}", letter); logger.debug("Finding character in grid {}", letter);
@@ -350,7 +442,13 @@ public class Playfair{
//If it was not found something went wrong //If it was not found something went wrong
throw new InvalidInputException("The character '" + letter + "' was not found in the grid"); 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 /**
* Returns the character in the grid at the specified coordinates.
*
* @param x the x-coordinate
* @param y the y-coordinate
* @return the character at the specified coordinates
*/
protected char getGridChar(int x, int y){ protected char getGridChar(int x, int y){
logger.debug("Getting character from grid[{}][{}]", x, y); logger.debug("Getting character from grid[{}][{}]", x, y);
@@ -365,7 +463,11 @@ public class Playfair{
logger.debug("Character {}", letter); logger.debug("Character {}", letter);
return letter; return letter;
} }
//Adds characters that aren't letters to the output /**
* Adds characters that aren't letters to the output.
*
* @param cleanString the cleaned string to be formatted
*/
protected void addCharactersToCleanString(String cleanString){ protected void addCharactersToCleanString(String cleanString){
logger.debug("Formatting output string"); logger.debug("Formatting output string");
@@ -394,7 +496,11 @@ public class Playfair{
outputString = fullOutput.toString(); outputString = fullOutput.toString();
logger.debug("Formatted output '{}'", outputString); logger.debug("Formatted output '{}'", outputString);
} }
//Encodes inputString using the Playfair cipher and stores the result in outputString /**
* Encodes the input string using the Playfair cipher and stores the result in the output string.
*
* @throws InvalidInputException if the input string is invalid
*/
protected void encode() throws InvalidInputException{ protected void encode() throws InvalidInputException{
logger.debug("Encoding"); logger.debug("Encoding");
@@ -438,7 +544,11 @@ public class Playfair{
//Add other characters to the output string //Add other characters to the output string
addCharactersToCleanString(output.toString()); addCharactersToCleanString(output.toString());
} }
//Decodes inputString using the Playfair cipher and stores the result in outputString /**
* Decodes the input string using the Playfair cipher and stores the result in the output string.
*
* @throws InvalidInputException if the input string is invalid
*/
protected void decode() throws InvalidInputException{ protected void decode() throws InvalidInputException{
logger.debug("Decoding"); logger.debug("Decoding");
@@ -483,7 +593,12 @@ public class Playfair{
addCharactersToCleanString(output.toString()); addCharactersToCleanString(output.toString());
} }
//Constructor //?Constructor
/**
* Constructs a Playfair cipher instance with default settings.
*
* @throws InvalidCharacterException if default characters are invalid
*/
public Playfair() throws InvalidCharacterException{ public Playfair() throws InvalidCharacterException{
reset(); reset();
preserveCapitals = false; preserveCapitals = false;
@@ -493,6 +608,14 @@ public class Playfair{
setReplacer('i'); setReplacer('i');
setDoubled('x'); setDoubled('x');
} }
/**
* Constructs a Playfair cipher instance with specified settings.
*
* @param preserveCapitals whether to preserve capital letters
* @param preserveWhitespace whether to preserve whitespace
* @param preserveSymbols whether to preserve symbols
* @throws InvalidCharacterException if default characters are invalid
*/
public Playfair(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols) throws InvalidCharacterException{ public Playfair(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols) throws InvalidCharacterException{
reset(); reset();
this.preserveCapitals = preserveCapitals; this.preserveCapitals = preserveCapitals;
@@ -502,6 +625,17 @@ public class Playfair{
setReplacer('i'); setReplacer('i');
setDoubled('x'); setDoubled('x');
} }
/**
* Constructs a Playfair cipher instance with specified settings and characters.
*
* @param preserveCapitals whether to preserve capital letters
* @param preserveWhitespace whether to preserve whitespace
* @param preserveSymbols whether to preserve symbols
* @param replaced the character to be replaced
* @param replacer the character to replace the replaced character
* @param doubled the character to use for doubled letters
* @throws InvalidCharacterException if any character is invalid
*/
public Playfair(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols, char replaced, char replacer, char doubled) throws InvalidCharacterException{ public Playfair(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols, char replaced, char replacer, char doubled) throws InvalidCharacterException{
reset(); reset();
this.preserveCapitals = preserveCapitals; this.preserveCapitals = preserveCapitals;
@@ -512,7 +646,15 @@ public class Playfair{
setDoubled(doubled); setDoubled(doubled);
} }
//Sets the keyword and inputString and encodes the message /**
* Sets the keyword and input string and encodes the message.
*
* @param keyword the keyword for the cipher
* @param input the message to encode
* @return the encoded message
* @throws InvalidCharacterException if any character is invalid
* @throws InvalidInputException if the input string is invalid
*/
public String encode(String keyword, String input) throws InvalidCharacterException, InvalidInputException{ public String encode(String keyword, String input) throws InvalidCharacterException, InvalidInputException{
reset(); reset();
setKeyword(keyword); setKeyword(keyword);
@@ -520,7 +662,15 @@ public class Playfair{
encode(); encode();
return outputString; return outputString;
} }
//Sets the keyword and inputString and decodes the message /**
* Sets the keyword and input string and decodes the message.
*
* @param keyword the keyword for the cipher
* @param input the encoded message to decode
* @return the decoded message
* @throws InvalidCharacterException if any character is invalid
* @throws InvalidInputException if the input string is invalid
*/
public String decode(String keyword, String input) throws InvalidCharacterException, InvalidInputException{ public String decode(String keyword, String input) throws InvalidCharacterException, InvalidInputException{
reset(); reset();
setKeyword(keyword); setKeyword(keyword);
@@ -529,7 +679,9 @@ public class Playfair{
return outputString; return outputString;
} }
//Makes sure all variables are empty /**
* Resets all variables to their default values.
*/
public void reset(){ public void reset(){
logger.debug("Resetting fields"); logger.debug("Resetting fields");
@@ -538,25 +690,60 @@ public class Playfair{
outputString = ""; outputString = "";
keyword = ""; keyword = "";
} }
//Getters //?Getters
/**
* Returns the replaced character.
*
* @return the replaced character
*/
public char getReplaced(){ public char getReplaced(){
return replaced; return replaced;
} }
/**
* Returns the replacer character.
*
* @return the replacer character
*/
public char getReplacer(){ public char getReplacer(){
return replacer; return replacer;
} }
/**
* Returns the doubled character.
*
* @return the doubled character
*/
public char getDoubled(){ public char getDoubled(){
return doubled; return doubled;
} }
/**
* Returns the keyword used in the cipher.
*
* @return the keyword
*/
public String getKeyword(){ public String getKeyword(){
return keyword; return keyword;
} }
/**
* Returns the input string that was set for encoding/decoding.
*
* @return the input string
*/
public String getInputString(){ public String getInputString(){
return inputString; return inputString;
} }
/**
* Returns the output string after encoding/decoding.
*
* @return the output string
*/
public String getOutputString(){ public String getOutputString(){
return outputString; return outputString;
} }
/**
* Return the grid used for encoding/decoding.
*
* @return the grid as a string
*/
public String getGrid(){ public String getGrid(){
logger.debug("Creating string from grid"); logger.debug("Creating string from grid");

View File

@@ -1,7 +1,23 @@
//CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/polysubstitution/PolybiusSquare.java //CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/polysubstitution/PolybiusSquare.java
//Mattrixwv //Mattrixwv
// Created: 01-04-22 // Created: 01-04-22
//Modified: 05-04-23 //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.polysubstitution; package com.mattrixwv.cipherstream.polysubstitution;
@@ -15,38 +31,74 @@ import com.mattrixwv.cipherstream.exceptions.InvalidInputException;
import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException; import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException;
/**
* Represents the Polybius square cipher encryption and decryption.
* The Polybius square cipher is a classical encryption method that uses a 5x5 grid
* to encode and decode messages based on the positions of letters in the grid.
*/
public class PolybiusSquare{ public class PolybiusSquare{
private static final Logger logger = LoggerFactory.getLogger(PolybiusSquare.class); private static final Logger logger = LoggerFactory.getLogger(PolybiusSquare.class);
//A class representing the location of a character in the grid /** A class representing the location of a character in the grid */
protected class CharLocation{ protected class CharLocation{
/** The x location in the grid */
private int x; private int x;
/** The y location in the grid */
private int y; private int y;
/**
* Constructs a CharLocation with the specified x and y coordinates.
*
* @param x the x-coordinate of the character's location
* @param y the y-coordinate of the character's location
*/
public CharLocation(int x, int y){ public CharLocation(int x, int y){
this.x = x; this.x = x;
this.y = y; this.y = y;
} }
/**
* Returns the x-coordinate of the character's location.
*
* @return the x-coordinate
*/
public int getX(){ public int getX(){
return x; return x;
} }
/**
* Returns the y-coordinate of the character's location.
*
* @return the y-coordinate
*/
public int getY(){ public int getY(){
return y; return y;
} }
} }
//Fields //?Fields
protected String inputString; //The message that needs to be encoded/decoded /** The message that needs to be encoded/decoded */
protected String outputString; //The encoded/decoded message protected String inputString;
protected String keyword; //The keyword used to create the grid /** The encoded/decoded message */
protected char[][] grid; //The grid used to encode/decode the message protected String outputString;
protected char replaced; //The letter that will need to be replaced in the grid and any input string or keyword /** The keyword used to create the grid */
protected char replacer; //The letter that replaces replaced in the input string or keyword protected String keyword;
//Settings /** The grid used to encode/decode the message */
protected boolean preserveWhitespace; //Persist whitespace in the output string protected char[][] grid;
protected boolean preserveSymbols; //Persist symbols in the output string /** The letter that will need to be replaced in the grid and any input string or keyword */
protected char replaced;
/** The letter that replaces replaced in the input string or keyword */
protected char replacer;
//?Settings
/** Persist whitespace in the output string */
protected boolean preserveWhitespace;
/** Persist symbols in the output string */
protected boolean preserveSymbols;
//Setting the character to be replaced /**
* Sets the replaced character.
*
* @param replaced the character to be replaced
* @throws InvalidCharacterException if the character is not a letter or is invalid
*/
protected void setReplaced(char replaced) throws InvalidCharacterException{ protected void setReplaced(char replaced) throws InvalidCharacterException{
logger.debug("Setting replaced"); logger.debug("Setting replaced");
logger.debug("Original character {}", replaced); logger.debug("Original character {}", replaced);
@@ -63,7 +115,12 @@ public class PolybiusSquare{
this.replaced = Character.toUpperCase(replaced); this.replaced = Character.toUpperCase(replaced);
logger.debug("Cleaned character {}", this.replaced); logger.debug("Cleaned character {}", this.replaced);
} }
//Setting the character that replaces replaced /**
* Sets the replacer character.
*
* @param replacer the character the replaces replaced
* @throws InvalidCharacterException if the character is not a letter or is invalid
*/
protected void setReplacer(char replacer) throws InvalidCharacterException{ protected void setReplacer(char replacer) throws InvalidCharacterException{
logger.debug("Setting replacer"); logger.debug("Setting replacer");
logger.debug("Original character {}", replacer); logger.debug("Original character {}", replacer);
@@ -80,7 +137,9 @@ public class PolybiusSquare{
this.replacer = Character.toUpperCase(replacer); this.replacer = Character.toUpperCase(replacer);
logger.debug("Cleaned character {}", this.replacer); logger.debug("Cleaned character {}", this.replacer);
} }
//Create the grid from the keyword /**
* Creates the grid from the keyword.
*/
protected void createGrid(){ protected void createGrid(){
logger.debug("Creating grid from keyword"); logger.debug("Creating grid from keyword");
@@ -93,7 +152,13 @@ public class PolybiusSquare{
logger.debug("Created grid\n{}", getGrid()); logger.debug("Created grid\n{}", getGrid());
} }
//Strips invalid characters from the string that needs encoded/decoded /**
* Strips invalid characters from the string that needs encoding/decoding.
*
* @param inputString the input string to be cleaned
* @throws InvalidCharacterException if an invalid character is found
* @throws InvalidInputException if the input string is invalid
*/
protected void setInputStringEncode(String inputString) throws InvalidCharacterException, InvalidInputException{ protected void setInputStringEncode(String inputString) throws InvalidCharacterException, InvalidInputException{
if(inputString == null){ if(inputString == null){
throw new InvalidInputException("Input cannot be null"); throw new InvalidInputException("Input cannot be null");
@@ -148,6 +213,13 @@ public class PolybiusSquare{
throw new InvalidInputException("Input must contain at least 1 letter"); throw new InvalidInputException("Input must contain at least 1 letter");
} }
} }
/**
* Strips invalid characters from the string that needs decoding.
*
* @param inputString the input string to be cleaned
* @throws InvalidCharacterException if an invalid character is found
* @throws InvalidInputException if the input string is invalid
*/
protected void setInputStringDecode(String inputString) throws InvalidCharacterException, InvalidInputException{ protected void setInputStringDecode(String inputString) throws InvalidCharacterException, InvalidInputException{
if(inputString == null){ if(inputString == null){
throw new InvalidInputException("Input cannot be null"); throw new InvalidInputException("Input cannot be null");
@@ -193,7 +265,11 @@ public class PolybiusSquare{
throw new InvalidInputException("Input must contain at least 1 letter"); throw new InvalidInputException("Input must contain at least 1 letter");
} }
} }
//Returns the input string ready for encoding /**
* Returns the input string ready for encoding.
*
* @return the prepared input string
*/
protected String getPreparedInputStringEncode(){ protected String getPreparedInputStringEncode(){
logger.debug("Preparing input string for encoding"); logger.debug("Preparing input string for encoding");
@@ -203,6 +279,11 @@ public class PolybiusSquare{
logger.debug("Prepared string '{}'", cleanString); logger.debug("Prepared string '{}'", cleanString);
return cleanString; return cleanString;
} }
/**
* Returns the input string ready for decoding.
*
* @return the prepared input string
*/
protected String getPreparedInputStringDecode(){ protected String getPreparedInputStringDecode(){
logger.debug("Preparing input string for decoding"); logger.debug("Preparing input string for decoding");
@@ -211,7 +292,11 @@ public class PolybiusSquare{
logger.debug("Prepared string '{}'", cleanString); logger.debug("Prepared string '{}'", cleanString);
return cleanString; return cleanString;
} }
//Strips invalid characters from the keyword and creates the grid /**
* Strips invalid characters from the keyword and creates the grid.
*
* @param keyword the keyword to be processed
*/
protected void setKeyword(String keyword){ protected void setKeyword(String keyword){
if(keyword == null){ if(keyword == null){
throw new InvalidKeywordException("Keyword cannot be null"); throw new InvalidKeywordException("Keyword cannot be null");
@@ -244,7 +329,13 @@ public class PolybiusSquare{
//Create the grid from the sanitized keyword //Create the grid from the sanitized keyword
createGrid(); createGrid();
} }
//Returns the location of the given charcter in the grid /**
* Returns the location of the given character in the grid.
*
* @param letter the character whose location is to be found
* @return the location of the character in the grid
* @throws InvalidInputException if the character is not found in the grid
*/
protected CharLocation findChar(char letter) throws InvalidInputException{ protected CharLocation findChar(char letter) throws InvalidInputException{
logger.debug("Finding {} in grid", letter); logger.debug("Finding {} in grid", letter);
@@ -260,7 +351,11 @@ public class PolybiusSquare{
//If it was not found something went wrong //If it was not found something went wrong
throw new InvalidInputException("The character '" + letter + "' was not found in the grid"); throw new InvalidInputException("The character '" + letter + "' was not found in the grid");
} }
//Adds characters that aren't letters to the output /**
* Adds characters that aren't letters to the output during encoding.
*
* @param cleanString the cleaned string to be formatted
*/
protected void addCharactersToCleanStringEncode(String cleanString){ protected void addCharactersToCleanStringEncode(String cleanString){
logger.debug("Formatting output string for encoding"); logger.debug("Formatting output string for encoding");
@@ -287,6 +382,11 @@ public class PolybiusSquare{
outputString = fullOutput.toString(); outputString = fullOutput.toString();
logger.debug("Formatted output '{}'", outputString); logger.debug("Formatted output '{}'", outputString);
} }
/**
* Adds characters that aren't letters to the output during decoding.
*
* @param cleanString the cleaned string to be formatted
*/
protected void addCharactersToCleanStringDecode(String cleanString){ protected void addCharactersToCleanStringDecode(String cleanString){
logger.debug("Formatting output string for decoding"); logger.debug("Formatting output string for decoding");
@@ -313,7 +413,11 @@ public class PolybiusSquare{
outputString = fullOutput.toString(); outputString = fullOutput.toString();
logger.debug("Formatted output '{}'", outputString); logger.debug("Formatted output '{}'", outputString);
} }
//Encodes inputString using the Playfair cipher and stores the result in outputString /**
* Encodes the input string using the Polybius cipher and stores the result in the output string.
*
* @throws InvalidInputException if the input string is invalid
*/
protected void encode() throws InvalidInputException{ protected void encode() throws InvalidInputException{
logger.debug("Encoding"); logger.debug("Encoding");
@@ -337,7 +441,11 @@ public class PolybiusSquare{
//Add other characters to the output string //Add other characters to the output string
addCharactersToCleanStringEncode(output.toString()); addCharactersToCleanStringEncode(output.toString());
} }
//Decodes inputString using the Playfair cipher and stores the result in outputString /**
* Decodes the input string using the Polybius cipher and stores the result in the output string.
*
* @throws InvalidInputException if the input string is invalid
*/
protected void decode(){ protected void decode(){
logger.debug("Decoding"); logger.debug("Decoding");
@@ -363,7 +471,12 @@ public class PolybiusSquare{
addCharactersToCleanStringDecode(output.toString()); addCharactersToCleanStringDecode(output.toString());
} }
//Constructors //?Constructors
/**
* Constructs a PolybiusSquare cipher instance with default settings.
*
* @throws InvalidCharacterException if default characters are invalid
*/
public PolybiusSquare() throws InvalidCharacterException{ public PolybiusSquare() throws InvalidCharacterException{
reset(); reset();
setReplaced('J'); setReplaced('J');
@@ -371,6 +484,13 @@ public class PolybiusSquare{
preserveWhitespace = false; preserveWhitespace = false;
preserveSymbols = false; preserveSymbols = false;
} }
/**
* Constructs a PolybiusSquare cipher instance with specified settings.
*
* @param preserveWhitespace whether to preserve whitespace
* @param preserveSymbols whether to preserve symbols
* @throws InvalidCharacterException if default characters are invalid
*/
public PolybiusSquare(boolean preserveWhitespace, boolean preserveSymbols) throws InvalidCharacterException{ public PolybiusSquare(boolean preserveWhitespace, boolean preserveSymbols) throws InvalidCharacterException{
reset(); reset();
setReplaced('J'); setReplaced('J');
@@ -378,6 +498,15 @@ public class PolybiusSquare{
this.preserveWhitespace = preserveWhitespace; this.preserveWhitespace = preserveWhitespace;
this.preserveSymbols = preserveSymbols; this.preserveSymbols = preserveSymbols;
} }
/**
* Constructs a PolybiusSquare cipher instance with specified settings and characters.
*
* @param preserveWhitespace whether to preserve whitespace
* @param preserveSymbols whether to preserve symbols
* @param replaced the character to be replaced
* @param replacer the character to replace the replaced character
* @throws InvalidCharacterException if any character is invalid
*/
public PolybiusSquare(boolean preserveWhitespace, boolean preserveSymbols, char replaced, char replacer) throws InvalidCharacterException{ public PolybiusSquare(boolean preserveWhitespace, boolean preserveSymbols, char replaced, char replacer) throws InvalidCharacterException{
reset(); reset();
setReplaced(replaced); setReplaced(replaced);
@@ -386,10 +515,26 @@ public class PolybiusSquare{
this.preserveSymbols = preserveSymbols; this.preserveSymbols = preserveSymbols;
} }
//Sets the keyword and inputString and encodes the message /**
* Sets the keyword and input string and encodes the message.
*
* @param inputString the message to encode
* @return the encoded message
* @throws InvalidCharacterException if any character is invalid
* @throws InvalidInputException if the input string is invalid
*/
public String encode(String inputString) throws InvalidCharacterException, InvalidInputException{ public String encode(String inputString) throws InvalidCharacterException, InvalidInputException{
return encode("", inputString); return encode("", inputString);
} }
/**
* Sets the keyword and input string and encodes the message.
*
* @param keyword the keyword for the cipher
* @param inputString the message to encode
* @return the encoded message
* @throws InvalidCharacterException if any character is invalid
* @throws InvalidInputException if the input string is invalid
*/
public String encode(String keyword, String inputString) throws InvalidCharacterException, InvalidInputException{ public String encode(String keyword, String inputString) throws InvalidCharacterException, InvalidInputException{
reset(); reset();
setKeyword(keyword); setKeyword(keyword);
@@ -397,10 +542,26 @@ public class PolybiusSquare{
encode(); encode();
return outputString; return outputString;
} }
//Sets the keyword and inputString and decodes the message /**
* Sets the keyword and input string and decodes the message.
*
* @param inputString the encoded message to decode
* @return the decoded message
* @throws InvalidCharacterException if any character is invalid
* @throws InvalidInputException if the input string is invalid
*/
public String decode(String inputString) throws InvalidCharacterException, InvalidInputException{ public String decode(String inputString) throws InvalidCharacterException, InvalidInputException{
return decode("", inputString); return decode("", inputString);
} }
/**
* Sets the keyword and input string and decodes the message.
*
* @param keyword the keyword for the cipher
* @param inputString the encoded message to decode
* @return the decoded message
* @throws InvalidCharacterException if any character is invalid
* @throws InvalidInputException if the input string is invalid
*/
public String decode(String keyword, String inputString) throws InvalidCharacterException, InvalidInputException{ public String decode(String keyword, String inputString) throws InvalidCharacterException, InvalidInputException{
reset(); reset();
setKeyword(keyword); setKeyword(keyword);
@@ -409,7 +570,9 @@ public class PolybiusSquare{
return outputString; return outputString;
} }
//Makes sure all variables are empty /**
* Resets all variables to their default values.
*/
public void reset(){ public void reset(){
logger.debug("Resetting fields"); logger.debug("Resetting fields");
@@ -419,22 +582,52 @@ public class PolybiusSquare{
keyword = ""; keyword = "";
} }
//Getters //?Getters
/**
* Returns the replaced character.
*
* @return the replaced character
*/
public char getReplaced(){ public char getReplaced(){
return replaced; return replaced;
} }
/**
* Returns the replacer character.
*
* @return the replacer character
*/
public char getReplacer(){ public char getReplacer(){
return replacer; return replacer;
} }
/**
* Returns the keyword used in the cipher.
*
* @return the keyword
*/
public String getKeyword(){ public String getKeyword(){
return keyword; return keyword;
} }
/**
* Returns the input string that was set for encoding/decoding.
*
* @return the input string
*/
public String getInputString(){ public String getInputString(){
return inputString; return inputString;
} }
/**
* Returns the output string after encoding/decoding.
*
* @return the output string
*/
public String getOutputString(){ public String getOutputString(){
return outputString; return outputString;
} }
/**
* Returns a string representation of the grid.
*
* @return the grid as a string
*/
public String getGrid(){ public String getGrid(){
logger.debug("Creating string from grid"); logger.debug("Creating string from grid");

View File

@@ -1,7 +1,23 @@
//CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/polysubstitution/RailFence.java //CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/polysubstitution/RailFence.java
//Mattrixwv //Mattrixwv
// Created: 03-21-22 // Created: 03-21-22
//Modified: 05-04-23 //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.polysubstitution; package com.mattrixwv.cipherstream.polysubstitution;
@@ -14,19 +30,35 @@ import com.mattrixwv.cipherstream.exceptions.InvalidBaseException;
import com.mattrixwv.cipherstream.exceptions.InvalidInputException; import com.mattrixwv.cipherstream.exceptions.InvalidInputException;
/**
* Represents the Rail Fence cipher encryption and decryption.
* The Rail Fence cipher is a form of transposition cipher that writes the message in a zigzag pattern
* across multiple "rails" and then reads it off row by row to encode or decode the message.
*/
public class RailFence{ public class RailFence{
private static final Logger logger = LoggerFactory.getLogger(RailFence.class); private static final Logger logger = LoggerFactory.getLogger(RailFence.class);
//Fields //?Fields
protected String inputString; //The message that needs to be encoded/decoded /** The message that needs to be encoded/decoded */
protected String outputString; //The encoded/decoded message protected String inputString;
protected StringBuilder[] fence; //The fence used for encoding/decoding /** The encoded/decoded message */
//Settings protected String outputString;
protected boolean preserveCapitals; //Persist capitals in the output string /** The fence used for encoding/decoding */
protected boolean preserveWhitespace; //Persist whitespace in the output string protected StringBuilder[] fence;
protected boolean preserveSymbols; //Persist symbols in the output string //?Settings
/** Persist capitals in the output string */
protected boolean preserveCapitals;
/** Persist whitespace in the output string */
protected boolean preserveWhitespace;
/** Persist symbols in the output string */
protected boolean preserveSymbols;
//Strips invalid characters from the string that needs encoded/decoded /**
* Strips invalid characters from the string that needs to be encoded/decoded.
*
* @param inputString the input string to be cleaned
* @throws InvalidInputException if the input string is null or invalid
*/
protected void setInputString(String inputString) throws InvalidInputException{ protected void setInputString(String inputString) throws InvalidInputException{
//Ensure the input string isn't null //Ensure the input string isn't null
if(inputString == null){ if(inputString == null){
@@ -61,7 +93,12 @@ public class RailFence{
throw new InvalidInputException("Input must contain at least 1 letter"); throw new InvalidInputException("Input must contain at least 1 letter");
} }
} }
//Ensures the number of rails is valid and sets up the fence /**
* Ensures the number of rails is valid and sets up the fence.
*
* @param numRails the number of rails to be used
* @throws InvalidBaseException if the number of rails is less than 2
*/
protected void setNumRails(int numRails) throws InvalidBaseException{ protected void setNumRails(int numRails) throws InvalidBaseException{
if(numRails < 2){ if(numRails < 2){
throw new InvalidBaseException("You must use at least 2 rails"); throw new InvalidBaseException("You must use at least 2 rails");
@@ -74,13 +111,21 @@ public class RailFence{
fence[cnt] = new StringBuilder(); fence[cnt] = new StringBuilder();
} }
} }
//Strip the inputString of all non-letter characters /**
* Strips the input string of all non-letter characters.
*
* @return the cleaned input string
*/
protected String getCleanInputString(){ protected String getCleanInputString(){
logger.debug("Getting input string for encoding"); logger.debug("Getting input string for encoding");
return inputString.replaceAll("[^a-zA-Z]", ""); return inputString.replaceAll("[^a-zA-Z]", "");
} }
//Ensures capitals, lowercase, and symbols are displayed in the output string /**
* Ensures capitals, lowercase, and symbols are displayed in the output string.
*
* @param outputString the encoded/decoded output string to be formatted
*/
protected void formatOutput(String outputString){ protected void formatOutput(String outputString){
logger.debug("Formatting output string"); logger.debug("Formatting output string");
@@ -109,7 +154,11 @@ public class RailFence{
this.outputString = output.toString(); this.outputString = output.toString();
logger.debug("Formatted output '{}'", this.outputString); logger.debug("Formatted output '{}'", this.outputString);
} }
//Returns the decoded string found in the fence after all characters are placed correctly /**
* Returns the decoded string found in the fence after all characters are placed correctly.
*
* @return the decoded string
*/
protected String getDecodedStringFromFence(){ protected String getDecodedStringFromFence(){
logger.debug("Getting decoded string from the fence"); logger.debug("Getting decoded string from the fence");
@@ -161,7 +210,9 @@ public class RailFence{
logger.debug("Fence output '{}'", output); logger.debug("Fence output '{}'", output);
return output.toString(); return output.toString();
} }
//Encodes inputString using the RailFence cipher and stores the result in outputString /**
* Encodes the input string using the Rail Fence cipher and stores the result in the output string.
*/
protected void encode(){ protected void encode(){
logger.debug("Encoding"); logger.debug("Encoding");
@@ -204,7 +255,9 @@ public class RailFence{
//Format the output //Format the output
formatOutput(output.toString()); formatOutput(output.toString());
} }
//Decodes inputString using the RailFence cipher and stores the result in outputString /**
* Decodes the input string using the Rail Fence cipher and stores the result in the output string.
*/
protected void decode(){ protected void decode(){
logger.debug("Decoding"); logger.debug("Decoding");
@@ -256,13 +309,23 @@ public class RailFence{
formatOutput(output); formatOutput(output);
} }
//Constructor //?Constructor
/**
* Constructs a RailFence cipher instance with default settings.
*/
public RailFence(){ public RailFence(){
preserveCapitals = false; preserveCapitals = false;
preserveWhitespace = false; preserveWhitespace = false;
preserveSymbols = false; preserveSymbols = false;
reset(); reset();
} }
/**
* Constructs a RailFence cipher instance with specified settings.
*
* @param preserveCapitals whether to preserve uppercase letters
* @param preserveWhitespace whether to preserve whitespace
* @param preserveSymbols whether to preserve symbols
*/
public RailFence(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols){ public RailFence(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols){
this.preserveCapitals = preserveCapitals; this.preserveCapitals = preserveCapitals;
this.preserveWhitespace = preserveWhitespace; this.preserveWhitespace = preserveWhitespace;
@@ -270,7 +333,15 @@ public class RailFence{
reset(); reset();
} }
//Encodes inputString using a Rail Fence of length numRails and returns the result /**
* Encodes the input string using a Rail Fence of the specified number of rails and returns the result.
*
* @param numRails the number of rails to use
* @param inputString the message to encode
* @return the encoded message
* @throws InvalidBaseException if the number of rails is invalid
* @throws InvalidInputException if the input string is invalid
*/
public String encode(int numRails, String inputString) throws InvalidBaseException, InvalidInputException{ public String encode(int numRails, String inputString) throws InvalidBaseException, InvalidInputException{
//Set the parameters //Set the parameters
setNumRails(numRails); setNumRails(numRails);
@@ -280,7 +351,15 @@ public class RailFence{
encode(); encode();
return outputString; return outputString;
} }
//Decodes inputString using a Rail Fence of length numRails and returns the result /**
* Decodes the input string using a Rail Fence of the specified number of rails and returns the result.
*
* @param numRails the number of rails to use
* @param inputString the encoded message to decode
* @return the decoded message
* @throws InvalidBaseException if the number of rails is invalid
* @throws InvalidInputException if the input string is invalid
*/
public String decode(int numRails, String inputString) throws InvalidBaseException, InvalidInputException{ public String decode(int numRails, String inputString) throws InvalidBaseException, InvalidInputException{
//Set the parameters //Set the parameters
setNumRails(numRails); setNumRails(numRails);
@@ -291,7 +370,9 @@ public class RailFence{
return outputString; return outputString;
} }
//Makes sure all variables are empty /**
* Resets all variables to their default values.
*/
public void reset(){ public void reset(){
logger.debug("Resetting fields"); logger.debug("Resetting fields");
@@ -300,13 +381,28 @@ public class RailFence{
fence = null; fence = null;
} }
//Getters //?Getters
/**
* Returns the input string that was set for encoding/decoding.
*
* @return the input string
*/
public String getInputString(){ public String getInputString(){
return inputString; return inputString;
} }
/**
* Returns the output string after encoding/decoding.
*
* @return the output string
*/
public String getOutputString(){ public String getOutputString(){
return outputString; return outputString;
} }
/**
* Returns the number of rails used in the Rail Fence cipher.
*
* @return the number of rails
*/
public int getNumRails(){ public int getNumRails(){
return fence.length; return fence.length;
} }

View File

@@ -1,7 +1,23 @@
//CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Trifid.java //CipherStreamJava/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Trifid.java
//Mattrixwv //Mattrixwv
// Created: 03-03-22 // Created: 03-03-22
//Modified: 04-19-24 //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.polysubstitution; package com.mattrixwv.cipherstream.polysubstitution;
@@ -17,46 +33,92 @@ import com.mattrixwv.cipherstream.exceptions.InvalidInputException;
import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException; import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException;
/**
* The {@code Trifid} class implements the Trifid cipher, a polyalphabetic substitution cipher
* that uses a 3x3x3 grid to encode and decode messages.
*/
public class Trifid{ public class Trifid{
private static final Logger logger = LoggerFactory.getLogger(Trifid.class); private static final Logger logger = LoggerFactory.getLogger(Trifid.class);
//A class representing the location of a character in the grid /** A class representing the location of a character in the grid */
protected class CharLocation{ protected class CharLocation{
/** The x location in the grid */
protected int x; protected int x;
/** The y location in the grid */
protected int y; protected int y;
/** The z location in the grid */
protected int z; protected int z;
/**
* Constructs a CharLocation with the specified x and y coordinates.
*
* @param x the x-coordinate of the character's location
* @param y the y-coordinate of the character's location
* @param z the z-coordinate of the character's location
*/
public CharLocation(int x, int y, int z){ public CharLocation(int x, int y, int z){
this.x = x; this.x = x;
this.y = y; this.y = y;
this.z = z; this.z = z;
} }
/**
* Returns the x-coordinate of the character's location.
*
* @return the x-coordinate
*/
public int getX(){ public int getX(){
return x; return x;
} }
/**
* Returns the y-coordinate of the character's location.
*
* @return the y-coordinate
*/
public int getY(){ public int getY(){
return y; return y;
} }
/**
* Returns the z-coordinate of the character's location.
*
* @return the z-coordinate
*/
public int getZ(){ public int getZ(){
return z; return z;
} }
/**
* Prints out the location in a human readable format
*/
public String toString(){ public String toString(){
return "[" + (z + 1) + ", " + (x + 1) + ", " + (y + 1) + "]"; return "[" + (z + 1) + ", " + (x + 1) + ", " + (y + 1) + "]";
} }
} }
//Fields //?Fields
protected String inputString; //The message that needs to be encoded/decoded /** The message that needs to be encoded/decoded */
protected String outputString; //The encoded/decoded message protected String inputString;
protected String keyword; //The keyword used to create the grid /** The encoded/decoded message */
protected int groupSize; //The size of the groups used to break up the input protected String outputString;
protected char[][][] grid; //The grid used to encode/decode the message /** The keyword used to create the grid */
protected char fillIn; //The character added to the alphabet to meet the 27 character requirement protected String keyword;
//Settings /** The size of the groups used to break up the input */
protected boolean preserveCapitals; //Persist capitals in the output string protected int groupSize;
protected boolean preserveWhitespace; //Persist whitespace in the output string /** The grid used to encode/decode the message */
protected boolean preserveSymbols; //Persist symbols in the output string protected char[][][] grid;
/** The character added to the alphabet to meet the 27 character requirement */
protected char fillIn;
//?Settings
/** Persist capitals in the output string */
protected boolean preserveCapitals;
/** Persist whitespace in the output string */
protected boolean preserveWhitespace;
/** Persist symbols in the output string */
protected boolean preserveSymbols;
//Makes sure the fillIn is a valid character /**
* Sets the fill-in character used to complete the 27-character requirement for the grid.
*
* @param fillIn the fill-in character
* @throws InvalidCharacterException if the fill-in character is not a printable non-letter character
*/
protected void setFillIn(char fillIn) throws InvalidCharacterException{ protected void setFillIn(char fillIn) throws InvalidCharacterException{
//Make sure the character is a printing character //Make sure the character is a printing character
if((fillIn < ' ') || (fillIn > '~')){ if((fillIn < ' ') || (fillIn > '~')){
@@ -72,7 +134,13 @@ public class Trifid{
//Save the fillIn character //Save the fillIn character
this.fillIn = fillIn; this.fillIn = fillIn;
} }
//Strips invalid characters from the keyword and creates the grid /**
* Processes the keyword to generate the 3D grid. The keyword is sanitized to include
* only capital letters and the fill-in character.
*
* @param keyword the keyword used to create the grid
* @throws InvalidKeywordException if the keyword is invalid
*/
protected void setKeyword(String keyword) throws InvalidKeywordException{ protected void setKeyword(String keyword) throws InvalidKeywordException{
//Ensure the keyword isn't null //Ensure the keyword isn't null
if(keyword == null){ if(keyword == null){
@@ -104,7 +172,9 @@ public class Trifid{
//Create the grid from the sanitized keyword //Create the grid from the sanitized keyword
createGrid(); createGrid();
} }
//Creates the grid from the keyword /**
* Creates the 3D grid from the processed keyword.
*/
protected void createGrid(){ protected void createGrid(){
logger.debug("Creating grid from keyword"); logger.debug("Creating grid from keyword");
@@ -120,7 +190,12 @@ public class Trifid{
logger.debug("Completed grid\n{}", getGrid()); logger.debug("Completed grid\n{}", getGrid());
} }
//Ensures groupSize constraints /**
* Sets the group size used for encoding and decoding the input string.
*
* @param groupSize the group size
* @throws InvalidBaseException if the group size is less than or equal to zero
*/
protected void setGroupSize(int groupSize) throws InvalidBaseException{ protected void setGroupSize(int groupSize) throws InvalidBaseException{
if(groupSize <= 0){ if(groupSize <= 0){
throw new InvalidBaseException("Group size must be > 0"); throw new InvalidBaseException("Group size must be > 0");
@@ -130,7 +205,13 @@ public class Trifid{
this.groupSize = groupSize; this.groupSize = groupSize;
} }
//Ensures inputString constraints /**
* Prepares the input string for encoding or decoding by applying preservation settings
* and validating the input.
*
* @param inputString the input string to be processed
* @throws InvalidInputException if the input string is invalid
*/
protected void setInputString(String inputString) throws InvalidInputException{ protected void setInputString(String inputString) throws InvalidInputException{
//Ensure the input string isn't null //Ensure the input string isn't null
if(inputString == null){ if(inputString == null){
@@ -165,12 +246,22 @@ public class Trifid{
throw new InvalidInputException("Input must contain at least 1 letter"); throw new InvalidInputException("Input must contain at least 1 letter");
} }
} }
//Returns the inputString with only letters /**
* Returns the input string with only valid letters and fill-in characters.
*
* @return the cleaned input string
*/
protected String getCleanInputString(){ protected String getCleanInputString(){
logger.debug("Cleaning input string for encoding"); logger.debug("Cleaning input string for encoding");
return inputString.toUpperCase().replaceAll("[^A-Z" + fillIn + "]", ""); return inputString.toUpperCase().replaceAll("[^A-Z" + fillIn + "]", "");
} }
//Returns the location of the given character in the grid /**
* Finds the location of a given character in the 3D grid.
*
* @param letter the character to find
* @return the location of the character
* @throws InvalidCharacterException if the character is not found in the grid
*/
protected CharLocation findChar(char letter) throws InvalidCharacterException{ protected CharLocation findChar(char letter) throws InvalidCharacterException{
logger.debug("Finding character {} in grid", letter); logger.debug("Finding character {} in grid", letter);
@@ -189,7 +280,13 @@ public class Trifid{
//If it was not found something went wrong //If it was not found something went wrong
throw new InvalidCharacterException("The character '" + letter + "' was not found in the grid"); throw new InvalidCharacterException("The character '" + letter + "' was not found in the grid");
} }
//Return the character from the location provided /**
* Retrieves the character at the specified location in the 3D grid.
*
* @param location the location of the character
* @return the character at the specified location
* @throws InvalidCharacterException if the location is out of bounds
*/
protected char getChar(CharLocation location) throws InvalidCharacterException{ protected char getChar(CharLocation location) throws InvalidCharacterException{
if(location.getX() > 2){ if(location.getX() > 2){
throw new InvalidCharacterException("x cannot be larget than 2"); throw new InvalidCharacterException("x cannot be larget than 2");
@@ -205,7 +302,11 @@ public class Trifid{
return grid[location.getZ()][location.getX()][location.getY()]; return grid[location.getZ()][location.getX()][location.getY()];
} }
//Adds all non-letter characters back to the output string /**
* Formats the output string according to the preservation settings.
*
* @param outputString the output string to format
*/
protected void formatOutput(String outputString){ protected void formatOutput(String outputString){
logger.debug("Formatting output"); logger.debug("Formatting output");
@@ -242,7 +343,11 @@ public class Trifid{
this.outputString = output.toString(); this.outputString = output.toString();
logger.debug("Formatted output '{}'", this.outputString); logger.debug("Formatted output '{}'", this.outputString);
} }
//Encodes inputString using a polybius square and stores the result in outputString /**
* Encodes the input string using the Trifid cipher.
*
* @throws InvalidCharacterException if an invalid character is encountered
*/
protected void encode() throws InvalidCharacterException{ protected void encode() throws InvalidCharacterException{
logger.debug("Encoding"); logger.debug("Encoding");
@@ -308,7 +413,11 @@ public class Trifid{
//Format the output //Format the output
formatOutput(output.toString()); formatOutput(output.toString());
} }
//Decodes inputString using a polybius square and stores the result in outputString /**
* Decodes the input string using the Trifid cipher.
*
* @throws InvalidCharacterException if an invalid character is encountered
*/
protected void decode() throws InvalidCharacterException{ protected void decode() throws InvalidCharacterException{
logger.debug("Decoding"); logger.debug("Decoding");
@@ -380,7 +489,10 @@ public class Trifid{
} }
//Constructor //?Constructor
/**
* Constructs a Trifid object with default settings.
*/
public Trifid() throws InvalidCharacterException{ public Trifid() throws InvalidCharacterException{
preserveCapitals = false; preserveCapitals = false;
preserveWhitespace = false; preserveWhitespace = false;
@@ -388,6 +500,13 @@ public class Trifid{
setFillIn('+'); setFillIn('+');
reset(); reset();
} }
/**
* Constructs a Trifid object with default settings.
*
* @param preserveCapitals whether to preserve capital letters
* @param preserveWhitespace whether to preserve whitespace
* @param preserveSymbols whether to preserve symbols
*/
public Trifid(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols) throws InvalidCharacterException{ public Trifid(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols) throws InvalidCharacterException{
this.preserveCapitals = preserveCapitals; this.preserveCapitals = preserveCapitals;
this.preserveWhitespace = preserveWhitespace; this.preserveWhitespace = preserveWhitespace;
@@ -395,6 +514,15 @@ public class Trifid{
setFillIn('+'); setFillIn('+');
reset(); reset();
} }
/**
* Constructs a Trifid object with default settings.
*
* @param preserveCapitals whether to preserve capital letters
* @param preserveWhitespace whether to preserve whitespace
* @param preserveSymbols whether to preserve symbols
* @param fillIn the character to use for fill-in characters
* @throws InvalidCharacterException if the fill-in character is invalid
*/
public Trifid(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols, char fillIn) throws InvalidCharacterException{ public Trifid(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols, char fillIn) throws InvalidCharacterException{
this.preserveCapitals = preserveCapitals; this.preserveCapitals = preserveCapitals;
this.preserveWhitespace = preserveWhitespace; this.preserveWhitespace = preserveWhitespace;
@@ -403,10 +531,32 @@ public class Trifid{
reset(); reset();
} }
//Encodes inputString using keyword and groupSize and returns the result /**
* Encodes the specified input string using the provided keyword and group size.
*
* @param keyword the keyword used for encoding
* @param inputString the input string to encode
* @return the encoded string
* @throws InvalidBaseException if the group size is invalid
* @throws InvalidKeywordException if the keyword is invalid
* @throws InvalidInputException if the input string is invalid
* @throws InvalidCharacterException if an invalid character is encountered
*/
public String encode(String keyword, String inputString) throws InvalidBaseException, InvalidKeywordException, InvalidInputException, InvalidCharacterException{ public String encode(String keyword, String inputString) throws InvalidBaseException, InvalidKeywordException, InvalidInputException, InvalidCharacterException{
return encode(keyword, inputString.length(), inputString); return encode(keyword, inputString.length(), inputString);
} }
/**
* Encodes the specified input string using the provided keyword and group size.
*
* @param keyword the keyword used for encoding
* @param groupSize the size of groups
* @param inputString the input string to encode
* @return the encoded string
* @throws InvalidBaseException if the group size is invalid
* @throws InvalidKeywordException if the keyword is invalid
* @throws InvalidInputException if the input string is invalid
* @throws InvalidCharacterException if an invalid character is encountered
*/
public String encode(String keyword, int groupSize, String inputString) throws InvalidBaseException, InvalidKeywordException, InvalidInputException, InvalidCharacterException{ public String encode(String keyword, int groupSize, String inputString) throws InvalidBaseException, InvalidKeywordException, InvalidInputException, InvalidCharacterException{
//Set the parameters //Set the parameters
reset(); reset();
@@ -418,10 +568,32 @@ public class Trifid{
encode(); encode();
return outputString; return outputString;
} }
//Decodes inputString using keyword and groupSize and returns the result /**
* Decodes the specified input string using the provided keyword and group size.
*
* @param keyword the keyword used for decoding
* @param inputString the input string to decode
* @return the decoded string
* @throws InvalidBaseException if the group size is invalid
* @throws InvalidKeywordException if the keyword is invalid
* @throws InvalidInputException if the input string is invalid
* @throws InvalidCharacterException if an invalid character is encountered
*/
public String decode(String keyword, String inputString) throws InvalidBaseException, InvalidKeywordException, InvalidInputException, InvalidCharacterException{ public String decode(String keyword, String inputString) throws InvalidBaseException, InvalidKeywordException, InvalidInputException, InvalidCharacterException{
return decode(keyword, inputString.length(), inputString); return decode(keyword, inputString.length(), inputString);
} }
/**
* Decodes the specified input string using the provided keyword and group size.
*
* @param keyword the keyword used for decoding
* @param groupSize the size of groups
* @param inputString the input string to decode
* @return the decoded string
* @throws InvalidBaseException if the group size is invalid
* @throws InvalidKeywordException if the keyword is invalid
* @throws InvalidInputException if the input string is invalid
* @throws InvalidCharacterException if an invalid character is encountered
*/
public String decode(String keyword, int groupSize, String inputString) throws InvalidBaseException, InvalidKeywordException, InvalidInputException, InvalidCharacterException{ public String decode(String keyword, int groupSize, String inputString) throws InvalidBaseException, InvalidKeywordException, InvalidInputException, InvalidCharacterException{
//Set the parameters //Set the parameters
reset(); reset();
@@ -434,7 +606,9 @@ public class Trifid{
return outputString; return outputString;
} }
//Makes sure all variables are empty /**
* Resets all internal variables to their default values.
*/
public void reset(){ public void reset(){
logger.debug("Resetting fields"); logger.debug("Resetting fields");
@@ -445,22 +619,52 @@ public class Trifid{
grid = new char[3][3][3]; grid = new char[3][3][3];
} }
//Getters //?Getters
/**
* Returns the current input string.
*
* @return the input string
*/
public String getInputString(){ public String getInputString(){
return inputString; return inputString;
} }
/**
* Returns the current output string.
*
* @return the output string
*/
public String getOutputString(){ public String getOutputString(){
return outputString; return outputString;
} }
/**
* Returns the current keyword.
*
* @return the keyword
*/
public String getKeyword(){ public String getKeyword(){
return keyword; return keyword;
} }
/**
* Returns the current group size.
*
* @return the group size
*/
public int getGroupSize(){ public int getGroupSize(){
return groupSize; return groupSize;
} }
/**
* Returns the current fill-in character.
*
* @return the fill-in character
*/
public char getFillIn(){ public char getFillIn(){
return fillIn; return fillIn;
} }
/**
* Returns a string representation of the 3D grid.
*
* @return the grid as a string
*/
public String getGrid(){ public String getGrid(){
logger.debug("Creating string from grid"); logger.debug("Creating string from grid");