From 58adbfc473f84cdb6c8da597a055c28fbd6eb497 Mon Sep 17 00:00:00 2001 From: Shaun Reed Date: Thu, 22 Jul 2021 10:50:29 -0400 Subject: [PATCH] Update columnar-transposition example + Use inheritance to provide base class for key based ciphers --- cpp/README.md | 1 + .../columnar-transposition/driver.cpp | 6 +- .../columnar-transposition/lib-cipher.cpp | 63 ++++++++----------- .../columnar-transposition/lib-cipher.hpp | 57 +++++++++++------ 4 files changed, 69 insertions(+), 58 deletions(-) diff --git a/cpp/README.md b/cpp/README.md index 60aa95d..80801a0 100644 --- a/cpp/README.md +++ b/cpp/README.md @@ -4,6 +4,7 @@ shaunrd0/klips/cpp/ ├── algorithms # Examples of various algorithms written in C++ ├── cmake # Example of using cmake to build and organize larger projects +├── cryptography# Examples of encrypting / decrypting using ciphers in C++ ├── datastructs # Collection of useful datastructures written in C++ ├── graphics # Examples of graphics projects written in C++ ├── patterns # Examples of various design patterns written in C++ diff --git a/cpp/cryptography/columnar-transposition/driver.cpp b/cpp/cryptography/columnar-transposition/driver.cpp index da69af3..187eafa 100644 --- a/cpp/cryptography/columnar-transposition/driver.cpp +++ b/cpp/cryptography/columnar-transposition/driver.cpp @@ -27,10 +27,10 @@ int main (const int argc, const char * argv[]) { // Using example keyword from www.braingle.com // + The embedded example there doesn't seem to support numbers in keywords :( - CipherData cData("ZEBRAS"); + Columnar cData("ZEBRAS"); - // Taking user input for keyword using CipherData ctor -// CipherData cData; + // Taking user input for keyword using Columnar ctor +// Columnar cData; int choice = 0; bool exit = false; diff --git a/cpp/cryptography/columnar-transposition/lib-cipher.cpp b/cpp/cryptography/columnar-transposition/lib-cipher.cpp index 7cbf9fe..03d5a3f 100644 --- a/cpp/cryptography/columnar-transposition/lib-cipher.cpp +++ b/cpp/cryptography/columnar-transposition/lib-cipher.cpp @@ -10,8 +10,9 @@ #include "lib-cipher.hpp" -// Initializes orderVect to determine order columns should be used -void CipherData::InitOrder(std::string temp) +KeyData::~KeyData() {} + +void Columnar::InitOrder(std::string temp) { // Create a temp value sorted lexicographically, remove duplicate characters // https://en.cppreference.com/w/cpp/string/basic_string/operator_cmp @@ -32,38 +33,8 @@ void CipherData::InitOrder(std::string temp) } -// Allows getting keyWord when using CipherData default ctor -std::string CipherData::GetKey() +void Columnar::ValidateKeyword(const std::string &message) { - std::string key; - std::cout << "Enter the keyword: "; - std::getline(std::cin, key); - std::cout << "Keyword entered: \"" << key << "\"\n"; - return key; -} - -// Transpose a character matrix, using a vector of strings -void CipherData::Transpose(const std::vector &in, - std::vector &out) -{ - int cols = in[0].size(); - // JIC some other row is larger than the first - for (const auto &row : in) cols = (row.size() > cols) ? row.size() : cols; - int rows = in.size(); - - out.resize(cols); - - for (int i = 0; i < cols; i++) { - for (int j = 0; j < rows; j++) { - if (in[j].size() <= i) continue; - out[i] += in[j][i]; - } - } -} - -void CipherData::ValidateKeyword(const std::string &message) -{ - if (keyWord_.size() < message.size()) return; // Pop letters from keyWord until it is < message.size() while (keyWord_.size() >= message.size()) keyWord_.pop_back(); // Do not append order to a previous orderVect; Erase it first @@ -72,7 +43,25 @@ void CipherData::ValidateKeyword(const std::string &message) InitOrder(keyWord_); } -std::string CipherData::Encrypt(std::string message) +void Columnar::Transpose(const std::vector &in, + std::vector &out) +{ + size_t cols = in[0].size(); + // JIC some other row is larger than the first + for (const auto &row : in) cols = (row.size() > cols) ? row.size() : cols; + size_t rows = in.size(); + + out.resize(cols); + + for (size_t i = 0; i < cols; i++) { + for (size_t j = 0; j < rows; j++) { + if (in[j].size() <= i) continue; + out[i] += in[j][i]; + } + } +} + +std::string Columnar::Encrypt(std::string message) { // If no message was provided, ask for one if (message.empty()) { @@ -80,7 +69,7 @@ std::string CipherData::Encrypt(std::string message) std::getline(std::cin, message); std::cout << "Encrypting message \"" << message << "\"\n"; } - ValidateKeyword(message); + if (keyWord_.size() >= message.size()) ValidateKeyword(message); std::string encryptedMessage; std::vector rows; @@ -99,7 +88,7 @@ std::string CipherData::Encrypt(std::string message) return encryptedMessage; } -std::string CipherData::Decrypt(std::string message) +std::string Columnar::Decrypt(std::string message) { // If no message was provided, ask for one if (message.empty()) { @@ -107,7 +96,7 @@ std::string CipherData::Decrypt(std::string message) std::getline(std::cin, message); std::cout << "Decrypting message \"" << message << "\"\n"; } - ValidateKeyword(message); + if (keyWord_.size() >= message.size()) ValidateKeyword(message); std::string decryptedMessage; std::vector rows; diff --git a/cpp/cryptography/columnar-transposition/lib-cipher.hpp b/cpp/cryptography/columnar-transposition/lib-cipher.hpp index 22d3ebd..f414e62 100644 --- a/cpp/cryptography/columnar-transposition/lib-cipher.hpp +++ b/cpp/cryptography/columnar-transposition/lib-cipher.hpp @@ -16,37 +16,58 @@ #include /******************************************************************************/ -// CipherData struct to hold data and methods related to encrypting / decrypting -struct CipherData { +// KeyData struct to hold data related to key ciphers +struct KeyData { + explicit KeyData(std::string key) : keyWord_(std::move(key)) {}; + explicit KeyData() : keyWord_(GetKey()) {}; + // Pure virtual dtor to make abstract class despite no pure virtual members + virtual ~KeyData() = 0; + + // Allows getting keyWord when using KeyData default ctor + static std::string GetKey() + { + std::string key; + std::cout << "Enter the keyword: "; + std::getline(std::cin, key); + std::cout << "Keyword entered: \"" << key << "\"\n"; + return key; + } + +protected: + std::string keyWord_; +}; +// Definition of pure virtual dtor + +/******************************************************************************/ +// Columnar struct to define methods related to columnar transposition +struct Columnar : KeyData { // Can't create this object without providing a keyWord to initialize order - explicit CipherData(std::string keyWord) : keyWord_(std::move(keyWord)) + explicit Columnar(std::string keyWord) : KeyData(std::move(keyWord)) { InitOrder(keyWord_); } - CipherData() : keyWord_(GetKey()) { InitOrder(keyWord_);} + // Inherit call to GetKey() from KeyData default ctor + Columnar() { InitOrder(keyWord_);} - /****************************************************************************/ - // Member functions - - // Initializes orderVect, pass by value to create local copy of keyWord + // Initializes orderVect to determine order columns should be used void InitOrder(std::string temp); - static std::string GetKey(); - static void - Transpose(const std::vector &in, std::vector &out); + /****************************************************************************/ + // Member function definitions - // Default values for param allows calling with no message + void ValidateKeyword(const std::string &message); + + // Transpose a character matrix, using a vector of strings + static void Transpose(const std::vector &in, + std::vector &out); + + // Default parameter allows calling Encrypt() to take message input std::string Encrypt(std::string message=""); + // Default parameter allows calling Decrypt() to take message input std::string Decrypt(std::string message=""); private: - // Used to make a valid keyword from an invalid keyWord - // + Still encrypts / decrypts with whatever the user inputs as keyWord - // + But technically the keyword is modified without the user knowing :) - void ValidateKeyword(const std::string &message); - - std::string keyWord_; std::vector orderVect_; };