Verschlüsselung mithilfe der Bacon-Chiffre [gelöst]
-
#include <cstdlib> #include <cctype> #include <cmath> #include <iterator> #include <algorithm> #include <bitset> #include <string> #include <iostream> char const encodable_chars[] { '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', '.', ' ' }; std::size_t get_encodable_chars_max_bits() { return static_cast<std::size_t>(std::log2(std::size(encodable_chars)) + 1); } void print_encodable_chars(std::ostream &os) { for (auto const ch : encodable_chars) os << '\'' << ch << "\', "; os << "\b\b \n"; } bool check_message(std::string const &message) { return std::all_of(std::begin(message), std::end(message), [](char ch) { return std::find(std::begin(encodable_chars), std::end(encodable_chars), ch) != std::end(encodable_chars); } ); } bool check_cipher(std::string const &cipher) { return std::all_of(std::begin(cipher), std::end(cipher), [](char ch) { return std::islower(ch) || std::isspace(ch) || std::ispunct(ch); } ); } std::size_t get_workable_size(std::string const &cipher) { std::size_t workable_size{}; for (auto const ch : cipher) { if (std::islower(ch)) ++workable_size; } return workable_size; } std::string encrypt(std::string const &message, std::string const &cipher) { std::string ciphertext; std::string cipherchunk; std::size_t usable_chunk_length{}; std::size_t const encodable_chars_max_bits{ get_encodable_chars_max_bits() }; auto cipher_iter{ std::begin(cipher) }; for (auto message_iter{ std::begin(message) }; message_iter != std::end(message) && cipher_iter != std::end(cipher); ++cipher_iter) { if (usable_chunk_length == encodable_chars_max_bits && message_iter != std::end(message)) { auto char_to_encode{ std::find(std::begin(encodable_chars), std::end(encodable_chars), *message_iter) }; auto value_to_encode{ std::distance(std::begin(encodable_chars), char_to_encode) }; auto encoded_value{ std::bitset<std::numeric_limits<char>::digits>(value_to_encode) }; std::size_t bit{}; for (auto chunk_iter = std::rbegin(cipherchunk); chunk_iter != std::rend(cipherchunk); ++chunk_iter) { if (std::islower(*chunk_iter)) { if (encoded_value[bit]) *chunk_iter = std::toupper(*chunk_iter); ++bit; } } ++message_iter; ciphertext += cipherchunk; cipherchunk = ""; usable_chunk_length = 0; } cipherchunk += *cipher_iter; if (std::islower(*cipher_iter)) ++usable_chunk_length; } if (cipher_iter != std::end(cipher)) ciphertext.append(cipher_iter, std::end(cipher)); return ciphertext; } std::string decrypt(std::string const &ciphertext, std::string const &cipher) { std::string chunk; std::size_t usable_chunk_length{}; std::size_t const encodable_chars_max_bits{ get_encodable_chars_max_bits() }; std::string message; for (auto ciphertext_iter{ std::begin(ciphertext) }; ciphertext_iter != std::end(ciphertext); ++ciphertext_iter) { if (usable_chunk_length == encodable_chars_max_bits) { std::size_t bit{}; std::bitset<std::numeric_limits<char>::digits> encoded_value; for (auto chunk_iter{ std::rbegin(chunk) }; chunk_iter != std::rend(chunk); ++chunk_iter) { if (std::islower(*chunk_iter) || std::isupper(*chunk_iter)) { if (std::isupper(*chunk_iter)) encoded_value[bit] = 1; ++bit; } } message += encodable_chars[encoded_value.to_ulong()]; usable_chunk_length = 0; chunk = ""; } chunk += *ciphertext_iter; if (std::islower(*ciphertext_iter) || std::isupper(*ciphertext_iter)) ++usable_chunk_length; } return message; } int main() { std::string cipher { "the world is changed. i feel it in the water. i feel it in the earth. " "i smell it in the air. much that once was is lost, for none now live " "who remember it. it began with the forging of the great rings. " "three were given to the elves, immortal, wisest andfairest of all beings. " "seven to the dwarf lords, great miners andcraftsmen of the mountain halls. " "and nine, nine rings were gifted to the race of men, who, above all else, " "desire power. but they were, all of them, deceived, for another ring was made. " "in the land of mordor, in the fires of mount doom, the dark lord sauron forged " "in secret a master ring, to control all others. and into this ring he poured " "his cruelty, his malice andhis will to dominate all life. one ring to rule them all." }; std::cout << "Cipher valid: " << std::boolalpha << check_cipher(cipher) << '\n'; std::cout << "Your message: "; std::string message; if (!std::getline(std::cin, message)) { std::cerr << "Input Error :(\n\n"; return EXIT_FAILURE; } if (!check_message(message)) { std::cerr << "Sowwy but your message isn't encodable :(\nEncodable characters:\n"; print_encodable_chars(std::cerr); std::cerr.put('\n'); return EXIT_FAILURE; } if (message.length() > get_workable_size(cipher)) { std::cerr << "Sowwy but your message is to long :(\n\n"; return EXIT_FAILURE; } auto ciphertext{ encrypt(message, cipher) }; std::cout << "\nCiphertext: " << ciphertext << "\n\n"; auto decrypted_message{ decrypt(ciphertext, cipher) }; std::cout << "Decrypted message: " << decrypted_message << "\n\n"; }
-
Ich habe das Grundgerüst gebaut und möchte jetzt für jeden Buchstaben eine switch anweisung machen. Mit Neu=Neu+cipher[i]-32 erreiche ich das mein kleines L zu einem großen L wird. Soweit so gut, aber wie kann ich nun weitere zeichen an L anhängen. Nichts funktioniert, was ich versuche:
#include <iostream> #include <math.h> using namespace std; char encrypt(string cipher, string eingabe) { char neu; for(int i=0;i<141;i++) { switch(eingabe[i]) { case 32 :;break; case 46 :;break; case 97 : neu=neu+cipher[i]-32; neu=neu+cipher[i+1];break; case 98 :; break; case 99 :; break; case 100:; break; case 101:; break; case 102:; break; case 103:; break; case 104:; break; case 105:; break; case 106:; break; case 107:; break; case 108:; break; case 109:; break; case 110:; break; case 111:; break; case 112:; break; case 113:; break; case 114:; break; case 115:; break; case 116:; break; case 117:; break; case 118:; break; case 119:; break; case 120:; break; case 121:; break; case 122:; break; } } return neu; } int main() { string neu; string eingabe; string cipher="loremipsumdolorsitametconsetetursadipscingelitrseddiamnonumyeirmodtemp" "orinviduntutlaboreetdoloremagnaaliquyameratseddiamvoluptuaatveroeosest"; cout<< "Geben Sie einen zu verschluesselnden String ein!"<<endl; getline(cin,eingabe); neu=encrypt(cipher,eingabe); if (eingabe.length()<29) { cout<< "Die Verschluesselung lautet;"<<neu<< endl; } else { cout << "Eine Verschluesselung ist nicht moeglich!"; } return 0; }
-
@Francesco sagte in Verschlüsselung mithilfe der Bacon-Chiffre:
möchte jetzt für jeden Buchstaben eine switch anweisung machen.
Wie wäre es mit einem Array?
@Francesco sagte in Verschlüsselung mithilfe der Bacon-Chiffre:
Mit Neu=Neu+cipher[i]-32 erreiche ich das mein kleines L zu einem großen L wird.
std::tolower()
gibt Dir den Kleinbuchstaben.<cctype>
.
-
@Swordfish Vielen Dank für die ausführliche Antwort, leider sind wir noch ganz am Anfang von c++ und dürfen nur grundbefehle benutzen.
-
@Swordfish Arrays dürfen wir nicht benutzen, genau so wie tolower. Die Befehle die wir bisher haben sind s[], s.length(), switch, for und while schleifen. Das wars
-
@Francesco Es gibt keine "Befehle" in einer Sprache wie C oder C++. Es gibt Statements. Statements können Funktionsaufrufe beinhalten. Das was Du unter "Befehle" verstehst sind wahrscheinlich Klassen und Funktionen der C++ Standard Library. Was darfst Du davon verwenden? Was explizit nicht? Ein Lehrer der explizit verbietet neues zu lernen taugt irgendwie nicht.
-
@Francesco sagte in Verschlüsselung mithilfe der Bacon-Chiffre:
Arrays dürfen wir nicht benutzen
wtf? Eigene Funktionen darfst Du aber schreiben wie Du lustig bist?
-
@Francesco sagte in Verschlüsselung mithilfe der Bacon-Chiffre:
#include <math.h>
Lass das! Erstens ist das wenn schon
<cmath>
in C++ und zweitens brauchst Du es nicht.
-
@Swordfish sagte in Verschlüsselung mithilfe der Bacon-Chiffre:
Eigene Funktionen darfst Du aber schreiben wie Du lustig bist?
#include <iostream> bool my_isspace(char ch) { return ch == ' '; // natuerlich nicht vollstaendig aber ausreichend } bool my_ispunct(char ch) { return ch == '.'; // ditto } bool my_isupper(char ch) { return 'A' <= ch && ch <= 'Z'; } bool my_islower(char ch) { return 'a' <= ch && ch <= 'z'; } char my_toupper(char ch) { if (!my_islower(ch)) return ch; return 'A' + ch - 'a'; } char my_tolower(char ch) { if (!my_isupper(ch)) return ch; return 'a' + ch - 'A'; } int main() { for (char ch = 'a'; ch <= 'z'; ++ch) std::cout.put(my_toupper(ch)); std::cout.put('\n'); for (char ch = 'A'; ch <= 'Z'; ++ch) std::cout.put(my_tolower(ch)); std::cout.put('\n'); }
Und vor allem hör' bitte auf
97
zu schreiben wenn Du'a'
meinst. Schreib''a'
.Wenn man davon ausgehen darf daß
cipher
wirklich wirklich nur aus Kleinbuchstaben besteht wird die Sache einfacher.
-
@Swordfish unser professor möchte, dass wir alles von grund auf lernen
-
@Francesco das ist keine Antwort auf meine Fragen.
-
@Swordfish ja eigene funktionen darf ich so schreiben wie ich möchte, mit unseren bisherigen kenntnissen. Welche s[i] zur Auslese einer Stelle in einem String, s.lenght() Länge des String s, Grundrechenoperationen und Logik, for und while schleifen. Das wars
-
@Francesco Das ist ja toll. Dann kannst Du
std::string
auch als arrayersatz für die zu enkodieren Zeichen verwenden und meine Funktionen oben um festzustellen um welche Art es sich handelt und um zwischen klein und groß zu konvertieren.std::string const encodable_chars{ "abcdefghijklmnopqrstuvwxyz. " }; // ... std::size_t my_find(std::string const &str, char ch) { for (std::size_t i{}; i < str.length(); ++i) if (str[i] == ch) return i; return str.length(); }
Wenn
my_find()
das Zeichen nicht finden konnte gibt esstr.length()
zurück. Sonst ist es der Index des gefundenen Zeichens.
-
#include <cstdlib> #include <string> #include <iostream> constexpr size_t chunk_length{ 5 }; bool my_islower(char ch) { return 'a' <= ch && ch <= 'z'; } char my_toupper(char ch) { if (!my_islower(ch)) return ch; return 'A' + ch - 'a'; } bool get_bit(std::size_t value, std::size_t bit) { return (value >> bit) & 0x01; } std::string const encodable_chars{ "abcdefghijklmnopqrstuvwxyz. " }; std::size_t my_find(std::string const &str, char ch) { for (std::size_t i{}; i < str.length(); ++i) if (str[i] == ch) return i; return str.length(); } std::string encrypt(std::string const &message, std::string const &cipher) { std::string ciphertext; std::size_t const number_of_usable_chunks{ cipher.length() / chunk_length }; for (std::size_t chunk_number{}; chunk_number < number_of_usable_chunks; ++chunk_number) { std::cout << "chunk number #" << chunk_number << '\n'; std::string chunk; for (std::size_t i{}; i < chunk_length; ++i) { std::cout << cipher[chunk_number * chunk_length + i]; chunk += cipher[chunk_number * chunk_length + i]; } std::cout.put('\n'); if (chunk_number < message.length()) { std::cout << "character to encode: " << message[chunk_number] << '\n'; auto value{ my_find(encodable_chars, message[chunk_number]) }; if (value == encodable_chars.length()) return {}; for (std::size_t bit{ chunk_length }; bit; --bit) { std::cout << chunk[chunk_length - bit] << ": " << get_bit(value, bit - 1) << "\t'"; if (get_bit(value, bit - 1)) chunk[chunk_length - bit] = my_toupper(chunk[chunk_length - bit]); std::cout << chunk[chunk_length - bit] << "'\n"; } } std::cout.put('\n'); ciphertext += chunk; } return ciphertext; } int main() { std::string cipher{ "loremipsumdolorsitametconsetetursadipscingelitrseddiamnonumyeirmodtemp" "orinviduntutlaboreetdoloremagnaaliquyameratseddiamvoluptuaatveroeosest" }; std::cout << "Message: "; std::string message; if (!std::getline(std::cin, message)) { std::cerr << "Input Error :(\n\n"; return EXIT_FAILURE; } auto ciphertext{ encrypt(message, cipher) }; std::cout << ciphertext; }
Kannst Du das nachvollziehen?
-
@Swordfish Ja danke dir !