Johnny B.: ID-Verschlüsselung für Newsletter

Hallo geehrtes Forum,

ich plane gerade ein Newsletter-Script. Am Ende der versendeten Mails befindet sich ein Abmelde-Link. In diesem soll die ID des Empfängers so verschlüsselt sein, daß man nicht durch Verändern des verschlüsselten Strings zufällig bei einer anderen ID landet. Kann mir jemand dazu ein Perl-Modul empfehlen? Welche Verschlüsselung macht hier Sinn? Worauf muß ich achten, wenn ich es _richtig_ machen will?

Besten Dank
JOhnnY B.

  1. h1,

    .. Worauf muß ich achten, wenn ich es _richtig_ machen will?

    Wenn Du es richtig machen willst, darfst Du nicht verschlüsseln, sondern musst crypten. Dazu empfehle ich

    use Digest::MD5 qw(md5_hex);

    Hotti

    --
    Wenn der Kommentar nicht zum Code passt, kann auch der Code falsch sein.
    1. Hallo Hotti,

      Wenn Du es richtig machen willst, darfst Du nicht verschlüsseln, sondern musst crypten. Dazu empfehle ich
      use Digest::MD5 qw(md5_hex);

      --- das ist mir nicht ganz klar: ich crypte also so in etwa:

      my $digest = md5_hex('2');
      print "$digest";

      Das Ergebnis ist c81e728d9d4c2f636f067f89cc14862c. Immer. Logisch.

      Nur wie komme ich von diesem Crypt wieder zurück zu meiner ID? Dazu fand ich folgende Aussage:
      "Ein Passwort, das mit MD5 kodiert wurde kann definitiv nicht zurück gerechnet werden. MD5 funktioniert nur in eine Richtung und erstellt aus dem Passwort einen sogenannten Hash-Wert. Man könnte diesen auch als Prüfsumme bezeichnen.
      Der Sinn und Zweck von MD5 ist es ja gerade, dass nicht auf den Ursprungswert zurückgerechnet werden kann. Könnte man das, wäre ja MD5 absolut sinnlos."

      Mein Abmeldelink übergibt mir also die gecrypte ID und ich kann sie nicht zurückrechnen? Es sei denn ich lege mir eine Tabelle mit sämtlichen MD5-Ergebnissen an und vergleiche, aber so ist das sicher nicht gemeint?

      Verwirrte Grüße
      JOhnnY

      1. hi,

        my $digest = md5_hex('2');
        print "$digest";

        Das Ergebnis ist c81e728d9d4c2f636f067f89cc14862c. Immer. Logisch.

        Logisch. Es kommt dasselbe raus, aber keiner weiß was reingesteckt wurde. Wenn Du an der '2' nur ein Bit veränderst, sieht das Ergebnis gänzlich anders aus.

        Aber du suchst wohl eher was für symmetrische Verschlüsselung. Solche Algorithmen liegen nicht so offen im Internet rum, die stehen allenfalls in dicken Büchern. Google mal nach Diffie Hellman, Manfred Lipp,

        viel Glück,
        Hotti

        1. Hallo Hotti,

          Aber du suchst wohl eher was für symmetrische Verschlüsselung. Solche Algorithmen liegen nicht so offen im Internet rum, die stehen allenfalls in dicken Büchern. Google mal nach Diffie Hellman, Manfred Lipp,

          --- spannendes Thema! Wobei das doch sehr weit geht.

          Ich habe eine andere Lösung erdacht, die müßte doch sicher sein?

          my $id = 100;
          my $cryptmail = md5_hex('adresse@email.de');
          my $link = "http://domain.de/abmelden.cgi?id=$id&email=$cryptmail";

          dann kommt bei abmelden.cgi die id im Klartext an.

          Ich überprüfe dann, ob sich die md5-Prüfsummen der übergebenen und der für $id = 100 gespeicherten Emailadresse gleichen.

          Wenn jemand die id ändert, stimmt die Prüfsumme nicht, also kein Zugriff möglich. Und niemand kann zu einer unbekannten id die korrekte Prüfsumme der hinterlegten Emailadresse brute_forcen (mal davon abgesehen, daß sich niemand solche Mühe machen wird, nur um jemand anderen von einem Newsletter abzumelden...

          Zufriedene Grüße
          JOhnnY

          1. hi,

            Ich habe eine andere Lösung erdacht, die müßte doch sicher sein?

            Nein. Das Problem ist hier:

            my $cryptmail = md5_hex('adresse@email.de');

            Die email-Addr kann 'geraten'werden. Oder ein User hat die mal weitergegeben, was auch normal ist.

            md5_hex('das was du hier reintust');

            darf nur _einer_ wissen. Und nur der kann dieselbe Checksumme erzeugen.

            Hotti

            1. md5_hex('das was du hier reintust');

              darf nur _einer_ wissen. Und nur der kann dieselbe Checksumme erzeugen.

              Also: Was Du der md5_hex() übergibtst, kann durchaus was Zufälliges sein. Nur: Du musst Dir halt merken, zu welcher email-Adresse das gehört. Ob Du Dir dazu

              $hash = md5_hex($zufall);

              entweder $hash oder $zufall merkst, also in eine Tabelle schreibst, die nur Du kennst, bleibt Dir überlassen.

              Hotti

            2. Hallo Hotti,

              Nein. Das Problem ist hier:

              my $cryptmail = md5_hex('adresse@email.de');
              Die email-Addr kann 'geraten'werden. Oder ein User hat die mal weitergegeben, was auch normal ist.

              --- ich verstehe den Punkt nicht. Wenn ein Abmeldelink so ausschaut:

              http://www.xyz.de/abmelden.cgi?id=123&mail=c81e728d9d4c2f636f067f89cc14862c

              dann kann ich anhand der md5-Prüfsumme den User verifizieren. Er selbst darf sich abmelden.

              Bei dem Verändern der id auf 122 in dem Link müßte ja die md5-Prüfsumme zu der für 122 hinterlegten Emailadresse passen. Aber niemand weiß wer 122 ist. Niemand kann die Emailadresse wissen und erst recht nicht die md5-Prüfsumme. Es geht ja darum, daß niemand durch ein simples Verändern des Link auf andere Datensätze zugreifen kann.

              Ich könnte natürlich noch etwas in der Art wie
              my $cryptmail = md5_hex('adresse@email.de_$anmeldedatum_salz_pfeffer');
              nehmen. Das dürfte dann wirklich niemand mehr herausbekommen. Wobei ich mir beim besten Willen nicht vorstellen kann, wie jemand eine zufällige Email-Adresse 'erraten' will. Mag sein, daß dies mit brute_force oder ähnlichen Spezialtricks möglich ist? Wobei dann kann man gleich _alle_ möglichen Prüfsummen durchlaufen lassen. Irgendeine wird irgendwann mal passen. Ich denke den Aufwand wird sich niemand für das Knacken einer Newsletter-Abmeldung machen.

              Beruhigte Grüße
              Johnny

  2. Gib dem Empfänger zusätzlich zur ID noch eine weitere Kennung. Zum Beispiel einen Hash aus irgendwas, oder zwei Hashwerte aneinander gehängt. Es sollte halt eindeutig sein. Das ganze dann als Base64 codieren, damit hast du dann eine recht lange "ID", die so schnell keiner errät.

    1. Gib dem Empfänger zusätzlich zur ID noch eine weitere Kennung. Zum Beispiel einen Hash aus irgendwas, oder zwei Hashwerte aneinander gehängt. Es sollte halt eindeutig sein. Das ganze dann als Base64 codieren, damit hast du dann eine recht lange "ID", die so schnell keiner errät.

      Nimmt mich wunder wie eine so lange URL in der Plaintext Mail funktioniert.

      mfg Beat

      --
      ><o(((°>           ><o(((°>
         <°)))o><                     ><o(((°>o
      Der Valigator leibt diese Fische
    2. Hallo Encoder,

      Gib dem Empfänger zusätzlich zur ID noch eine weitere Kennung. Zum Beispiel einen Hash aus irgendwas, oder zwei Hashwerte aneinander gehängt. Es sollte halt eindeutig sein. Das ganze dann als Base64 codieren, damit hast du dann eine recht lange "ID", die so schnell keiner errät.

      --- ich habe in einer früheren Version so Dinge gemacht wie:

      • erhöhe die ID um 4739640
      • füge an der siebten Stelle eine '5' ein
      • erhöhe die zehnte Ziffer um '3'

      Das mag sicher sein, sicher genug für einen Abmeldelink, aber ich fand es unsauber programmiert. Gebastelt. Daher suche ich jetzt nach einer "sauberen" Lösung. Gedacht habe ich mir etwas in der Art:

      my $schluessel = 'salz';
      my $id = '100';
      my $crypt_ausgabe = crypt($id, $schluessel);

      und zurück dann in etwa so:
      my $id = decrypt($crypt_ausgabe, $schluessel);

      So kann jemand, der $schluessel nicht kennt, aus dem Ergebnis keine Rückschlüsse ziehen. Und sicher genug scheint mir das auch zu sein - naja, wenn es eine solche Funktion 'crypt/decypt' gibt?! Gibt es doch bestimmt irgendwie irgendwo irgendwann?!??

      Gebastelte Grüße
      JOhnnY

      1. Gibt es doch bestimmt irgendwie irgendwo irgendwann?!??

        Klar gibt es die, DES zum Beispiel als Schlüsselwort für die Suche. Oder guck mal hier rein http://php.net/manual/en/book.mcrypt.php da ist sicher auch was drin.