Enrico: Komprimierung/Dekomprimierung jeweils unter PHP und JavaScript

Hallo,

ich durchforste das Internet seit gefühlten Wochen vergeblich nach einer äquivalent arbeitenden (und für mich auch verständlichen) Umsetzung von PHP's gzcompress, gzdeflate oder gzencode.

Ich finde "nur" sehr umfangreiche Bibliotheken, die entweder mit Umlauten nicht funktionieren oder aber nur in JavaScript oder nur in PHP funktionieren oder die ich nicht nach JavaScript oder PHP übertragen kann, weil mir hier die Kenntnisse fehlen.

Statt dessen habe ich Unmengen an Seiten gefunden, die sich mit LZW befassen.

Da ich die Komprimierung (primär erstmal nicht LZW) nutzen möchte, Strings vor dem Übertragen vom Server zum Client und umgekehrt zu verkleinern, frage ich mich, warum LZW so gelobt wird, zumal ja die maximale Anzahl an in einer URL erlaubten Zeichen um die 2000 Zeichen beträgt und LZW in meinem Testfall aus einem 1760 Zeichen langen String einen 3369 Zeichen langen String macht.

Was ist daran effektiv?
Könnt ihr mir Umsetzungen in PHP und JavaScript empfehlen?

Danke und Gruß,
Enrico

  1. ich durchforste das Internet seit gefühlten Wochen vergeblich nach einer äquivalent arbeitenden (und für mich auch verständlichen) Umsetzung von PHP's gzcompress, gzdeflate oder gzencode.

    Da ich die Komprimierung (primär erstmal nicht LZW) nutzen möchte, Strings vor dem Übertragen vom Server zum Client und umgekehrt zu verkleinern, frage ich mich, warum LZW so gelobt wird, zumal ja die maximale Anzahl an in einer URL erlaubten Zeichen um die 2000 Zeichen beträgt und LZW in meinem Testfall aus einem 1760 Zeichen langen String einen 3369 Zeichen langen String macht.

    Vorneweg solltest du wissen, dass Javascript von Haus aus nicht wirklich dafür geeignet ist, mit Bits und Bytes umzugehen, jedenfalls im klassischen Sinne.
    Bei URLs ist es noch schlimmer, die nehmen nicht nur nur Text, der Text ist auch noch auf einen kleinen Satz Zeichen eingeschränkt. Um in einer URL mehr als eine Handvoll Binärdaten zu übertragen, muss man schon _sehr_ gute Gründe haben.

    LZW (und sicher die allermeisten anderen Verfahren) arbeitet mit Bits und Bytes. Da bist du mit Javascript und URLs eigentlich schonmal so falsch wie mit Lederpeitsche und Gummimaske auf dem Wiener Opernball - kann man machen, muss man sich aber nicht über das Ergebnis wundern.
    Hättest du dir einen kurzen Überblick über die Funktionsweise von LZW geholt, wäre dir aufgefallen, dass LZW 9 bis 12 Bit breite Wörter zurückgibt. Diese Wörter müssen auf Bytes (8 Bit breite Wörter) verteilt und diese Bytes dann wiederum in einen URL-fähigen Text umgewandelt werden. Du kannst Allerweltstexte gar nicht so gut komprimieren, wie die beiden nachfolgenden Schritte die Daten wieder aufblasen.

    Ich vermute stark, dass es bei anderen Verfahren am Ende in der URL nicht viel besser aussehen wird.

    Könnt ihr mir Umsetzungen in PHP und JavaScript empfehlen?

    Ich empfehle dir dringendst, deine Daten per POST zu übertragen. Dafür ist POST da und du scheinst ja auch die Serverseite unter deiner Kontrolle zu haben, kannst dich also darauf einrichten. Warum um alles in der Welt muss es also GET sein?

    1. Hallo,

      Hättest du dir einen kurzen Überblick über die Funktionsweise von LZW geholt, wäre dir aufgefallen, dass LZW 9 bis 12 Bit breite Wörter zurückgibt. Diese Wörter müssen auf Bytes (8 Bit breite Wörter) verteilt und diese Bytes dann wiederum in einen URL-fähigen Text umgewandelt werden. Du kannst Allerweltstexte gar nicht so gut komprimieren, wie die beiden nachfolgenden Schritte die Daten wieder aufblasen.

      wenn es wirklich nur Texte im volkstümlichen Sinn sind, könnte die Rechnung sogar noch aufgehen. Längere Plaintext-Passagen (der weitaus größte Teil der Bytes im ASCII-Bereich 0x20..7F, viele sich wiederholende Muster) lassen sich gelegentlich auf unter 20% des ursprünglichen Speicherbedarfs komprimieren. Dann mit der URL-Codierung wieder aus einem Byte drei machen, und man ist immer noch bei "nur" 60% der ursprünglichen Datenmenge.

      Das funktioniert aber auch erst ab einer gewissen Länge des Originaltexts. Denn solange die Lookup-Tabellen des verwendeten Kompressionsverfahrens noch einen merklichen Anteil der Gesamt-Datenmenge ausmachen, ist das Verfahren ineffizient. Deswegen ergeben kleine Dateien auch meistens zip-Archive, die größer sind als die Ursprüngliche Datei.

      Ich empfehle dir dringendst, deine Daten per POST zu übertragen.

      Und darüber hinaus empfehle ich, sich nicht über die Kompression den Kopf zu zerbrechen. Vom Server zum Client passiert das nämlich meist schon ganz automatisch, und vom Client zum Server werden meist deutlich weniger Daten übertragen.

      Ciao,
       Martin

      --
      Auch mit eckigen Radios kann man Rundfunk hören.
      Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
      1. Hallo Klärchen,
        hallo Martin,

        Anlaß meiner Überlegungen ist die komprimierte Übertragung verschlüsselter sensibler Daten vom Client zum Server und umgekehrt.

        Beispiel:

        1. Erfassen von persönlichen Daten (Namen, Geburtsdatum, E-Mail-Adresse,...) im Browser
        2. Verschlüsselung und Komprimierung
        3. Übertragung zum Server
        4. Dekomprimierung und Entschlüsselung
        5. Abspeichern

        $_GET habe ich deswegen gewählt, weil es, nach dem Übertragen von Formulardaten mittels POST beim Zurückblättern eine störende Sicherheitsabfrage beim Zurückblättern gibt.

        Gruß,
        Enrico

        1. Hi Enrico,

          1. Erfassen von persönlichen Daten (Namen, Geburtsdatum, E-Mail-Adresse,...) im Browser

          das scheint mir eine Datenmenge zu sein, bei der sich eine Komprimierung generell noch nicht lohnt (ein paar hundert Byte bis wenige kB).

          $_GET habe ich deswegen gewählt, weil es, nach dem Übertragen von Formulardaten mittels POST beim Zurückblättern eine störende Sicherheitsabfrage beim Zurückblättern gibt.

          Dafür wird bei GET -je nach Browsereinstellung- der gesamte Request einschließlich aller URL-Parameter stillschweigend nochmal gesendet, was je nach Verarbeitung auf dem Server zu doppelten Datenbankeinträgen oder ähnlichen unerwünschten Nebenwirkungen führen kann.

          Ciao,
           Martin

          --
          F: Was sagt der große Keks zum kleinen Keks?
          A: Du kannst dich jetzt verkrümeln.
          Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
          1. Hi Martin,

            das scheint mir eine Datenmenge zu sein, bei der sich eine Komprimierung generell noch nicht lohnt

            Hmm, vielleicht werde ich bei mir an dieser Stelle doch den Rotstift ansetzen.

            was je nach Verarbeitung auf dem Server zu doppelten Datenbankeinträgen

            Das habe ich über Setzen, Abfragen und Löschen einer Session-Variable abgefangen.

            Gruß,
            Enrico

            1. Hallo,

              was je nach Verarbeitung auf dem Server zu doppelten Datenbankeinträgen
              Das habe ich über Setzen, Abfragen und Löschen einer Session-Variable abgefangen.

              das ist gut, denn man muss selbst bei POST damit rechnen, dass dann und wann irgendein Dödel die Abfrage nach erneutem Senden voller Inbrunst mit "Ey, klar doch!" beantwortet.

              Ciao,
               Martin

              --
              Ordnung ist, wenn man etwas findet, was man gar nicht sucht.
              Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
        2. Hi,

          Anlaß meiner Überlegungen ist die komprimierte Übertragung verschlüsselter sensibler Daten vom Client zum Server und umgekehrt.

          klingt so, als wäre https angebracht.

          1. Erfassen von persönlichen Daten (Namen, Geburtsdatum, E-Mail-Adresse,...) im Browser

          also kein wirklich großes Datenvolumen - im Vergleich zu dem Overhead, den jeder http(s)-Request so mit sich bringt, fallen diese paar Nutzdaten kaum ins Gewicht, egal ob unkomprimiert oder komprimiert.

          $_GET habe ich deswegen gewählt, weil es, nach dem Übertragen von Formulardaten mittels POST beim Zurückblättern eine störende Sicherheitsabfrage beim Zurückblättern gibt.

          POST->REDIRECT->GET.

          cu,
          Andreas

          --
          Warum nennt sich Andreas hier MudGuard?
          O o ostern ...
          Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.
    2. Hallo,

      Vorneweg solltest du wissen, dass Javascript von Haus aus nicht wirklich dafür geeignet ist, mit Bits und Bytes umzugehen, jedenfalls im klassischen Sinne.

      Es gibt mittlerweile explizite Datentypen zum Arbeiten mit Binärdaten.

      https://developer.mozilla.org/en-US/docs/Web/API/ArrayBuffer
      http://www.html5rocks.com/en/tutorials/webgl/typed_arrays/

      Mathias

  2. Hallo,

    durch Zufall bin ich nun auf folgende Seite gestossen.

    Mit etwas Anpassung funktioniert nun der Austausch zwischen PHP und JavaScript perfekt.

    Bei Interesse teile ich die Anpassungen gerne mit.

    Gruß,
    Enrico

  3. Was ist daran effektiv?
    Könnt ihr mir Umsetzungen in PHP und JavaScript empfehlen?

    Wozu willst Du das?

    Der Datenverkehr zwischen dem Browser und dem Server ist schon via HTTP-Protokoll komprimierbar. Mit mod_deflate komprimiert der Webserver (!) den Datenverkehr, der Browser entpackt. Für den Nutzer und Entwickler ist das völlig transparent.

    Eine Implementierung für einen serverseitigen Cache bei quasistatischen Inhalten findest Du in meinem Artikel "PHP: Einfaches Caching für Webprojekte".

    Dann wäre da noch eine Liste mit Skripten für die LZW-Komprimierung in 21 Sprachen Die 22. Sprache wäre PHP.

    Wenn Du also eventuell größere Texte oder z.B. JSON-Daten browserseitig mit LZW komprimieren willst und annehmen musst, dass diese Zeichen verstümmelt werden weil die Kodierung UTF ist dann jage den String ("Blob") doch vor dem Komprimieren einfach durch einen base-64-Kodierer:
    https://github.com/jsxgraph/jsxgraph/blob/master/src/utils/base64.js

    Auf dem Server dann anders herum. 1.) entpacken 2. "Blob" decodieren

    Jörg Reinholz

    1. Hallo Jörg,

      Wozu willst Du das?

      Ich will die Größe der vom Client zum Server und umgekehrt zu übertragenden Daten verkleinern, da diese vor der Übertragung zum Server bzw. Client immer verschlüsselt und nach der Übertragung wieder entschlüsselt werden und die Verschlüsselung die Größe nicht unerheblich vergrößert.

      Glücklicherweise habe ich heute in der Früh doch noch eine Seite gefunden, die mir eine, bezogen auf die Stringlänge, vernünftige Adaption von PHP's deflate in JavaScript bietet.

      Dann wäre da noch eine Liste

      Aufgrund meines Fokus auf der Erzeugung möglichst kurzer Strings kam LZW nicht in Frage.

      findest Du in meinem Artikel

      Dein Artikel ist sehr interessant, wenn ich auch noch nicht weiß, wie ich ihn verwenden könnte. Was verstehst Du unter "quasistatischen" Inhalten? Vor-, Nachname, Geburtsdatum, Adresse,...?

      dann jage den String ("Blob") doch vor dem Komprimieren einfach durch einen base-64-Kodierer

      Das mache ich auch (und das war, da der JavaScript-Code 100% kompatibel zu PHP sein muss, kein leichtes Unterfangen).

      Gruß,
      Enrico

      1. Ich will die Größe der vom Client zum Server und umgekehrt zu übertragenden Daten verkleinern, da diese vor der Übertragung zum Server bzw. Client immer verschlüsselt und nach der Übertragung wieder entschlüsselt werden und die Verschlüsselung die Größe nicht unerheblich vergrößert.

        Verschlüsselung? Oha. Wie sieht die denn aus? Wenn du ernsthaft etwas verschlüsseln möchtest, dann benutze doch lieber https. Mit selbst zusammengeschusterten "Verschlüsselungen" sind schon etliche auf die Nase gefallen.
        Wenn dir wirklich etwas an den Daten liegt und das nicht nur Spielerei sein soll, dann solltest davon ausgehen, dass jemand, der an der Leitung horcht, auch in der Lage ist, andere als allgemein anerkannte Verfahren in Nullkommanix auseinanderzunehmen.

        Davon abgesehen umgehst du dein Problem mit POST durch Beantworten der POST-Anfrage mit einer Weiterleitung 303. Alternativ könntest du auch AJAX nutzen, ebenfalls mit POST.
        In beiden Fällen fabrizierst du weder Monster-URLs, noch landen deine sensiblen Daten an einem Ort, wo sensible Daten eigentlich auch nichts zu suchen haben: in den Zugriffsprotokollen von Browser (Chronik) und Webserver.

        1. Hallo Klärchen,

          sorry, ich antworte später, muss jetzt zu unserem Dartspiel.

          Gruß,
          Enrico

        2. Verschlüsselung? Oha. Wie sieht die denn aus?

          Ich verschlüssle/entschlüssle die Daten vor/nach der Übertragung client- und serverseitig mit AES in Verbindung mit einem Schlüssel, der aus den zu übertragenden Daten erzeugt wird und - versteckt - mit übertragen wird.

          Beantworten der POST-Anfrage mit einer Weiterleitung 303
          Alternativ könntest du auch AJAX nutzen, ebenfalls mit POST.

          Klingt interessant. Werde ich mir anschauen.

          Gruß,
          Enrico

          1. Hallo,

            Ich verschlüssle/entschlüssle die Daten vor/nach der Übertragung client- und serverseitig mit AES in Verbindung mit einem Schlüssel, der aus den zu übertragenden Daten erzeugt wird und - versteckt - mit übertragen wird.

            Kryptographie ist nicht einfach und nach meinem Laienverständnis läuft hier alles schief, was nur schief laufen kann.

            Nur weil mit AES ein prinzipiell brauchbarer Algorithmus verwendet wird, ist diese Anwendung keinesfalls sicher. Es kommt immer auf die korrekte Verwendung und konkrete Ansteuerung von AES an (Modus, Schlüsselwahl, Initialisierungsvektor, Schlüsselübertragung…).

            Der Schlüssel sollte nicht aus den Daten hergeleitet werden, sondern möglichst zufällig sein. Wenn der Schlüssel ohnehin mit der Nachricht übertragen wird, dann ist das nicht mehr Verschlüsselung, sondern einfach knackbare Verschleierung. Jeder kann den clientseitigen Code lesen und das »Versteck« unter der Fußmatte finden. Wie Klärchen schon gesagt hat: Wer tatsächlich an der Leitung horcht, wird das schnell auseinandernehmen können.

            Es gibt bereits ein System, das das Problem der sicheren Schlüsselübertragung und anschließenden Nachrichtenverschlüsselung löst: SSL und in diesem Falle HTTPS. Eine selbstgebaute »Verschlüsselung» hingegen ist meistens nutzlos und den Aufwand nicht wert.

            Grüße
            Mathias

          2. Mahlzeit,

            Ich verschlüssle/entschlüssle die Daten vor/nach der Übertragung client- und serverseitig mit AES in Verbindung mit einem Schlüssel, der aus den zu übertragenden Daten erzeugt wird und - versteckt - mit übertragen wird.

            Ist das nicht so als wenn du die Tür zusperrst und dann den Schlüssel mit Klebeband auf die Tür klebst?

            --
            42
            1. Hallo,

              Ich verschlüssle/entschlüssle die Daten vor/nach der Übertragung client- und serverseitig mit AES in Verbindung mit einem Schlüssel, der aus den zu übertragenden Daten erzeugt wird und - versteckt - mit übertragen wird.
              Ist das nicht so als wenn du die Tür zusperrst und dann den Schlüssel mit Klebeband auf die Tür klebst?

              ja, aber versteckt - also in einem Briefumschlag. :-)

              Ciao,
               Martin

              --
              Es existiert kein Weg, "für" etwas zu optimieren, sondern nur gegen alles andere.
                (Cheatah)
              Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
              1. Mahlzeit,

                ja, aber versteckt - also in einem Briefumschlag. :-)

                Oder unter der Fussmatte :D

                --
                42
            2. Hallo M,

              Ist das nicht so als wenn du die Tür zusperrst und dann den Schlüssel mit Klebeband auf die Tür klebst?

              Ich denke nicht, da der Key aus einzelnen Zeichen an verschiedenen Positionen aus dem zu übertragenden String erzeugt wird oder ist das unsicher? Derjenige, der an die Daten kommen möchte, weiß ja nicht, aus wie vielen und aus welchen Zeichen der Key besteht.

              Gruß,
              Enrico

              1. Mahlzeit,

                Ich denke nicht, da der Key aus einzelnen Zeichen an verschiedenen Positionen aus dem zu übertragenden String erzeugt wird oder ist das unsicher?

                Den  Schlüssel offen liegen zu lassen, ist IMMER unsicher. Wenn ich meinen Haustürschlüssel zersäge und im Hausflur verteile, kann er trotzdem leicht rekonstruiert werden.

                Derjenige, der an die Daten kommen möchte, weiß ja nicht, aus wie vielen und aus welchen Zeichen der Key besteht.

                Du erzeugst den Schlüssel per javascript, somit ist die Art der Erzeugung und die Position der Fragmente im Klartext einsehbar. Überdenk deine obige Aussage nochmal ;)

                --
                42
                1. Hallo M,

                  Du erzeugst den Schlüssel per javascript, somit ist die Art der Erzeugung und die Position der Fragmente im Klartext einsehbar

                  Ich verschleiere den JavaScript-Code natürlich.

                  "Deobfuskiert" man den Code, dann erhält man, exemplarisch, nur folgende Ausgabe:

                  q 2k(s)  
                  {  
                     q A(a, b)  
                     {  
                        S.k = a;  
                        S.l = b  
                     }  
                     r o = [9 A(2j, 2i), 9 A(2g, 2h), ... ], t = 9 3q(3l), x, y;  
                    
                     q B(s)  
                     {  
                        r a = [], Q = s.u * 8, i = 0;  
                        v(; i < Q; i += 8)  
                        {  
                           a[i >> 5] |= (s.3k(i / 8) & 3j) << (24 - (i % 32))  
                        }  
                        p a  
                     }  
                    
                     ...  
                  }
                  

                  Gruß,
                  Enrico

                  1. Ich verschleiere den JavaScript-Code natürlich.

                    Das doppelte Verschleiern macht es nicht besser. Ein Angreifer wird dennoch anschauen können, was das Skript treibt.

                    Im Gegenteil läufst Du in Gefahr, dass entsprechende Virenscanner auf das verdunkelte Javascript stoßen und die Weitergabe der Webseite an den Browser vermeiden. Google und andere Dienste könnten sogar zu der Meinung kommen, die Seite enthalte womöglich Schadcode und statt der Seite bekommt der Benutzer vom Browser eine Warnung gezeigt.

                    Da nimm besser https. Da bekommt der Benutzer auch eine Warnung, und die auch nur dann falls Du nicht die geringfügige Ausgabe für ein signiertes Serverzertifakt scheust. Bei vielen Webhostingangeboten gibt es den dazu, das hat den Vorteil, Du musst Dich beim Ablauf nicht drum kümmern, dass macht der Hoster automatisch.

                    Wenn ich die Arbeit sehe, die Du jetzt schon reingesteckt hast - du bist ja seit Monaten dran - dann wäre das sehr viel billiger gewesen.

                    Jörg Reinholz

                    1. Hallo Jörg,

                      Das doppelte Verschleiern macht es nicht besser

                      Im Gegenteil läufst Du in Gefahr, dass entsprechende Virenscanner auf das verdunkelte Javascript stoßen und die Weitergabe der Webseite an den Browser vermeiden. Google und andere Dienste könnten sogar zu der Meinung kommen, die Seite enthalte womöglich Schadcode und statt der Seite bekommt der Benutzer vom Browser eine Warnung gezeigt.

                      Hm, daran habe ich gar nicht gedacht ^^

                      Da nimm besser https. Da bekommt der Benutzer auch eine Warnung, und die auch nur dann falls Du nicht die geringfügige Ausgabe für ein signiertes Serverzertifakt scheust.

                      Entschuldige, wenn ich da jetzt dumm nachfrage, aber wie würde "das mit https" funktionieren?
                      Wie kann ich das auf meinem localhost einbinden und testen?

                      Bei vielen Webhostingangeboten gibt es den dazu, das hat den Vorteil, Du musst Dich beim
                      Ablauf nicht drum kümmern, dass macht der Hoster automatisch.

                      1und1 hätte auf jeden Fall ein Paket, das SSL unterstützt.

                      du bist ja seit Monaten dran - dann wäre das sehr viel billiger gewesen.

                      Wenn ich zum Zeitpunkt, als ich meinem Kumpel angeboten hatte, für unseren Mittelaltermarkt einen Webshop zu erstellen, gewusst hätte, wie viel Arbeit dahinter steckt, dann hätte ich hier wohl geschwiegen ^^

                      Gruß,
                      Enrico

                      1. Mahlzeit,

                        Wie kann ich das auf meinem localhost einbinden und testen?

                        indem du deinen Webserver entsprechend konfigurierst und passende Zertifikate erzeugst.
                        Leider sind die Infos über Betriebssystem, Webserver usw. aktuell nur dir bekannt.

                        --
                        42
                      2. Moin!

                        Entschuldige, wenn ich da jetzt dumm nachfrage, aber wie würde "das mit https" funktionieren?
                        Wie kann ich das auf meinem localhost einbinden und testen?

                        bei mir geht das mit einem Einzeiler:

                        ~ > sudo ln -s /etc/apache2/sites-available/default-ssl.conf /etc/apache2/sites-enabled/default-ssl.conf  
                        
                        

                        Die Beispielzertifikate sind die einer virtuellen Schlangenöl-Gesellschaft.

                        Mal ein wenig maulen: Es wird Zeit, dass auch das sysntax-highlighting für sh/bash ins Forum implementiert wird...

                        Jörg Reinholz

                  2. Mahlzeit,

                    Ich verschleiere den JavaScript-Code natürlich.

                    Es dürfte vermutlich einer der schlimmsten Fehler eines Programmierers sein, einen Hacker für dumm zu halten ;)

                    --
                    42
              2. Ich denke nicht, da der Key aus einzelnen Zeichen an verschiedenen Positionen aus dem zu übertragenden String erzeugt wird oder ist das unsicher?

                Es ist unsicher, denn Du gibst ja zwangsläufig das Programm und damit die Weise, wie der Key korrekt erzeugt wird, mit auf den Weg. Das ist bei Verschlüsselung ein schwerer Designfehler.

                Jörg Reinholz

      2. Dein Artikel ist sehr interessant, wenn ich auch noch nicht weiß, wie ich ihn verwenden könnte. Was verstehst Du unter "quasistatischen" Inhalten?

        Naja. Sowas wie die das Resultat der Bemühungen eines CMS, welches über einen langen Zeitraum auf die gleichen Requests hin auch unveränderte Webseiten erzeugt.

        Also sowas wie http://www.fastix.org/?seite=impressum

        Oder was Wordpress macht... oder ...

        Jörg Reinholz