mirror of
https://bitbucket.org/Mattrixwv/cipherstream.git
synced 2025-12-06 18:33:58 -05:00
238 lines
5.9 KiB
C++
238 lines
5.9 KiB
C++
//Ciphers/SourceFiles/Vigenere.cpp
|
|
//Matthew Ellison
|
|
// Created: 04-29-18
|
|
//Modified: 03-07-19
|
|
//This file contains the implementation of the Vigenere class
|
|
|
|
#include "../Headers/Vigenere.hpp"
|
|
#include <string>
|
|
#include <vector>
|
|
#include <cctype>
|
|
|
|
|
|
/**
|
|
* @brief The current library's version number
|
|
*
|
|
*/
|
|
const std::string Vigenere::version = "1.1";
|
|
|
|
/**
|
|
* @brief Construct a new Vigenere object
|
|
*
|
|
*/
|
|
Vigenere::Vigenere(){
|
|
reset();
|
|
}
|
|
|
|
/**
|
|
* @brief Destroy the Vigenere object
|
|
*
|
|
*/
|
|
Vigenere::~Vigenere(){
|
|
}
|
|
|
|
/**
|
|
* @brief Removes all invalid characters from input and sets it to inputString
|
|
*
|
|
* @param input The string you want to encode/decode
|
|
*/
|
|
void Vigenere::setInputString(std::string input){
|
|
//Loop through every character in input. Remove all whitespace and punctuation and make sure all letters are capital and add it to inputString
|
|
for(unsigned int cnt = 0;cnt < input.size();++cnt){
|
|
char letter = input[cnt];
|
|
if(isupper(letter)){
|
|
inputString += letter;
|
|
}
|
|
else if(islower(letter)){
|
|
inputString += toupper(letter);
|
|
}
|
|
//If the letter is whitespace or punctuation do nothing
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Returns the string you wish to encode/decode
|
|
*
|
|
* @return The string you wish to encode/decode
|
|
*/
|
|
std::string Vigenere::getInputString() const{
|
|
return inputString;
|
|
}
|
|
|
|
/**
|
|
* @brief Returns the encoded/decoded message
|
|
*
|
|
* @return The encoded/decoded message
|
|
*/
|
|
std::string Vigenere::getOutputString() const{
|
|
return outputString;
|
|
}
|
|
|
|
/**
|
|
* @brief Removes all invalid characters from key and sets it to keyword
|
|
*
|
|
* @param key The keyword used for the cipher
|
|
*/
|
|
void Vigenere::setKeyword(std::string key){
|
|
//Loop through every letter in the key and make sure all of them are uppercase letters
|
|
for(unsigned int cnt = 0;cnt < key.size();++cnt){
|
|
char letter = key[cnt];
|
|
if(isupper(letter)){
|
|
keyword += letter;
|
|
}
|
|
else if(islower(letter)){
|
|
keyword += toupper(letter);
|
|
}
|
|
//If it is not a letter ignore it
|
|
}
|
|
//Make sure offset is empty before adding to it
|
|
offset.clear();
|
|
setOffset();
|
|
//If after all the eliminating of unusable characters the keyword is empty throw an error
|
|
if(keyword == ""){
|
|
throw emptyKeyword();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Returns the keyword you are using for the cipher
|
|
*
|
|
* @return The keyword you are using for the cipher
|
|
*/
|
|
std::string Vigenere::getKeyword() const{
|
|
return keyword;
|
|
}
|
|
|
|
/**
|
|
* @brief Uses keyword to set the offsets of the letters used during encoding/decoding
|
|
*
|
|
*/
|
|
void Vigenere::setOffset(){
|
|
//Reserve the correct size to increase speed later
|
|
offset.reserve(keyword.size());
|
|
|
|
//Loop through every letter in keyword and get the offset from A
|
|
for(char letter : keyword){
|
|
offset.push_back((letter - 'A') % 26);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Returns the vector that holds the offsets of the letters used during encoding/decoding
|
|
*
|
|
* @return A the vector holding offsets of the letters used during encoding/decoding
|
|
* @note Used mostly for debuging
|
|
*/
|
|
std::vector<unsigned int> Vigenere::getOffsets() const{
|
|
return offset;
|
|
}
|
|
|
|
/**
|
|
* @brief Encodes the inputString using the Vigenere cipher and saves the result in outputString
|
|
*
|
|
* @return The encoded message
|
|
*/
|
|
std::string Vigenere::encode(){
|
|
//Reserve the correct size for the output string to increase speed for longer messages
|
|
outputString.reserve(inputString.size());
|
|
|
|
//Step through every charater in the inputString and advance it the correct amount, according to offset
|
|
for(unsigned int cnt = 0;cnt < inputString.size();++cnt){
|
|
char letter = (inputString[cnt] + offset[cnt % offset.size()]); //By using % you allow it to loop without having a separate counter
|
|
//Make sure the character is still a letter, if not, wrap around
|
|
if(letter < 'A'){
|
|
letter += 26;
|
|
}
|
|
else if(letter > 'Z'){
|
|
letter -= 26;
|
|
}
|
|
outputString += letter;
|
|
}
|
|
|
|
return outputString;
|
|
}
|
|
|
|
/**
|
|
* @brief Sets all of the variables for the cipher and returns the result
|
|
*
|
|
* @param key The keyword used in the cipher
|
|
* @param input The message that you wish to encode
|
|
* @return The encoded message
|
|
*/
|
|
std::string Vigenere::encode(std::string key, std::string input){
|
|
reset();
|
|
try{
|
|
setKeyword(key);
|
|
}
|
|
//Catch the emptyKeyword error if it was thrown
|
|
catch(emptyKeyword){
|
|
std::string errorString = "After all unusable characters were stripped away the keyword given was empty";
|
|
return errorString;
|
|
}
|
|
setInputString(input);
|
|
return encode();
|
|
}
|
|
|
|
/**
|
|
* @brief Decodes the inputString using the Vigenere cipher and saves the result in outputString
|
|
*
|
|
* @return The decoded message
|
|
*/
|
|
std::string Vigenere::decode(){
|
|
//Reserve the correct size for the output string to increase speed for longer messages
|
|
outputString.reserve(inputString.size());
|
|
|
|
//Step through every charater in the inputString and reduce it the correct amount, according to offset
|
|
for(unsigned int cnt = 0;cnt < inputString.size();++cnt){
|
|
char letter = (inputString[cnt] - offset[cnt % offset.size()]); //By using % you allow it to loop without having a separate counter
|
|
if(letter < 'A'){
|
|
letter += 26;
|
|
}
|
|
else if(letter > 'Z'){
|
|
letter -= 26;
|
|
}
|
|
outputString += letter;
|
|
}
|
|
|
|
return outputString;
|
|
}
|
|
|
|
/**
|
|
* @brief Sets all of the variables for the cipher and returns the result
|
|
*
|
|
* @param key The keyword used in the cipher
|
|
* @param input The message that you wish to decode
|
|
* @return The decoded message
|
|
*/
|
|
std::string Vigenere::decode(std::string key, std::string input){
|
|
reset();
|
|
try{
|
|
setKeyword(key);
|
|
}
|
|
//Catch the emptyKeyword error if it was thrown
|
|
catch(emptyKeyword){
|
|
std::string errorString = "After all unusable characters were stripped away the keyword given was empty";
|
|
return errorString;
|
|
}
|
|
setInputString(input);
|
|
return decode();
|
|
}
|
|
|
|
/**
|
|
* @brief Makes sure all of the variables are empty
|
|
*
|
|
*/
|
|
void Vigenere::reset(){
|
|
inputString = outputString = keyword = "";
|
|
offset.clear();
|
|
}
|
|
|
|
/**
|
|
* @brief Returns a string containing the version information
|
|
*
|
|
* @return The version information
|
|
*/
|
|
std::string Vigenere::getVersion(){
|
|
return version;
|
|
}
|