Created
April 13, 2020 14:19
-
-
Save Animesh-Ghosh/d143ddc16d23d6ffd2661844915d4082 to your computer and use it in GitHub Desktop.
Some ciphers.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| To build | |
| g++ crypt.cpp -o crypt.exe -std=c++11 -Wall -Wextra -O2 | |
| */ | |
| #include <iostream> | |
| #include <algorithm> | |
| #include <array> | |
| #include <vector> | |
| #include <set> | |
| #include <map> | |
| #include <chrono> | |
| #include <random> | |
| // abstract base class with pure virtual methods to be overloaded | |
| // for each type of cipher that inherits from this class | |
| class Crypt { | |
| protected: | |
| std::string message; // message string which will be mutated | |
| public: | |
| Crypt() : message("") { | |
| std::cout << "Constructing Crypt with no message.\n"; | |
| } | |
| Crypt(const std::string &message) : message(message) { | |
| std::cout << "Constructing Crypt with message: " << message << '\n'; | |
| } | |
| ~Crypt() { | |
| std::cout << "Destroying Crypt...\n"; | |
| } | |
| virtual void setMessage(const std::string &message) { | |
| this->message = message; | |
| } | |
| // pure virtual method declarations | |
| virtual std::string Encrypt() = 0; | |
| virtual std::string Decrypt() = 0; | |
| }; | |
| // Ceasar cipher which moves characters by 3 values | |
| class CeasarCipher : public Crypt { | |
| protected: | |
| static const std::array<char, 26> alphabets; | |
| // helper method to get index of a character (all lower case) | |
| // protected so as to be used by derived class as well | |
| unsigned int getIdx(const char &c) { | |
| for (unsigned int i = 0; i < alphabets.size(); ++i) { | |
| if (alphabets[i] == c) { | |
| return i; | |
| } | |
| } | |
| return 0; | |
| } | |
| public: | |
| CeasarCipher() : Crypt() {} | |
| CeasarCipher(const std::string &message) | |
| : Crypt(message) {} | |
| ~CeasarCipher() { | |
| std::cout << "Destroying CeasarCipher...\n"; | |
| } | |
| std::string Encrypt() { | |
| if (message == "") { | |
| return "No message to encrypt!"; | |
| } | |
| std::for_each(message.begin(), message.end(), [&](char &c) { | |
| c = alphabets[(getIdx(c) + 3) % alphabets.size()]; | |
| }); | |
| return message; | |
| } | |
| std::string Decrypt() { | |
| if (message == "") { | |
| return "No message to decrypt!"; | |
| } | |
| std::for_each(message.begin(), message.end(), [&](char &c) { | |
| int idx = getIdx(c) - 3; | |
| c = alphabets[idx < 0 ? alphabets.size() + idx : idx]; | |
| }); | |
| return message; | |
| } | |
| }; | |
| const std::array<char, 26> CeasarCipher::alphabets = { | |
| 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', | |
| 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' | |
| }; | |
| // extended Ceasar cipher which moves characters any given amount of value | |
| class CeasarCipherExt : public CeasarCipher { | |
| protected: | |
| const unsigned int key; | |
| public: | |
| CeasarCipherExt() : CeasarCipher(), key(1u) { | |
| std::cout << "Constructing CeasarCipherExt with key: " << key << '\n'; | |
| } | |
| CeasarCipherExt(const std::string &message, unsigned int key) | |
| : CeasarCipher(message), key(key) { | |
| std::cout << "Constructing CeasarCipherExt with key: " << key << '\n'; | |
| } | |
| ~CeasarCipherExt() { | |
| std::cout << "Destroying CeasarCipherExt...\n"; | |
| } | |
| std::string Encrypt() { | |
| if (message == "") { | |
| return "No message to encrypt!"; | |
| } | |
| std::for_each(message.begin(), message.end(), [&](char &c) { | |
| c = alphabets[(getIdx(c) + key) % alphabets.size()]; | |
| }); | |
| return message; | |
| } | |
| std::string Decrypt() { | |
| if (message == "") { | |
| return "No message to decrypt!"; | |
| } | |
| std::for_each(message.begin(), message.end(), [&](char &c) { | |
| int idx = getIdx(c) - key; | |
| c = alphabets[idx < 0 ? alphabets.size() + idx : idx]; | |
| }); | |
| return message; | |
| } | |
| }; | |
| template<typename T> | |
| std::ostream& operator<<(std::ostream &os, const std::vector<T> &v) { | |
| for (const T &x : v) { | |
| os << x << ' '; | |
| } | |
| return os; | |
| } | |
| // Rail fence cipher | |
| class RailFence : public Crypt { | |
| private: | |
| std::vector<char> upperFence, lowerFence; | |
| void constructFences() { | |
| for (unsigned int i = 0; i < message.size(); ++i) { | |
| if (i % 2 == 0) { | |
| upperFence.push_back(message[i]); | |
| } | |
| else { | |
| lowerFence.push_back(message[i]); | |
| } | |
| } | |
| } | |
| public: | |
| RailFence() : Crypt() {} | |
| RailFence(const std::string &message) : Crypt(message) { | |
| constructFences(); | |
| } | |
| ~RailFence() { | |
| std::cout << "Destroying RailFence...\n"; | |
| } | |
| void setMessage(const std::string &message) { | |
| this->message = message; | |
| constructFences(); | |
| } | |
| std::string Encrypt() { | |
| if (message == "") { | |
| return "No message to encrypt!"; | |
| } | |
| std::string newMessage; | |
| for (const char &c : upperFence) { | |
| newMessage.push_back(c); | |
| } | |
| for (const char &c : lowerFence) { | |
| newMessage.push_back(c); | |
| } | |
| message = newMessage; | |
| return message; | |
| } | |
| std::string Decrypt() { | |
| if (message == "") { | |
| return "No message to decrypt!"; | |
| } | |
| std::string newMessage; | |
| for (const char &c : upperFence) { | |
| newMessage.push_back(c); | |
| newMessage.push_back(0); // appending empty character | |
| } | |
| for (unsigned int i = 0, k = 0; i < newMessage.size(); ++i) { | |
| if (newMessage[i] == 0) { | |
| newMessage[i] = lowerFence[k++]; | |
| } | |
| } | |
| message = newMessage; | |
| return message; | |
| } | |
| }; | |
| template<typename T> | |
| std::ostream& operator<<(std::ostream &os, const std::set<T> &s) { | |
| std::for_each(s.begin(), s.end(), [&](const T &x) { | |
| os << x << ' '; | |
| }); | |
| return os; | |
| } | |
| template<typename key, typename value> | |
| std::ostream& operator<<(std::ostream &os, const std::map<key, value> &map) { | |
| for (auto it = map.begin(); it != map.end(); ++it) { | |
| os << it->first << " -> " << it->second << '\n'; | |
| } | |
| return os; | |
| } | |
| class MonoAlpha : public Crypt { | |
| private: | |
| static const std::set<char> alphabets; | |
| std::map<char, char> charMap, reverseCharMap; | |
| void constructMaps() { | |
| using clock = std::chrono::system_clock; | |
| unsigned seed = clock::now().time_since_epoch().count(); | |
| std::default_random_engine generator(seed); | |
| std::set<char> assignedChars; | |
| std::for_each(alphabets.begin(), alphabets.end(), [&](const char &c) { | |
| const std::set<char> currentChar = { c }; | |
| std::vector<char> difference(alphabets.size()); | |
| auto it = std::set_difference( | |
| alphabets.begin(), alphabets.end(), | |
| currentChar.begin(), currentChar.end(), | |
| difference.begin() | |
| ); | |
| difference.resize(it - difference.begin()); | |
| std::uniform_int_distribution<int> distribution(0, difference.size() - 1); | |
| char replacement = difference[distribution(generator)]; | |
| if (charMap.size() > 0) { | |
| while (assignedChars.count(replacement) != 0) { | |
| replacement = difference[distribution(generator)]; | |
| } | |
| } | |
| charMap[c] = replacement; | |
| reverseCharMap[replacement] = c; | |
| assignedChars.insert(replacement); | |
| }); | |
| } | |
| public: | |
| MonoAlpha() : Crypt() {} | |
| MonoAlpha(const std::string &message) : Crypt(message) { | |
| constructMaps(); | |
| } | |
| ~MonoAlpha() { | |
| std::cout << "Destroying MonoAlpha...\n"; | |
| } | |
| void setMessage(const std::string &message) { | |
| this->message = message; | |
| constructMaps(); | |
| } | |
| std::string Encrypt() { | |
| if (message == "") { | |
| return "No message to encrypt!"; | |
| } | |
| for (char &c : message) { | |
| c = charMap.find(c)->second; | |
| } | |
| return message; | |
| } | |
| std::string Decrypt() { | |
| if (message == "") { | |
| return "No message to decrypt!"; | |
| } | |
| for (char& c : message) { | |
| c = reverseCharMap.find(c)->second; | |
| } | |
| return message; | |
| } | |
| }; | |
| const std::set<char> MonoAlpha::alphabets = { | |
| 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', | |
| 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' | |
| }; | |
| int main() { | |
| const std::string message = R"(a very long test message... | |
| so long that infact it can't be deciphered!)"; | |
| // CeasarCipher ceasar_cipher(message); | |
| // std::cout << ceasar_cipher.Encrypt() << '\n'; // newline, special characters (ASCII) not preserved | |
| // std::cout << ceasar_cipher.Decrypt() << '\n'; | |
| // CeasarCipherExt ceasar_cipher_ext(message, 5); | |
| // std::cout << ceasar_cipher_ext.Encrypt() << '\n'; // newline, special characters (ASCII) not preserved | |
| // std::cout << ceasar_cipher_ext.Decrypt() << '\n'; | |
| RailFence rail_fence_cipher(message); | |
| std::cout << rail_fence_cipher.Encrypt() << '\n'; | |
| std::cout << rail_fence_cipher.Decrypt() << '\n'; | |
| // MonoAlpha mono_alpha_cipher; | |
| // mono_alpha_cipher.setMessage(message); | |
| // std::cout << mono_alpha_cipher.Encrypt() << '\n'; // newline, special characters (ASCII) not preserved | |
| // std::cout << mono_alpha_cipher.Decrypt() << '\n'; | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment