Passwort generator mit Bedingungen


  • Mod

    Wenn sich der fast gleiche Code 5x wiederholt, macht man was falsch.


  • Gesperrt

    Dieser Beitrag wurde gelöscht!

  • Gesperrt

    Ok:

    #include <stdexcept>
    
    #include <iostream>
    
    #include <random>
    
    #include <vector>
    
    #include <algorithm>
    
    using namespace std;
    
    vector < vector < char16_t >> all_chars;
    int32_t all_size = 0;
    
    void add(char16_t from, char16_t to) {
      vector < char16_t > v;
      for (char16_t i = from; i <= to; i++) {
        v.push_back(i);
      }
      all_chars.push_back(v);
      all_size += v.size();
    }
    
    void init() {
      if (all_size != 0) {
        throw logic_error("already init");
      }
      add('a', 'z');
      add('A', 'Z');
      add('0', '9');
      add('!', '/');
      add('a', 'z');
    }
    
    char16_t get_ch(int32_t i) {
      if (i < 0 || i >= all_size) {
        throw invalid_argument("");
      }
      for (int j = 0; j < all_chars.size(); j++) {
        if (i < all_chars[j].size()) {
          return all_chars[j][i];
        }
        i -= all_chars[j].size();
      }
      return 0;
    }
    
    bool is_valid(string s, int i, int min, int max) {
      int c = 0;
      for (auto j: s) {
        if (find(all_chars[i].begin(), all_chars[i].end(), j) != all_chars[i].end()) {
          c++;
        }
      }
      return c >= min && c <= max;
    }
    
    int is_valid(string s) {
      if (!is_valid(s, 0, 1, all_size)) {
        return 0;
      }
      if (!is_valid(s, 1, 6, all_size)) {
        return 1;
      }
      if (!is_valid(s, 2, 8, all_size)) {
        return 2;
      }
      if (!is_valid(s, 3, 2, 5)) {
        return 3;
      }
      return 4;
    }
    
    string get_pw() {
      string s = ""; {
        random_device rd; // obtain a random number from hardware
        mt19937 gen(rd()); // seed the generator
        uniform_int_distribution < > distr(0, all_size - 1); // define the range
        while (s.size() < 30) {
          s += (char) get_ch(distr(gen));
        }
      } {
        random_device rd;
        mt19937 gen(rd());
        uniform_int_distribution < > distr1(0, all_size - 1);
        int v;
        while ((v = is_valid(s)) != 4) {
          uniform_int_distribution < > distr2(0, all_chars[v].size() - 1);
          int r1 = distr1(gen);
          int r2 = distr2(gen);
          s[r1] = (char) all_chars[v][r2];
        }
      }
      return s;
    }
    
    int main() {
      init();
      cout << get_pw();
      return 0;
    }
    

    Beispiel für ein sicheres Passwort: qJb1t3SdXL3-iymtN+90h1rOS,z8+7 😉 (Nur ein Spaß, jedes "bekannte" Passwort ist nicht mehr sicher...)

    Aber... ich laufe doch damit in ein Halteproblem - oder nicht?



  • @Jockelx sagte in Passwort generator mit Bedingungen:

    @Belli sagte in Passwort generator mit Bedingungen:

    Na klar, warum soll das hässlich sein?

    Weil ich nichts von shufflen geschrieben habe!? Und dann passt es zur Aufgabe, ist aber hässlich.

    Ach ja klar, weil Du es nicht geschrieben hast, logisch ...



  • @helpinfo sagte in Passwort generator mit Bedingungen:

    @Belli wie shuffle ich die einzelnen bedingungen in einem string?

    mit std::random_shuffle


  • Mod

    @EinNutzer0 sagte in Passwort generator mit Bedingungen:

    @SeppJ sagte in Passwort generator mit Bedingungen:

    Wenn sich der fast gleiche Code 5x wiederholt, macht man was falsch.

    fast 😉

    Ich weiß schon, was ich gesagt habe. Dass du das nicht verstehst, weiß ich. Aber trotzdem ist meine Aussage korrekt, dass du hier was falsch machst, mit genau der genannten Begründung.


  • Gesperrt

    @SeppJ sagte in Passwort generator mit Bedingungen:

    @EinNutzer0 sagte in Passwort generator mit Bedingungen:

    @SeppJ sagte in Passwort generator mit Bedingungen:

    Wenn sich der fast gleiche Code 5x wiederholt, macht man was falsch.

    fast 😉

    Ich weiß schon, was ich gesagt habe. Dass du das nicht verstehst, weiß ich. Aber trotzdem ist meine Aussage korrekt, dass du hier was falsch machst, mit genau der genannten Begründung.

    Siehe doch https://www.c-plusplus.net/forum/topic/353721/passwort-generator-mit-bedingungen/19#

    ... anstatt eine unkonstruktive Antwort zu schreiben.

    Meiner Meinung nach, gibt es ein algorithmisches Problem, wenn es zu viele Sonderzeichen gibt.



  • Das sieht an einigen Stellen irgendwie umständlich aus.

    Prinzipiell fände ich es schön, so einen PW Generator als Klasse zu kapseln. Der Klasse könnte man dann verschiedene Alphabete, aus denen zu ziehen ist mit geben, so wie zugehörige Einschränkungen. Das würde dir vlt auch helfen, das Problem weiter zu abstrahieren und den Code klarer zu schreiben.

    Außerdem @EinNutzer0 könnte dir ein Blick in die Standard Lib helfen, std::random_shuffle wurde schon genannt, ich hätte noch std::generate_n hilfreich gefunden, eine Art std::count hast du selbst geschrieben.

    @EinNutzer0 sagte in Passwort generator mit Bedingungen:

    Aber... ich laufe doch damit in ein Halteproblem - oder nicht?

    Das Halteproblem ist eine bestimmte Fragestellung aus der theoretischen Informatik, ich gehe davon aus, dass du meinst, dass dein Algo nicht deterministisch ist. Und ja, du gehst halt davon aus, dass deine Erstellung irgendwann schon zufällig eine gültige Kombination findet. Das kann auch mal länger dauern.

    Eine Mögliche Lösung dafür wurde im Thread ja auch schon genannt, Anforderungen nacheinander Abarbeiten und dann nochmal durchwürfeln.


  • Gesperrt

    @Schlangenmensch sagte in Passwort generator mit Bedingungen:

    Prinzipiell fände ich es schön, so einen PW Generator als Klasse zu kapseln.

    Danke, ich hab es mal neu gemacht:

    #include <stdexcept>
    #include <iostream>
    #include <random>
    #include <vector>
    #include <algorithm>
    
    #define SIZEC 30
    
    using namespace std;
    
    class alphabet
    {
    private:
        vector<char16_t> all_chars;
        size_t min;
        size_t max;
    
    public:
        static vector<alphabet> alphabets;
        static size_t all_count;
        static random_device rd;
        static mt19937 gen;
        alphabet(char16_t from, char16_t to, size_t min, size_t max);
        char16_t get_random_char();
        static char16_t get_random_overall_char();
        int search_random_char(string s);
        int is_valid(string s);
        string make_valid(string s);
    };
    
    alphabet::alphabet(char16_t from, char16_t to, size_t min, size_t max)
    {
        for (char16_t i = from; i <= to; i++)
        {
            all_chars.push_back(i);
        }
        all_count += all_chars.size();
        this->min = min;
        this->max = max;
    }
    
    char16_t alphabet::get_random_char()
    {
        uniform_int_distribution<> distr(0, all_chars.size() - 1);
        return all_chars[distr(gen)];
    }
    
    char16_t alphabet::get_random_overall_char()
    {
        uniform_int_distribution<> distr(0, all_count - 1);
        int i = distr(gen);
        for (auto a : alphabets)
        {
            if (i < a.all_chars.size())
            {
                return a.all_chars[i];
            }
            i -= a.all_chars.size();
        }
        return 0;
    }
    
    int alphabet::search_random_char(string s)
    {
        uniform_int_distribution<> distr(0, s.size() - 1);
        int i;
        do
        {
            i = distr(gen);
        } while (find(all_chars.begin(), all_chars.end(), s[i]) == all_chars.end());
        return i;
    }
    
    int alphabet::is_valid(string s)
    {
        int c = 0;
        for (auto i : s)
        {
            if (find(all_chars.begin(), all_chars.end(), i) != all_chars.end())
            {
                c++;
            }
        }
        if (c < min)
        {
            return -1;
        }
        if (c > max)
        {
            return +1;
        }
        return 0;
    }
    
    string alphabet::make_valid(string s)
    {
        uniform_int_distribution<> distr(0, s.size() - 1);
        int v;
        while ((v = is_valid(s)) != 0)
        {
            if (v < 0)
            {
                s[distr(gen)] = (char)get_random_char();
            }
            else
            {
                s[search_random_char(s)] = get_random_overall_char();
            }
        }
        return s;
    }
    
    void init()
    {
        alphabet::all_count = 0;
        alphabet::rd;
        alphabet::gen = mt19937(alphabet::rd());
        alphabet::alphabets.push_back(alphabet('a', 'z', 1, SIZEC));
        alphabet::alphabets.push_back(alphabet('A', 'Z', 6, SIZEC));
        alphabet::alphabets.push_back(alphabet('0', '9', 8, SIZEC));
        alphabet::alphabets.push_back(alphabet('!', '/', 2, 5));
    }
    
    string generate_valid_password()
    {
        string s = "";
        while (s.size() < SIZEC)
        {
            s += (char)alphabet::get_random_overall_char();
        }
        bool f;
        do
        {
            f = false;
            for (auto a : alphabet::alphabets)
            {
                if (a.is_valid(s) != 0)
                {
                    f = true;
                    a.make_valid(s);
                }
            }
        } while (f);
        return s;
    }
    
    int main()
    {
        init();
        cout << generate_valid_password();
        cout << endl;
        return 0;
    }
    

    Leider ist jetzt irgendwo ein Übersetzungsfehler, den ich nicht sehe... Habt ihr eine Idee?



  • @EinNutzer0 Warum hat deine Klasse statische Membervariablen? Die Initalisierung dieser findet nicht in einer Funktion statt, dann meckert der Linker auch nicht.

    size_t alphabet::all_count = 0;
    random_device alphabet::rd;
    mt19937 alphabet::gen = mt19937(alphabet::rd());
    vector<alphabet> alphabet::alphabets;
    
    void init()
    {
      alphabet::alphabets.push_back(alphabet('a', 'z', 1, SIZEC));
      alphabet::alphabets.push_back(alphabet('A', 'Z', 6, SIZEC));
      alphabet::alphabets.push_back(alphabet('0', '9', 8, SIZEC));
      alphabet::alphabets.push_back(alphabet('!', '/', 2, 5));
    }
    

    Warum heißt deine Klasse alphabet, finde ich bei der Aufgabenstellung irreführend.

    Und nochmal, warum dieses ganze Static?


  • Gesperrt

    @Schlangenmensch Hattest recht, static überflüssig...

    Ich hab es doch noch hinbekommen... 😆 Auch, wenn ich nicht weiß, wie...

    siehe bitte neuen Thread

    Würde mich wieder darüber freuen, wenn jemand noch einmal kurz drüberschauen könnte.


    Das soll natürlich nicht besser sein als shuffle, es ist nur ein anderer Ansatz.



  • Dieser Beitrag wurde gelöscht!


  • @Belli sagte in Passwort generator mit Bedingungen:

    @Jockelx sagte in Passwort generator mit Bedingungen:

    @Belli sagte in Passwort generator mit Bedingungen:

    Na klar, warum soll das hässlich sein?

    Weil ich nichts von shufflen geschrieben habe!? Und dann passt es zur Aufgabe, ist aber hässlich.

    Ach ja klar, weil Du es nicht geschrieben hast, logisch ...

    Ich weiß echt nicht, was du von mir willst...ich schreib etwas, was die Aufgabe zwar löst, aber hässlich ist und du sagst, nee ist nicht hässlich, wenn man das anders macht!? Ja, Glückwunsch, du bist der aller Beste oder frohe Weihnachten oder was willst du jetzt hören?



  • @EinNutzer0 Deine Klassen und was sie machen finde ich immer noch nicht stringend.

    Warum hat ein Alphabet min und max Werte?
    Warum ist ein Alphabet darauf beschränkt aufeinanderfolgende Werte enthalten zu können?
    Warum sind die verschiedenen Alphabete in alphabets hart eincodiert?
    Warum ist generate_valid_password eine Funktion auf alphabets?

    Das sind alles Sachen, die einen unbedarften Leser des Codes wundern dürften.

    Außerdem: Was ist mit const correctness?

    Funktionell habe ich jetzt nicht geguckt. Dafür habe ich momentan keine Zeit.


  • Gesperrt

    @Schlangenmensch (Und @Quiche-Lorraine ) Danke für deine Hinweise! Lass uns das in dem anderen Thread fortsetzen, um die anderen in diesem Thread nicht unnötig zu stören.


Anmelden zum Antworten