From c8683680dd267dcbf551c5cf8cd9d40e2951b72e Mon Sep 17 00:00:00 2001 From: Shaun Reed Date: Tue, 20 Jul 2021 11:21:59 -0400 Subject: [PATCH] Add subdirectory for cryptography examples + Add example using columnar transposition for encrypting / decrypting messages + Fix cmake build error from duplicate lib-bst when building from project root --- cpp/CMakeLists.txt | 1 + cpp/algorithms/trees/binary/CMakeLists.txt | 6 +- cpp/cryptography/CMakeLists.txt | 18 +++ .../columnar-transposition/CMakeLists.txt | 22 +++ .../columnar-transposition/driver.cpp | 85 ++++++++++++ .../columnar-transposition/lib-cipher.cpp | 127 ++++++++++++++++++ .../columnar-transposition/lib-cipher.hpp | 48 +++++++ 7 files changed, 304 insertions(+), 3 deletions(-) create mode 100644 cpp/cryptography/CMakeLists.txt create mode 100644 cpp/cryptography/columnar-transposition/CMakeLists.txt create mode 100644 cpp/cryptography/columnar-transposition/driver.cpp create mode 100644 cpp/cryptography/columnar-transposition/lib-cipher.cpp create mode 100644 cpp/cryptography/columnar-transposition/lib-cipher.hpp diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 8d71069..76a63b2 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -19,6 +19,7 @@ project( add_subdirectory(algorithms) add_subdirectory(cmake) +add_subdirectory(cryptography) add_subdirectory(datastructs) add_subdirectory(graphics) add_subdirectory(patterns) diff --git a/cpp/algorithms/trees/binary/CMakeLists.txt b/cpp/algorithms/trees/binary/CMakeLists.txt index 1020e60..664c83d 100644 --- a/cpp/algorithms/trees/binary/CMakeLists.txt +++ b/cpp/algorithms/trees/binary/CMakeLists.txt @@ -15,7 +15,7 @@ project ( LANGUAGES CXX ) -add_library(lib-bst "bst.cpp") +add_library(lib-bst-algo "bst.cpp") -add_executable(test-bst "driver.cpp") -target_link_libraries(test-bst lib-bst) +add_executable(test-bst-algo "driver.cpp") +target_link_libraries(test-bst-algo lib-bst) diff --git a/cpp/cryptography/CMakeLists.txt b/cpp/cryptography/CMakeLists.txt new file mode 100644 index 0000000..e1576ba --- /dev/null +++ b/cpp/cryptography/CMakeLists.txt @@ -0,0 +1,18 @@ +############################################################################### +## Author: Shaun Reed ## +## Legal: All Content (c) 2021 Shaun Reed, all rights reserved ## +## About: A root project for practicing cryptography in C++ ## +## ## +## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## +############################################################################## +# +cmake_minimum_required(VERSION 3.15) + +project ( + #[[NAME]] Cryptography + VERSION 1.0 + DESCRIPTION "A project for practicing cryptography in C++" + LANGUAGES CXX +) + +add_subdirectory(columnar-transposition) diff --git a/cpp/cryptography/columnar-transposition/CMakeLists.txt b/cpp/cryptography/columnar-transposition/CMakeLists.txt new file mode 100644 index 0000000..5b54e7f --- /dev/null +++ b/cpp/cryptography/columnar-transposition/CMakeLists.txt @@ -0,0 +1,22 @@ +################################################################################ +## Author: Shaun Reed ## +## Legal: All Content (c) 2021 Shaun Reed, all rights reserved ## +## About: A root project for practicing columnar transposition cipher in C++ ## +## ## +## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## +################################################################################ +# + +cmake_minimum_required(VERSION 3.15) + +project( + #[[NAME]] ColumnarTransposition + VERSION 1.0 + DESCRIPTION "Practice implementing columnar transposition in C++" + LANGUAGES CXX +) + +add_library(lib-cipher "lib-cipher.cpp") + +add_executable(columnar-transposition-test "driver.cpp") +target_link_libraries(columnar-transposition-test lib-cipher) diff --git a/cpp/cryptography/columnar-transposition/driver.cpp b/cpp/cryptography/columnar-transposition/driver.cpp new file mode 100644 index 0000000..fa82a67 --- /dev/null +++ b/cpp/cryptography/columnar-transposition/driver.cpp @@ -0,0 +1,85 @@ +/*############################################################################## +## Author: Shaun Reed ## +## Legal: All Content (c) 2021 Shaun Reed, all rights reserved ## +## About: An example of using columnar transposition cipher ## +## + Using concept at www.braingle.com/brainteasers/codes/columnartrans.php ## +## ## +## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## +################################################################################ +*/ + +#include "lib-cipher.hpp" + +#include + +// Columnar transposition cipher +// https://www.braingle.com/brainteasers/codes/columnartrans.php#form +// NOTE: Must check the 'irregular case' box to produce same results +// + I only used the irregular case to encrypt and decrypt +// + I did not write any code for testing with the regular case + + +/******************************************************************************/ +// Main program loop +int main (const int argc, const char * argv[]) { + // Left some test cases I used commented out :) + + // Using example keyword from www.braingle.com + // + The embedded example there doesn't seem to support numbers in keywords :( + CipherData cData("ZEBRAS"); + + // Taking user input for keyword using CipherData ctor +// CipherData cData; + + int choice = 0; + bool exit = false; + std::string message; // Message to encrypt or decrypt + while (!exit) { + + std::string result; + switch (choice) { + case 1: + std::cout << "\nEncrypting...\n"; + + // Encrypt example from www.braingle.com + result = cData.Encrypt("WEAREDISCOVEREDFLEEATONCE"); + + // Take input for encrypting a message +// result = cData.Encrypt(); + + std::cout << "Encrypted message: " << result << std::endl; + exit = true; + break; + + case 2: + std::cout << "\nDecrypting...\n"; + + // Encrypt, decrypt example from www.braingle.com + result = cData.Decrypt(cData.Encrypt("WEAREDISCOVEREDFLEEATONCE")); + + // Take input for previously encrypted message to decrypt +// result = cData.Decrypt(); + + std::cout << "Decrypted message: " << result << std::endl; + exit = true; + break; + + default: + std::cout << "What would you like to do?\n1. Encrypt\n2. Decrypt\n"; + // Take input, handle it accordingly + // + https://www.cplusplus.com/forum/general/207458/ + if (!(std::cin >> choice)) { + std::cout << "Invalid character input, choose an option below\n"; + } + else if (choice != 1 && choice != 2) { + std::cout << "Incorrect option entered (" << choice << ")\n"; + } + std::cin.clear(); + std::cin.ignore(); + break; + } + + } + + return 0; +} diff --git a/cpp/cryptography/columnar-transposition/lib-cipher.cpp b/cpp/cryptography/columnar-transposition/lib-cipher.cpp new file mode 100644 index 0000000..11450e5 --- /dev/null +++ b/cpp/cryptography/columnar-transposition/lib-cipher.cpp @@ -0,0 +1,127 @@ +/*############################################################################## +## Author: Shaun Reed ## +## Legal: All Content (c) 2021 Shaun Reed, all rights reserved ## +## About: An example of using columnar transposition cipher ## +## + Using concept at www.braingle.com/brainteasers/codes/columnartrans.php ## +## ## +## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## +################################################################################ +*/ + +#include "lib-cipher.hpp" + +// Initializes orderVect to determine order columns should be used +void CipherData::InitOrder(std::string temp) +{ + // Create a temp value sorted lexicographically, remove duplicate characters + // https://en.cppreference.com/w/cpp/string/basic_string/operator_cmp + std::sort(temp.begin(), temp.end()); + auto it = std::unique(temp.begin(), temp.end()); + temp.erase(it, temp.end()); + + // Step through each character in lexicographic order + for (int i = 0; i < temp.size(); i++) { + // Check each character in the keyWord for the current lexicographic char + for (int j = 0; j < keyWord_.size(); j++) { + // If they are equal, push the index of the char in keyWord to orderVect + if (keyWord_[j] == temp[i]) { + orderVect_.push_back(j); + } + } + } + +} + +// Allows getting keyWord when using CipherData default ctor +std::string CipherData::GetKey() +{ + std::string key; + std::cout << "Enter the keyword: "; + std::getline(std::cin, key); + std::cout << "Keyword entered: " << key << std::endl; + 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]; + } + } +} + +std::string CipherData::Encrypt(std::string message) +{ + // If no message was provided, ask for one + if (message.empty()) { + std::cout << "Input message to encrypt: "; + std::getline(std::cin, message); + std::cout << "Encrypting message \"" << message << "\"\n"; + } + std::string encryptedMessage; + std::vector rows; + + // Split the message into rows equal to the length of our keyWord + for (size_t i = 0; i < message.size(); i+=keyWord_.size()) { + std::string substr = message.substr(i, keyWord_.size()); + rows.push_back(substr); + } + + // Transpose the matrix of characters + std::vector transposed; + Transpose(rows, transposed); + + // Append each row of the transposed matrix to our encryptedMessage + for (const auto &val : orderVect_) encryptedMessage += transposed[val]; + return encryptedMessage; +} + +std::string CipherData::Decrypt(std::string message) +{ + // If no message was provided, ask for one + if (message.empty()) { + std::cout << "Input message to decrypt: "; + std::getline(std::cin, message); + std::cout << "Decrypting message \"" << message << "\"\n"; + } + std::string result; + std::vector rows; + + // Split the message into rows equal to the length of our keyWord + int rowLength = message.size() / keyWord_.size(); + // If dividing message and keyword size has a remainder N + // + There will be N rows with +1 characters + int fullRows = message.size() % keyWord_.size(); + + rows.resize(orderVect_.size()); + // Track the ending position after each substring is taken + int lastPos = 0; + for (int i = 0; i < orderVect_.size(); i++) { + // If we are assigning to any row < fullRows, it should have + 1 character + if (orderVect_[i] < fullRows) { + rows[orderVect_[i]] = message.substr(lastPos, rowLength + 1); + lastPos += rowLength + 1; + } + else { + rows[orderVect_[i]] = message.substr(lastPos, rowLength); + lastPos += rowLength; + } + } + + std::vector transposed; + Transpose(rows, transposed); + + for (const auto &row : transposed) result += row; + return result; +} diff --git a/cpp/cryptography/columnar-transposition/lib-cipher.hpp b/cpp/cryptography/columnar-transposition/lib-cipher.hpp new file mode 100644 index 0000000..24aeed2 --- /dev/null +++ b/cpp/cryptography/columnar-transposition/lib-cipher.hpp @@ -0,0 +1,48 @@ +/*############################################################################## +## Author: Shaun Reed ## +## Legal: All Content (c) 2021 Shaun Reed, all rights reserved ## +## About: An example of using columnar transposition cipher ## +## + Using concept at www.braingle.com/brainteasers/codes/columnartrans.php ## +## ## +## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## +################################################################################ +*/ + +#ifndef COLUMNARTRANSPOSITION_LIB_CIPHER_HPP +#define COLUMNARTRANSPOSITION_LIB_CIPHER_HPP + +#include +#include +#include + +/******************************************************************************/ +// CipherData struct to hold data and methods related to encrypting / decrypting +struct CipherData { + // Can't create this object without providing a keyWord to initialize order + explicit CipherData(std::string keyWord) : keyWord_(std::move(keyWord)) + { + InitOrder(keyWord_); + } + CipherData() : keyWord_(GetKey()) { InitOrder(keyWord_);} + + /****************************************************************************/ + // Member functions + + // Initializes orderVect, pass by value to create local copy of keyWord + void InitOrder(std::string temp); + + static std::string GetKey(); + + static void + Transpose(const std::vector &in, std::vector &out); + + // Default values for param allows calling with no message + std::string Encrypt(std::string message=""); + std::string Decrypt(std::string message=""); + +private: + std::string keyWord_; + std::vector orderVect_; +}; + +#endif // COLUMNARTRANSPOSITION_LIB_CIPHER_HPP