Ankündigung

Einklappen
Keine Ankündigung bisher.

Verschlüsseln der DB-ID aus der URL mit OPENSSL

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Verschlüsseln der DB-ID aus der URL mit OPENSSL

    Ich habe zwei Funktionen geschrieben, um die DB-ID aus der URL mit OPENSSL zu verschlüsseln und zu entschlüsseln.

    Das Verschlüsseln scheint zu funktionieren. Das Entschlüsseln gibt grundsätzlich false zurück. Weiß jemand, woran es liegt?
    Ich wollte auch erreichen, dass der generierte String ausschließlich aus Buchstaben und Zahlen besteht.

    PHP-Code:

    function encrypt($id) {
    $key '...';
    $iv '...';
    $method 'aes-128-cbc';
    $options OPENSSL_RAW_DATA;
    $encrypted_id openssl_encrypt($id$method$key$options$iv);
    $encrypted_id base64_encode($encrypted_id);
    $encrypted_id strtr($encrypted_id '+/=_-''abcdxy');
    $encrypted_id strtolower($encrypted_id);
    return 
    $encrypted_id;
    }

    function 
    decrypt($encrypted_id) {
    $key '...';
    $iv '...';
    $method 'aes-128-cbc';
    $options OPENSSL_RAW_DATA;
    $encrypted_id strtr($encrypted_id'abcdxy''+/=_-');
    $encrypted_id base64_decode($encrypted_id);
    $decrypted_id openssl_decrypt($encrypted_id$method$key$options$iv);
    if (
    $decrypted_id === false) {
    return 
    'Es ist ein Fehler aufgetreten.';
    exit();
    } else {
    $decrypted_id = (INT) $decrypted_id;
    return 
    htmlspecialchars($decrypted_id ?? ''ENT_QUOTES"UTF-8");
    }
    }


    $user_id_get '';
    if (isset(
    $_GET['id'])) {
    $user_id_get decrypt($_GET['id']);
    echo 
    $user_id_get;
    exit();


  • #2
    abcdxy können auch so in einem base64 string vorkommen.
    Wenn du also +/=_- durch abcdxy ersetzt, zerstörst du die Eindeutigkeit, denn beim Zurück-Ersetzen werden ja auch die ganz normalen abcdxy mit ersetzt.

    Dein strtolower zerstört noch mehr Eindeutigkeit.

    ​​​​​In einem base64 string werden natürlich entsprechend viele unterschiedliche Bytes (Zeichen) benötigt.

    Ein Beispiel:
    Wir encoden "test" als base64
    Heraus kommt "dGVzdA=="
    Nach deiner Ersetzung und strtolower wäre das "dgvzdacc"

    Beim "decodieren" ersetzt du wieder rückwärts und bekommst "_gvz_+=="

    ​​​​​​Das ist ein völlig anderer String.
    Der base64 decodiert ergibt nichteinmal lesbare Zeichen, denn ein + kommt im base64 Alphabet nunmal gar nicht vor. Was das in deiner Ersetzungsliste überhaupt verloren hat, ist mir ein Rätsel.

    Aber auch ohne das + siehst du den Effekt deutlich.

    Wenn du also nur alphanumerische Zeichen möchtest, und dann auch noch case-insensitiv, dann musst du anstatt base64 eine geringere basis als 64 verwenden, wie zum Beispiel 32.
    Dort hast du allerdings immernoch das = fürs Padding (Auffüllen von fehlenden Bytes am Ende)
    Das wiederum könntest du hier tatsächlich ersetzen durch ein Zeichen, dass nicht zum Alphabet gehört. z.B. 0,1,8
    Good programming is 5% knowledge, 5% skill, 20% caffeine, 30% attention to detail and 40% RTFM
    Kapazitäten frei: Einfach per PN ein Angebot einholen.

    Kommentar


    • #3
      Zudem was schon gesagt wurde und ich zustimme, möchte ich noch darauf hinweisen, dass der Aufruf von htmlspecialchars() in einer Verschlüsselungsfunktion nichts verloren hat. Eine Funktion namens decrypt() sollte auch nur genau das machen, was sie sagt, nämlich entschlüsseln. Und nicht irgendwelche HTML-Zeichen dazu zaubern oder einen Fehlertext in Form eines Strings zurück geben. Für die Fehlerbehandlung gibt es übrigens try-catch, oder weniger schön: trigger_error(). Fallweise kann man auch den Boolean FALSE zurückgeben, aber try-catch wäre an sich die sauberste Variante.

      Kommentar


      • #4
        Zitat von reddighamburg Beitrag anzeigen
        abcdxy können auch so in einem base64 string vorkommen.
        Wenn du also +/=_- durch abcdxy ersetzt, zerstörst du die Eindeutigkeit, denn beim Zurück-Ersetzen werden ja auch die ganz normalen abcdxy mit ersetzt.

        Dein strtolower zerstört noch mehr Eindeutigkeit.

        ​​​​​In einem base64 string werden natürlich entsprechend viele unterschiedliche Bytes (Zeichen) benötigt.

        Ein Beispiel:
        Wir encoden "test" als base64
        Heraus kommt "dGVzdA=="
        Nach deiner Ersetzung und strtolower wäre das "dgvzdacc"

        Beim "decodieren" ersetzt du wieder rückwärts und bekommst "_gvz_+=="

        ​​​​​​Das ist ein völlig anderer String.
        Der base64 decodiert ergibt nichteinmal lesbare Zeichen, denn ein + kommt im base64 Alphabet nunmal gar nicht vor. Was das in deiner Ersetzungsliste überhaupt verloren hat, ist mir ein Rätsel.

        Aber auch ohne das + siehst du den Effekt deutlich.

        Wenn du also nur alphanumerische Zeichen möchtest, und dann auch noch case-insensitiv, dann musst du anstatt base64 eine geringere basis als 64 verwenden, wie zum Beispiel 32.
        Dort hast du allerdings immernoch das = fürs Padding (Auffüllen von fehlenden Bytes am Ende)
        Das wiederum könntest du hier tatsächlich ersetzen durch ein Zeichen, dass nicht zum Alphabet gehört. z.B. 0,1,8
        Danke schön. Jetzt habe ich verstanden was falsch gelaufen ist.
        Eigentlich suche ich nur nach einer einfachen Möglichkeit die ID in der URL zu verschleiern oder zu verschlüsseln. Base32 gibt es nicht als fertige Funktion, oder?

        PHP-Code:
        function encrypt($id) {
        $key '...';
        $iv '...';
        $method 'aes-128-cbc';
        $options OPENSSL_RAW_DATA;
        $encrypted_id openssl_encrypt($id$method$key$options$iv);
        $encrypted_id base64_encode($encrypted_id);
        $encrypted_id urlencode($encrypted_id);
        return 
        $encrypted_id;
        }

        function 
        decrypt($encrypted_id) {
        $key '...';
        $iv '...';
        $method 'aes-128-cbc';
        $options OPENSSL_RAW_DATA;
        $encrypted_id urldecode($encrypted_id);
        $encrypted_id base64_decode($encrypted_id);
        $decrypted_id openssl_decrypt($encrypted_id$method$key$options$iv);
        if (
        $decrypted_id === false) {
        return 
        'Es ist ein Fehler aufgetreten.';
        exit();
        } else {
        return 
        $decrypted_id;
        }
        }


        $user_id_get '';
        if (isset(
        $_GET['id'])) {
        $user_id_get decrypt($_GET['id']);
        echo 
        $user_id_get;
        exit();

        Mein erster Versuch mit dem jeweiligen Sonderzeichen funktioniert, aber nicht zuverlässig. Manchmal bekomme ich ein false zurück. Meistens funktioniert es jedoch.

        Zitat von hellbringer Beitrag anzeigen
        Zudem was schon gesagt wurde und ich zustimme, möchte ich noch darauf hinweisen, dass der Aufruf von htmlspecialchars() in einer Verschlüsselungsfunktion nichts verloren hat. Eine Funktion namens decrypt() sollte auch nur genau das machen, was sie sagt, nämlich entschlüsseln. Und nicht irgendwelche HTML-Zeichen dazu zaubern oder einen Fehlertext in Form eines Strings zurück geben. Für die Fehlerbehandlung gibt es übrigens try-catch, oder weniger schön: trigger_error(). Fallweise kann man auch den Boolean FALSE zurückgeben, aber try-catch wäre an sich die sauberste Variante.
        Auch dir danke ich
        Darüber habe ich auch nachgedacht, aber an dem Punkt dürfte dann doch nur ein Integer übergeben werden, oder nicht?
        Das casten als INT ist aber okay?

        Kommentar


        • #5
          Das blinde casten als INT ist nicht okay.
          Das hat aber auch noch einen anderen Grund.
          Du verarbeitest hier Benutzereingaben. Jeder kann dir jeden beliebigen "Rotz" in den get-Parameter hinein werfen, und es ist durchaus möglich, dass etwas anderes als ein Integer-Ähnlicher String dabei herauskommt.

          Gut ist, dass du hier explizit castest, und der cast an sich ist auch nicht verwerflich. aber du musst mindestens prüfen, ob das so gelungen ist, bevor du damit weiter arbeitest.

          Auch ist in dem Fall der name der Funktion ungünstig, denn von einem decrypt erwartet man ja eine solche Einschränkung auf int pauschal erstmal nicht, und wenn sie an anderer Stelle auch noch sinnvoll verwendet werden soll, dann ärgerst du dich schwarz, wenn es beim nächsten Mal um Namen oder Sternzeichen geht.

          Insofern wäre es auch hier "aufgeräumter", wenn die Ergebnisverarbeitung außerhalb der Funktion passiert.

          Klar, du könntest die Funktion auch erst dann ändern, wenn du das brauchst, aber dann müsstest du auch alle alten codestellen anpassen bei denen sie schon verwendet wurde und ein int erwartet wird.
          Deshalb lieber gleich richtig.

          Die funktion gemäß ihres Namens allgemein verwendbar, und alle Rahmenbedingungen in der jeweiligen Situation behandeln.
          ​​​​​

          zu deiner vorherigen Frage:
          Nein, base32 gehört nicht zum php core, aber es haben sich schon zahlreiche Menschen daran versucht und dementsprechend viele implementierungen eigener base32 funktionen gibt es auch zu finden.

          Good programming is 5% knowledge, 5% skill, 20% caffeine, 30% attention to detail and 40% RTFM
          Kapazitäten frei: Einfach per PN ein Angebot einholen.

          Kommentar


          • #6
            Eigentlich suche ich nur nach einer einfachen Möglichkeit die ID in der URL zu verschleiern oder zu verschlüsseln. Base32 gibt es nicht als fertige Funktion, oder?
            speice doch einfach ne zuordnung random -> uid als teballle

            Kommentar


            • #7
              Zitat von tomBuilder Beitrag anzeigen

              speice doch einfach ne zuordnung random -> uid als teballle
              Wenn es nur darum geht, die userID vor dem user zu verbergen, ist das die wohl einfachste Lösung. Im Prinzip wird aber hier nur verlagert, und die uid ist immernoch über die Datenbank zu ermitteln.

              Wenn es darum geht, bei einem Datenleak die Aufrufe immernoch nicht reproduzierbar zu haben, dann funktioniert das nicht, denn dann genügt der Diebstahl der Datenbank (ohne code) zum "entschlüsseln".

              Außerdem muss ja auch der random string unter denselben Anforderungen erzeugt werden.

              Pauschal halte ich den Ansatz mittels openssl auch für etwas "drüber" aber es ging eingangs um die Frage "warum funktioniert das nicht" und nicht um die Frage "kann man es anders lösen" ...

              ​​​​​​
              Good programming is 5% knowledge, 5% skill, 20% caffeine, 30% attention to detail and 40% RTFM
              Kapazitäten frei: Einfach per PN ein Angebot einholen.

              Kommentar


              • #8
                Zitat von reddighamburg Beitrag anzeigen
                Das blinde casten als INT ist nicht okay.
                Das hat aber auch noch einen anderen Grund.
                Du verarbeitest hier Benutzereingaben. Jeder kann dir jeden beliebigen "Rotz" in den get-Parameter hinein werfen, und es ist durchaus möglich, dass etwas anderes als ein Integer-Ähnlicher String dabei herauskommt.

                Gut ist, dass du hier explizit castest, und der cast an sich ist auch nicht verwerflich. aber du musst mindestens prüfen, ob das so gelungen ist, bevor du damit weiter arbeitest.
                Unbedacht sowieso nicht. Ich caste nur da, wo nur ein Integer übergeben werden darf. Also beispielsweise, wenn ich über $_GET die ID eines Datensatzes übergebe.

                PHP-Code:
                $user_id_get '';
                if (isset(
                $_GET['id'])) {
                $user_id_get = (INT) $_GET['id'];
                }

                if (! 
                is_numeric($user_id_get)) {
                exit();

                Also in etwa so überprüfen, ob das Casten erfolgreich gewesen ist?

                Zitat von reddighamburg Beitrag anzeigen
                Nein, base32 gehört nicht zum php core, aber es haben sich schon zahlreiche Menschen daran versucht und dementsprechend viele implementierungen eigener base32 funktionen gibt es auch zu finden.
                Okay, ich schaue mir das mal an

                Zitat von tomBuilder Beitrag anzeigen

                speice doch einfach ne zuordnung random -> uid als teballle
                Hört sich interessant an, jedoch kann ich nichts dazu finden. Hast du irgendwelche Artikel dazu, die näher darauf eingehen?

                Kommentar


                • #9
                  Wenn es nur darum geht, die userID vor dem user zu verbergen, ist das die wohl einfachste Lösung. Im Prinzip wird aber hier nur verlagert, und die uid ist immernoch über die Datenbank zu ermitteln.
                  gut, wenn man auf die db zugreifen kann und nicht auf auf auf die php dateien , in denen (hier nur im beispiel) der kery im claertext steht, weil er in nur innerhalb des hsm genutzt wird ....

                  ich weiß nicht was TE will, ausser dass die uid (?) eben nicht in der url steht, und dort durch aphanum erstetz werden soll, wenn nur ein hochzählen oder testen sinnvoller nicks verhindert werden soll, reicht es.
                  dass ein irgendwie identfizierbarer client durch ein solches bruteforce testing als badguy verdächtig scheint, muss ch ja mnicht erwähnen.



                  Hört sich interessant an, jedoch kann ich nichts dazu finden. Hast du irgendwelche Artikel dazu, die näher darauf eingehen?
                  ich weiß nicht, du findest nichts, suche ich auch nicht.

                  du erkennst bei base64 ein url problem , ok,
                  du kann statt hien und rum ersetzen, auch base64url nutzen .


                  Kommentar

                  Lädt...
                  X