Verschlüsselung mithilfe der Bacon-Chiffre [gelöst]



  • Guten Abend,
    ich verzweifle momentan an einer Hausaufgabe und hoffe Ihr könnt mir helfen. Mein Problem ist, dass ich nicht wirklich weiß was von mir verlangt wird. Die Aufgabenstellung lautet:

    https://share-your-photo.com/b9ad2717ce

    Mein Versuch bis jetzt:

    #include <iostream>
    #include <math.h>
    
    using namespace std;
    
    void encrypt(string cipher)
    {
        for(int i=0;i<cipher.length();i++)
        {
            if((cipher[i]>64)&&(cipher[i]<91)) //Hier wird für Kleinbuchstaben k und für Großbuchstaben g ausgegeben.
            {
                cout<<"g";
            }
            else
            {
                cout<<"k";
            }
        }
    }
    
    
    int main()
    {
        string cipher;
        cout<< "Geben Sie einen zu verschluesselnden String ein!"<<endl;
        getline(cin,cipher);
        if (cipher.length()%5==0) //Hier findet die Überprüfung des Strings statt
        {
            cout<< "Die Verschluesselung lautet;"<< endl;
            encrypt(cipher);
    
        }
        else
        {
            cout << "Eine Verschluesselung ist nicht möglich!";
        }
        return 0;
    }
    

    http://coliru.stacked-crooked.com/a/fe92d48e1688e3ce

    Ich hoffe Ihr könnt mir helfen 🙂



  • Zunächst mal Frage ich mich ob du die Chiffre überhaupt verstanden hast. Irgendwie schaut es nicht danach aus 😅. Und naja, der Code den du geschrieben hast bringt nicht wirklich etwas. Ich denke du solltest dir mal Zettel und Stift nehmen und erstmal die Chiffre testen. Wenn du das verstanden hast kannst du dir überlegen wie du sie implementieren würdest. Was braucht die Encrypt/Decrypt-Funktion für Argumente? Sollten sie vielleicht einen Wert zurück geben usw... Ich denke const-correctness und pass-by-reference hattet ihr noch nicht dran 😁



  • @Zhavok Also ich habe verstanden, dass wenn wie in der Aufgabenstellung ich das Beispiel
    sINNfReieRTEXTiStanGeNEhm entschlüssele mithilfe der Tabelle robot herrausbekomme. Um ehrlich zu sein mehr habe ich auch nicht wirklich verstanden. Informatik belege ich als Nebenfach in der Uni und bezüglich programmieren haben wir bis jetzt sehr wenig gemacht. Zudem bin ich kompletter Neuling. Könntest du die Aufgabenstellung eventuell anders formulieren? 😅



  • Eventuell habe ich gerade einen guten Einfall. Könnte es sein, dass von mir verlangt wird, dass in cipher eine unbedeutende Zeichenfolge in kleinbuchstaben eingegeben wird. Dann soll nach der Eingabe cipher angepasst werden (also bestimmte kleinbuchstaben zu großbuchstaben machen) und dann die angepasste cipher wieder ausgegeben werden?



  • Ja. So funktioniert die Verschlüsselung. Du nimmst einen unbedeutenden Text aus Kleinbuchstaben. Dann werden nach den angegeben Mustern die Buchstaben abgeändert. Wie schon gesagt, nehm dir ein Blatt Papier und lass die einen langen Satz einfallen. Dann überlegst du dir ein Wort was du in dem Satz verstecken möchtest. Das heißt du nimmst jeden Buchstabe des geheimwortes und wendest das dazugehörige Muster auf deinen Satz an.



  • @Zhavok Vielen Dank, ich melde mich sobald ich fertig bin ! 😄



  • #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 es str.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?


Anmelden zum Antworten