mirror of
https://bitbucket.org/Mattrixwv/cipherstream.git
synced 2025-12-06 18:33:58 -05:00
Added Playfair Cipher
This commit is contained in:
50
Headers/Playfair.hpp
Normal file
50
Headers/Playfair.hpp
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
//Ciphers/Headers/Playfair.hpp
|
||||||
|
//Matthew Ellison
|
||||||
|
// Created: 4-25-18
|
||||||
|
//Modified: 4-25-18
|
||||||
|
//This file contains the declaration of the Playfair class
|
||||||
|
//It is designed to encrypt and decrypt strings using the Playfair cipher
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef PLAYFAIR_HPP
|
||||||
|
#define PLAYFAIR_HPP
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
class Playfair{
|
||||||
|
private:
|
||||||
|
static char REPLACED; //The letter that will need to be replaced in the grid and any input string or keyword
|
||||||
|
static char REPLACER; //The letter that replaced REPLACED in any input string or keyword
|
||||||
|
static char DOUBLED; //The letter that will be placed between double letters in the input string if necessary or to make the string length even
|
||||||
|
std::string inputString;
|
||||||
|
std::string outputString;
|
||||||
|
std::string keyword;
|
||||||
|
char grid[5][5];
|
||||||
|
void createGrid();
|
||||||
|
bool checkGrid(const char letter) const;
|
||||||
|
void searchGrid(char letter, int& row, int& col);
|
||||||
|
public:
|
||||||
|
Playfair();
|
||||||
|
~Playfair();
|
||||||
|
void reset();
|
||||||
|
std::string encode();
|
||||||
|
std::string encode(std::string keyword, std::string input);
|
||||||
|
std::string decode();
|
||||||
|
std::string decode(std::string keyword, std::string input);
|
||||||
|
void setKeyword(std::string key);
|
||||||
|
std::string getKeyword() const;
|
||||||
|
void setInputString(std::string input);
|
||||||
|
std::string getInputString() const;
|
||||||
|
std::string getOutputString() const;
|
||||||
|
std::string getGrid() const;
|
||||||
|
//Change static variables
|
||||||
|
static char getReplaced();
|
||||||
|
static void setReplaced(const char replaced);
|
||||||
|
static char getReplacer();
|
||||||
|
static void setReplacer(const char replacer);
|
||||||
|
static char getDoubled();
|
||||||
|
static void setDoubled(const char doubled);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //PLAYFAIR_HPP
|
||||||
394
SourceFiles/Playfair.cpp
Normal file
394
SourceFiles/Playfair.cpp
Normal file
@@ -0,0 +1,394 @@
|
|||||||
|
//Ciphers/Headers/Playfair.cpp
|
||||||
|
//Matthew Ellison
|
||||||
|
// Created: 4-25-18
|
||||||
|
//Modified: 4-25-18
|
||||||
|
//This file contains the implementation of the Playfair class
|
||||||
|
//It is designed to encrypt and decrypt strings using the Playfair cipher
|
||||||
|
|
||||||
|
|
||||||
|
#include "../Headers/Playfair.hpp"
|
||||||
|
#include <string>
|
||||||
|
#include <cctype>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
char Playfair::REPLACED = 'J';
|
||||||
|
char Playfair::REPLACER = 'I';
|
||||||
|
char Playfair::DOUBLED = 'X';
|
||||||
|
|
||||||
|
Playfair::Playfair(){
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
Playfair::~Playfair(){
|
||||||
|
}
|
||||||
|
|
||||||
|
void Playfair::createGrid(){
|
||||||
|
unsigned int row, column;
|
||||||
|
bool found = false;
|
||||||
|
row = column = 0;
|
||||||
|
|
||||||
|
//Add any new leters from the keyword to the grid
|
||||||
|
///If you reach row 5 then the entire grid has been filled
|
||||||
|
char current;
|
||||||
|
for(int cnt = 0;(cnt < keyword.size()) && (row < 5);++cnt){
|
||||||
|
current = keyword[cnt];
|
||||||
|
//If the current letter needs to be replaced, do so
|
||||||
|
if(current == REPLACED){
|
||||||
|
current = REPLACER;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Search the grid for the current letter
|
||||||
|
found = checkGrid(current);
|
||||||
|
|
||||||
|
//If the letter is not in the grid add it
|
||||||
|
if(!found){
|
||||||
|
grid[row][column] = keyword[cnt];
|
||||||
|
++column;
|
||||||
|
//If the column number is too high reset it and advance the row
|
||||||
|
if(column >= 5){
|
||||||
|
column = 0;
|
||||||
|
++row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Until you reach the end of the grid you need to start with the first letter and try to add them to the grid
|
||||||
|
current = 'A';
|
||||||
|
while((row < 5) && (current <= 'Z')){
|
||||||
|
////Start here
|
||||||
|
//Make sure the is not the replaced letter
|
||||||
|
if(current == REPLACED){
|
||||||
|
++current;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check the grid for the current letter
|
||||||
|
found = checkGrid(current);
|
||||||
|
|
||||||
|
//If the letter was not found in the grid add it to the current location
|
||||||
|
if(!found){
|
||||||
|
grid[row][column] = current;
|
||||||
|
++column;
|
||||||
|
//If you have reached the end of the row move to the beginning of the next one
|
||||||
|
if(column >= 5){
|
||||||
|
column = 0;
|
||||||
|
++row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++current;
|
||||||
|
}
|
||||||
|
//Put a check here that row == 5. If it doesn't then there is a problem
|
||||||
|
///Make this a propper exception throw rather than this
|
||||||
|
if(row != 5){
|
||||||
|
std::cout << "There is a problem with the grid!\n" << getGrid() << std::endl;;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Playfair::checkGrid(const char letter) const{
|
||||||
|
//Step through every element in the grid and check for it
|
||||||
|
for(int rowCnt = 0;rowCnt < 5;++rowCnt){
|
||||||
|
for(int colCnt = 0;colCnt < 5;++colCnt){
|
||||||
|
//If you find the letter in the grid return true
|
||||||
|
if(letter == grid[rowCnt][colCnt]){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//If you reach a \0 then there are no more symbols past that and no reason to continue checking
|
||||||
|
else if(grid[rowCnt][colCnt] == '\0'){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//If it did not trigger the true, then it must be false
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Playfair::searchGrid(char letter, int& row, int& col){
|
||||||
|
////Start here
|
||||||
|
//Check if letter needs to be replaced
|
||||||
|
if(letter == REPLACED){
|
||||||
|
letter = REPLACER;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Go through every element in the grid until you find the correct letter
|
||||||
|
for(row = 0;row < 5;++row){
|
||||||
|
for(col = 0;col < 5;++col){
|
||||||
|
//If it is the correct letter you just need to return (row and col are passed by reference)
|
||||||
|
if(grid[row][col] == letter){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//If letter was not found you need to throw an error
|
||||||
|
///Turn this into a propper exception throw rather than this
|
||||||
|
std::cout << "Error in searchGrid()\nLetter: " << letter << "\n\n" << getGrid() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Playfair::reset(){
|
||||||
|
inputString = outputString = keyword = "";
|
||||||
|
//Clear the grid
|
||||||
|
for(int cnt1 = 0;cnt1 < 5;++cnt1){
|
||||||
|
for(int cnt2 = 0;cnt2 < 5;++cnt2){
|
||||||
|
grid[cnt1][cnt2] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Playfair::encode(){
|
||||||
|
outputString = "";
|
||||||
|
char letter1, letter2;
|
||||||
|
int row1, col1, row2, col2;
|
||||||
|
//Step through every element in the input string and encode a pair
|
||||||
|
for(int cnt = 1;cnt < inputString.size();cnt += 2){
|
||||||
|
//Grab two elements from the input string and search the grid for them
|
||||||
|
letter1 = inputString[cnt - 1];
|
||||||
|
letter2 = inputString[cnt];
|
||||||
|
|
||||||
|
//Get the location in the grid of each letter
|
||||||
|
searchGrid(letter1, row1, col1);
|
||||||
|
searchGrid(letter2, row2, col2);
|
||||||
|
|
||||||
|
//If the letters are in the same row, shift the column right by 1
|
||||||
|
if(row1 == row2){
|
||||||
|
++col1;
|
||||||
|
++col2;
|
||||||
|
|
||||||
|
//Wrap around
|
||||||
|
if(col1 > 4){
|
||||||
|
col1 -= 5;
|
||||||
|
}
|
||||||
|
if(col2 > 4){
|
||||||
|
col2 -= 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//If the letters are in the same column, shift the row down by 1
|
||||||
|
else if(col1 == col2){
|
||||||
|
++row1;
|
||||||
|
++row2;
|
||||||
|
|
||||||
|
//Wrap around
|
||||||
|
if(row1 > 4){
|
||||||
|
row1 -= 5;
|
||||||
|
}
|
||||||
|
if(row2 > 4){
|
||||||
|
row2 -= 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//If neither of the above then treat them like oposite corners in a square and swap their column variables
|
||||||
|
else{
|
||||||
|
std::swap(col1, col2);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get the new letters
|
||||||
|
letter1 = grid[row1][col1];
|
||||||
|
letter2 = grid[row2][col2];
|
||||||
|
//Add the new strings to the outputString
|
||||||
|
outputString += letter1;
|
||||||
|
outputString += letter2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return outputString;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Playfair::encode(std::string keyword, std::string input){
|
||||||
|
setKeyword(keyword);
|
||||||
|
setInputString(input);
|
||||||
|
return encode();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Playfair::decode(){
|
||||||
|
outputString = "";
|
||||||
|
char letter1, letter2;
|
||||||
|
int row1, col1, row2, col2;
|
||||||
|
//Step through every element in the input string and encode a pair
|
||||||
|
for(int cnt = 1;cnt < inputString.size();cnt += 2){
|
||||||
|
//Grab two elements from the input string and search the grid for them
|
||||||
|
letter1 = inputString[cnt - 1];
|
||||||
|
letter2 = inputString[cnt];
|
||||||
|
|
||||||
|
//Get the location in the grid of each letter
|
||||||
|
searchGrid(letter1, row1, col1);
|
||||||
|
searchGrid(letter2, row2, col2);
|
||||||
|
|
||||||
|
//If the letters are in the same row, shift the column left by 1
|
||||||
|
if(row1 == row2){
|
||||||
|
--col1;
|
||||||
|
--col2;
|
||||||
|
|
||||||
|
//Wrap around
|
||||||
|
if(col1 > 4){
|
||||||
|
col1 += 5;
|
||||||
|
}
|
||||||
|
if(col2 > 4){
|
||||||
|
col2 += 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//If the letters are in the same column, shift the row up by 1
|
||||||
|
else if(col1 == col2){
|
||||||
|
--row1;
|
||||||
|
--row2;
|
||||||
|
|
||||||
|
//Wrap around
|
||||||
|
if(row1 > 4){
|
||||||
|
row1 += 5;
|
||||||
|
}
|
||||||
|
if(row2 > 4){
|
||||||
|
row2 += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//If neither of the above then treat them like oposite corners in a square and swap their column variables
|
||||||
|
else{
|
||||||
|
std::swap(col1, col2);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get the new letters
|
||||||
|
letter1 = grid[row1][col1];
|
||||||
|
letter2 = grid[row2][col2];
|
||||||
|
//Add the new strings to the outputString
|
||||||
|
outputString += letter1;
|
||||||
|
outputString += letter2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return outputString;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Playfair::decode(std::string keyword, std::string input){
|
||||||
|
setKeyword(keyword);
|
||||||
|
setInputString(input);
|
||||||
|
return decode();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Playfair::setKeyword(std::string key){
|
||||||
|
//Make sure the keyword is blank
|
||||||
|
keyword = "";
|
||||||
|
//Remove all punctuation and make everything capital
|
||||||
|
for(int cnt = 0;cnt < key.size();++cnt){
|
||||||
|
//If it is an upper case letter, just add it to the keyword
|
||||||
|
if(isupper(key[cnt])){
|
||||||
|
keyword += key[cnt];
|
||||||
|
}
|
||||||
|
//If it is a lower case letter, make it upper case and add it to the keyword
|
||||||
|
else if(islower(key[cnt])){
|
||||||
|
keyword += toupper(key[cnt]);
|
||||||
|
}
|
||||||
|
//If it is not a letter, then just ignore it
|
||||||
|
}
|
||||||
|
//Create the grid from the new keyword
|
||||||
|
createGrid();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Playfair::getKeyword() const{
|
||||||
|
return keyword;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Playfair::setInputString(std::string input){
|
||||||
|
//Make sure inputString is empty
|
||||||
|
inputString = "";
|
||||||
|
//Remove all punctuation and make everything capital
|
||||||
|
for(int cnt = 0;cnt < input.size();++cnt){
|
||||||
|
char temp = input[cnt];
|
||||||
|
if(isupper(temp)){
|
||||||
|
//If the letter is the character than needs replaced, replace it
|
||||||
|
if(temp == REPLACED){
|
||||||
|
temp = REPLACER;
|
||||||
|
}
|
||||||
|
inputString += temp;
|
||||||
|
}
|
||||||
|
else if(islower(temp)){
|
||||||
|
temp = toupper(temp);
|
||||||
|
//If the letter is the character than needs replaced, replace it
|
||||||
|
if(temp == REPLACED){
|
||||||
|
temp = REPLACER;
|
||||||
|
}
|
||||||
|
inputString += temp;
|
||||||
|
}
|
||||||
|
//If it is not a letter do nothing to it
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if anything is doubled and needs bumped down by DOUBLED
|
||||||
|
for(int cnt = 1;cnt < inputString.size();){
|
||||||
|
char letter1, letter2;
|
||||||
|
//Get two adjacent letters and compare them
|
||||||
|
letter1 = inputString[cnt - 1];
|
||||||
|
letter2 = inputString[cnt];
|
||||||
|
//If they are the same insert DOUBLED between them
|
||||||
|
if(letter1 == letter2){
|
||||||
|
inputString.insert((inputString.begin() + cnt), DOUBLED);
|
||||||
|
}
|
||||||
|
//If they are not the same, do nothing
|
||||||
|
|
||||||
|
//Advance the counter by 2
|
||||||
|
cnt += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if the string length is odd and add DOUBLED to the end if it is
|
||||||
|
if((inputString.size() % 2) == 1){
|
||||||
|
inputString += DOUBLED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Playfair::getInputString() const{
|
||||||
|
return inputString;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Playfair::getOutputString() const{
|
||||||
|
return outputString;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Playfair::getGrid() const{
|
||||||
|
std::string temp;
|
||||||
|
for(int row = 0;row < 5;++row){
|
||||||
|
for(int col = 0;col < 5;++col){
|
||||||
|
temp += grid[row][col] + " ";
|
||||||
|
}
|
||||||
|
temp += '\n';
|
||||||
|
}
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
char Playfair::getReplaced(){
|
||||||
|
return REPLACED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Playfair::setReplaced(const char replaced){
|
||||||
|
//Make sure the letter is in the correct range
|
||||||
|
if(replaced >= 'A' && replaced <= 'Z'){
|
||||||
|
//Make sure the letter is not the same as the one that is replacing it
|
||||||
|
if(replaced != REPLACER){
|
||||||
|
REPLACED = replaced;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(replaced >= 'a' && replaced <= 'z'){
|
||||||
|
REPLACED = toupper(replaced);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char Playfair::getReplacer(){
|
||||||
|
return REPLACER;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Playfair::setReplacer(const char replacer){
|
||||||
|
//Make sure the letter is in the correct range
|
||||||
|
if(replacer >= 'A' && replacer <='Z'){
|
||||||
|
//Make sure the letter is not the same as the one that it is replacing
|
||||||
|
if(replacer != REPLACED){
|
||||||
|
REPLACER = replacer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(replacer >= 'a' && replacer <= 'z'){
|
||||||
|
REPLACER = toupper(replacer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char Playfair::getDoubled(){
|
||||||
|
return DOUBLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Playfair::setDoubled(const char doubled){
|
||||||
|
//Make sure the letter is in the correct range
|
||||||
|
if(doubled >= 'A' && doubled <= 'Z'){
|
||||||
|
DOUBLED = doubled;
|
||||||
|
}
|
||||||
|
else if(doubled >= 'a' && doubled <= 'z'){
|
||||||
|
DOUBLED = toupper(doubled);
|
||||||
|
}
|
||||||
|
}
|
||||||
33
main.cpp
33
main.cpp
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
#ifdef TEST_VERSION
|
#ifdef TEST_VERSION
|
||||||
#define CAESAR_TEST
|
#define CAESAR_TEST
|
||||||
//#define PLAYFAIR_TEST
|
#define PLAYFAIR_TEST
|
||||||
enum codingState { ENCODE, DECODE };
|
enum codingState { ENCODE, DECODE };
|
||||||
std::string testingError(codingState type, const std::string& input, const std::string& output, const std::string& cipher);
|
std::string testingError(codingState type, const std::string& input, const std::string& output, const std::string& cipher);
|
||||||
#endif //TEST_VERSION definition
|
#endif //TEST_VERSION definition
|
||||||
@@ -50,6 +50,7 @@ int main(int argc, char** argv){
|
|||||||
else{
|
else{
|
||||||
resultString += "Caesar Cipher error:\n" + errorString;
|
resultString += "Caesar Cipher error:\n" + errorString;
|
||||||
}
|
}
|
||||||
|
std::cout << "Test1: " << resultString << std::endl;
|
||||||
//Reset the variables
|
//Reset the variables
|
||||||
errorString = "";
|
errorString = "";
|
||||||
testResult = false;
|
testResult = false;
|
||||||
@@ -173,7 +174,35 @@ bool caesarTest(std::string& errorString){
|
|||||||
|
|
||||||
#ifdef PLAYFAIR_TEST
|
#ifdef PLAYFAIR_TEST
|
||||||
bool playfairTest(std::string& errorString){
|
bool playfairTest(std::string& errorString){
|
||||||
|
bool passed = true;
|
||||||
|
std::string keyword, inputString, outputString, cipherString;
|
||||||
|
Playfair cipher;
|
||||||
|
|
||||||
|
//Test from wikipedia
|
||||||
|
keyword = "Playfair Example";
|
||||||
|
inputString = "Hide the gold in the tree stump";
|
||||||
|
outputString = "BMODZBXDNABEKUDMUIXMMOUVIF";
|
||||||
|
//Setup the cipher
|
||||||
|
cipherString = cipher.encode(keyword, inputString);
|
||||||
|
//If the cipher didn't spit out the correct string throw an error
|
||||||
|
if(cipherString != outputString){
|
||||||
|
errorString += testingError(ENCODE, inputString, outputString, cipherString);
|
||||||
|
passed = false;
|
||||||
|
}
|
||||||
|
//This removes the spaces and turns everything capital so the reverse will work correctly
|
||||||
|
inputString = cipher.getInputString();
|
||||||
|
|
||||||
|
//Do the same thing in reverse
|
||||||
|
cipher.reset();
|
||||||
|
cipherString = cipher.decode(keyword, outputString);
|
||||||
|
//If the cipher didn't spit out the correct string throw an error
|
||||||
|
if(cipherString != inputString){
|
||||||
|
errorString += testingError(DECODE, outputString, inputString, cipherString);
|
||||||
|
passed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Return if the cipher passed the tests
|
||||||
|
return passed;
|
||||||
}
|
}
|
||||||
#endif //PLAYFAIR_TEST
|
#endif //PLAYFAIR_TEST
|
||||||
|
|
||||||
@@ -185,7 +214,7 @@ enum CipherFlagLocation { CAESAR, PLAYFAIR };
|
|||||||
void getFlags(bool flags[]);
|
void getFlags(bool flags[]);
|
||||||
|
|
||||||
int main(int argc, char** argv){
|
int main(int argc, char** argv){
|
||||||
|
//Add the ability to input and output files with the appropriate strings
|
||||||
}
|
}
|
||||||
|
|
||||||
void getFlags(bool flags[]){
|
void getFlags(bool flags[]){
|
||||||
|
|||||||
1
makefile
1
makefile
@@ -14,6 +14,7 @@ libPlayfair.a: SourceFiles/Playfair.cpp
|
|||||||
Ciphers: main.cpp
|
Ciphers: main.cpp
|
||||||
(CXX) -O3 -std=c++11 -o $@ $< -lCaesar -lPlayfair
|
(CXX) -O3 -std=c++11 -o $@ $< -lCaesar -lPlayfair
|
||||||
|
|
||||||
|
#Linux
|
||||||
libCaesar.lib: SourceFiles/Caesar.cpp
|
libCaesar.lib: SourceFiles/Caesar.cpp
|
||||||
g++ -shared -std=c++11 -O3 -fPIC -o $@ $<
|
g++ -shared -std=c++11 -O3 -fPIC -o $@ $<
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user