#include #include #include #include #include #include #include #include #include #include const std::string ADFGVX = "ADFGVX"; const std::string ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; std::random_device random; std::mt19937 mersenne_twister(random()); std::vector> initialise_polybius_square() { std::vector letters(ALPHABET.begin(), ALPHABET.end()); std::shuffle(letters.begin(), letters.end(), mersenne_twister); std::vector> result = { 6, std::vector(6, 0) }; for ( int32_t row = 0; row < 6; ++row ) { for ( int32_t column = 0; column < 6; ++column ) { result[row][column] = letters[6 * row + column]; } } return result; } // Create a key using a word from the dictionary 'unixdict.txt' std::string create_key(const uint64_t& size) { if ( size < 7 || size > 12 ) { throw std::invalid_argument("Key should contain between 7 and 12 letters, both inclusive."); } std::vector candidates; std::fstream file_stream; file_stream.open("../unixdict.txt"); std::string word; while ( file_stream >> word ) { if ( word.length() == size && word.length() == std::unordered_set{ word.begin(), word.end() }.size() ) { std::transform(word.begin(), word.end(), word.begin(), [](const char& ch){ return std::toupper(ch); }); if ( word.find_first_not_of(ALPHABET) == std::string::npos ) { candidates.emplace_back(word); } } } std::shuffle(candidates.begin(), candidates.end(), mersenne_twister); std::string key = candidates[0]; return key; } std::string encrypt(const std::string& plain_text, const std::vector>& polybius, const std::string& key) { std::string code = ""; for ( const char& ch : plain_text ) { for ( int32_t row = 0; row < 6; ++row ) { for ( int32_t column = 0; column < 6; ++column ) { if ( polybius[row][column] == ch ) { code += ADFGVX[row]; code += ADFGVX[column]; } } } } std::string encrypted = ""; for ( const char& ch : key ) { for ( uint64_t i = key.find(ch); i < code.length(); i += key.length() ) { encrypted += code[i]; } encrypted += " "; } return encrypted; } std::string decrypt(const std::string& encrypted_text, const std::vector>& polybius, const std::string& key) { const uint64_t space_count = std::count(encrypted_text.begin(), encrypted_text.end(), ' '); const uint64_t code_size = encrypted_text.length() - space_count; std::vector blocks; std::stringstream stream(encrypted_text); std:: string word; while ( stream >> word ) { blocks.emplace_back(word); } std::string code = ""; for ( int32_t i = 0; code.length() < code_size; ++i ) { for ( const std::string& block : blocks ) { if ( code.length() < code_size ) { code += block[i]; } } } std::string plain_text = ""; for ( uint64_t i = 0; i < code_size - 1; i += 2 ) { int32_t row = ADFGVX.find(code[i]); int32_t column = ADFGVX.find(code[i + 1]); plain_text += polybius[row][column]; } return plain_text; } int main() { const std::vector> polybius = initialise_polybius_square(); std::cout << "The 6 x 6 Polybius square:" << std::endl; std::cout << " | A D F G V X" << std::endl; std::cout << "--------------" << std::endl; for ( int32_t row = 0; row < 6; ++row ) { std::cout << ADFGVX[row] << "|"; for ( int32_t column = 0; column < 6; ++column ) { std::cout << " " << polybius[row][column]; } std::cout << std::endl; } std::cout << std::endl; const std::string key = create_key(9); std::cout << "The key is " << key << std::endl << std::endl; const std::string plain_text = "ATTACKAT1200AM"; std::cout << "Plain text: " << plain_text <