PHP Asymmetrische Verschlüsselung (RSA)

joschilein

Multitalent
ID: 9301
L
5 Mai 2006
1.393
151
Ich habe mich die letzten Tage mal etwas in RSA eingelesen, da ich eine asymmetrische Verschlüsselung auf dem Server brauche. Es würden dann Daten gespeichert, die auch nicht (so leicht) zu knacken sind, wenn dem Angreifer die Datenbank und die PHP-Skripte zur Verfügung stünden. Erst im meinem Offline-System sollen sie mit dem dort vorliegenden (privaten) Schlüssel wieder gelesen werden können.

Nun hatte ich mir mal verschiedene Klassen angeschaut, die das Thema auf ziemlich unterschiedliche Weise angehen. Die Punkte 1 und 3 sind dabei vom Algorithmus her natürlich relativ nahe.

  1. ggf. Erzeugung der beiden/drei Schlüssel
  2. Unwandlung des Nachrichtentextes in Zahlenkolonnen
  3. Die Verrechnung der Zahlenkolonnen mit dem öffentlichen Schlüssel

Aber gerade der Punkt 2 scheint einen großen Unterschied zu bringen. In einer angeschauten Klasse werden z.B. fünf Zeichen aus dem Nachrichtentext entnommen, jeweils als zweistelliger Ascii-Code verbunden und damit ein 10stelliger Integer an Schritt 3 übergeben, wo dann bis zu 12stellige Integer entstehen.

Nun ist das Problem, dass der Zeichensatz dadurch begrenzt ist. Ist z.B. ein "ü" im Nachrichtentext, dann wird dieser Block hinterher falsch entschlüsselt.

Ich möchte den möglichen Zeichensatz erhöhen. Eine dreistellige Ascii-Representation führt aber auch zu Problemen, da selbst bei nur 4 Zeichen pro Block (3*4=12stellig bzw. 11stellig wegen meist führender 0) manche Blöcke falsch entschlüsselt werden. Das hat sicher mit der maximalen Größe von Integern zu tun.

Nun überlege ich den Schritt 2 so zu optimieren, dass in maximal 10 Stellen möglichst viele Zeichen bei einem möglichst großem Zeichensatz reingehen.

Wenn ich 250 Zeichen als Zeichensatz hätte (mal grob durchgezählt brauche ich mindestens 107, zweistellig reicht also keinesfalls), könnte ich z.B. jeweils 4 Zeichen zu einer dreistelligen Zahl verrechnen (4*250=1000; 000-999), also 9 Stellen für 12 Zeichen (bisher 10 Stellen für 5 Zeichen). Bei 10stelligem Ergebnis könnten es sogar zwei fünfer Blöcke à 400 Zeichen sein, also 10 Stellen für 800 Zeichen oder 200 bei 1000er Zeichensatz. Und man kann natürlich noch weiter denken und gleich alle 10 Stellen für 40 Mio (bei 250er Satz) bzw. 10 Mio (bei 1000er Satz) Zeichen nutzen.

Ich kann jetzt nur leider nicht beurteilen, ob sich dadurch die Sicherheit im letztlichen RSA Ergebnis ändert. Dieser wird dann selten über einen verschlüsselten Block hinauskommen. In Sachen Komprimierung wäre das natürlich Spitze. Aber vor allem: Hier geht es zwar nur um eine Verschlüsselung für mich selbst, aber wie wäre es wenn sowas auch zur gegenseitigen Kommunikation genutzt werden sollte? Der Empfänger müsste doch neben der eigentlichen Umkehrung der Verschlüsselung von Schritt 3 auch wissen wie das Blockergebnis in die einzelnen Zeichen des Nachrichtentextes umgesetzt werden soll, damit auch Schritt 2 "entschlüsseln" können. Diese Verschlüsselung geht zwar letztlich nicht über die Kraft von Cäsar&Co. hinaus, aber auf irgendein Verfahren müssen sich Sender und Empfänger ja einigen.

Zwar interessiert mich in erster Linie natürlich erstmal mein konkreter Ansatz, aber an der Theorie dahinter bin ich auch nicht ganz uninteressiert. Meine Recherchen dazu kommen aber irgendwie nicht weiter. Habe nur gelesen, dass Nachrichten i.d.R. symmetrisch verschlüsselt werden (z.B. AES) und nur der AES-Schlüssel dann per RSA verschlüsselt wird, was wohl insgesamt Geschwindigkeitsvorteile bringen soll.
 
Alle fertigen RSA-Klassen sind "unsicher" ;) Plain-RSA, also einfach die NAchricht gechunkt mit RSA verschlüsseln, sollte nicht genutzt werden, da es zu viele Angriffsvektoren gibt.
Das du aber nur solche Implementierungen findest, zeigt einfach, dass die meisten, die das dann Implementieren keinen Schimmer von Kryptographie haben oder nichtmal auf Wikipedia nachgesehen haben, wo mitlerweile auch schon davor gewarnt wird.
Auch sind die von solchen Leuten geschriebenen Algorithmen für die Schlüsselerzeugung nicht gut genug, einfach per Random 2 Zufallsprimzahlen wählen reicht nicht aus, damit RSA wirklich sicher ist, müssen auch noch einige Eigenschaften der Zufallszahlen erfüllt sein (sie dürfen z.B. nicht nahe aneinander liegen usw.)
Das es soviele Möglichkeiten gibt die Daten in Zahlen abzubilden ist einfach, dass RSA nur auf Zahlen definiert wurde, nicht wie man Byte-Ketten in Zahlen umwandelt, da macht dann eben jeder dieser "Möchtegerns" seine eigene Suppe.

Wenn man RSA sicher nutzen will, solltest du zu OpenSSL greifen (ist auch in PHP vorhanden). Dort wird dann ein Padding genutzt (PKCS1 wenn ich mich recht entsinne), die Schlüssel werden sicher erzeugt und die verschlüsselte Version ist auch mit anderen Libraries oder Programmiersprachen wieder entschlüsselbar, da man sich an einen Standard hält.

Dein letzter angesprochener Punkt nennt sich "hybride Verschlüsselung". Deine echten Daten werden mit einem schnellen symmetrischen Verfahren (AES) verschlüsselt. Der Key der dafür genutzt wurde aber dann mit dem langsamen asymmetrischen Verfahren (RSA). Dadurch hast du den Geschwindigkeitsvorteil und den Sicherheitsvorteil.

Kurz gesagt: Nutze keine dieser reinen PHP-Implementierungen von Hinz-und-Kunz sondern nimm die OpenSSL-Variante, die stammt von vielen Personen, wurde viel korrekturgelesen und gilt als sicher, ganz anders als diese PHP-Versionen.
 
Ich bin ja nun auch nicht gerade der geborene Kryptograph (wenn man mal den Bereich Polysemie ausnimmt :ugly:).

Was macht denn RSA eigentlich zu RSA? Letztlich ist es doch der beschriebene Punkt 3, oder?

Gibt es eigentlich andere asymmetrische Verfahren, die besser, schneller, sicherer, .. sind? Bei Geschwindigkeit gerade im Bezug auf PHP? Oder können das die hybriden Varianten als quasi-asymmetrisch schon abbilden?

Die verschiedenen Schwachpunkte habe ich mir natürlich auch schon angeschaut, aber ehrlich gesagt nicht verstanden gehabt. Aber wenigstens blicke ich mittlerweile schon etwas klarer durchs CrypTool als noch vor ein paar Jahren.

Dass die verschiedenen Klassen Schwachstellen haben, war mir schon klar. Highlight ist eine Klasse, die die Primzahlen erst in der Laufzeit errechnen möchte und damit natürlich jedes Zeitlimit sprengt :ugly: Ich hätte mir dann schon dann ein Schlüsselpaar aus dem Kryptool geangelt, anstatt die megakurzen Klassenschlüssel zu verwenden. Der eigentliche Algorithmus müsste doch dann aber überall gleich sein?! (-> Was macht RSA zu RSA?)

OpelSSL schaue ich mir dann mal an. Online ist es vorhanden, offline muss ich es erst noch installieren/aktivieren.
 
Was macht denn RSA eigentlich zu RSA? Letztlich ist es doch der beschriebene Punkt 3, oder?
Neija RSA ist erstmal ein Verschlüsselungsverfahren welches damals auf Zahlen definiert wurde (man kann ja alles in eine Zahl umwandeln), bei denen die maximale Zahl kleiner als das N sein muss.

Gibt es eigentlich andere asymmetrische Verfahren, die besser, schneller, sicherer, .. sind?
Neija, da gibt es noch El Gamal, ob das irgendwo eingesetzt wird weiß ich gar nicht, aber im Gegensatz zu RSA konnte man dessen Sicherheit beweisen, bei RSA vermutet man, dass es sicher ist, weil man vermutet, dass es keine effiziente Möglichkeit der Primfaktorzerlegung gibt, bei den Logarithmen von El Gamal kann man das wohl beweisen. Frag mich nicht wieso, als der Beweis geführt wurde bin ich vorne und hinten nicht mitgekommen :biggrin:

Bei Geschwindigkeit gerade im Bezug auf PHP?
Es gibt da noch NTRUEncrypt welches behauptet sicher zu sein und vielfach schneller als RSA, was davon stimmt kann ich dir nicht sagen. Da das Verfahren patentiert ist, ist die Verbreitung wirklich sehr dürftig.

Oder können das die hybriden Varianten als quasi-asymmetrisch schon abbilden?
Hybride Verfahren sind schon extrem effizient ;) PGP verwendet per Default ein hybrides Verfahren, soweit ich mich erinnere (2. wenn :LOL:)

Ich hätte mir dann schon dann ein Schlüsselpaar aus dem Kryptool geangelt, anstatt die megakurzen Klassenschlüssel zu verwenden.
Schlüssel aus dem Cryptool zu nutzen erachte ich nicht als sehr sinnvoll, da diese Software dafür gedacht ist, kryptographische Verfahren näher zubringen, also auch nicht unbedingt Wert auf die kryptografisch sicherste Implementierung legen.
Wenn du dagegen die PKCS12 Keyfiles von z.B. OpenSSL nimmst, kannst du dir wenigstens sicher sein, dass diese auch wirklich möglichst optimal erzeugt wurden.

Der eigentliche Algorithmus müsste doch dann aber überall gleich sein?! (-> Was macht RSA zu RSA?)
Ja, RSA ist überall identisch. Aber RSA ist eben nur als Operation auf Zahlen definiert. Wie man aber aus binärem Input eine Zahl bildet ist durch RSA nicht definiert. Wenn man dort sicherstellen will, dass es überall gleich gemacht wird muss man eben Verfahren wie PKCS1 nutzen.
Aber PKCS1 wird eben von keiner PHP-Klasse implementiert, da man sich dann erstmal durch ein RFC wälzen müsste, und das scheuen die meisten Entwickler dann (warum auch immer). Diese fertigen PHP-Klassen sind also wenn es wirklich auf Sicherheit ankommt zu nichts zu gebrauchen.
 
Also irgendwie bekomme ich openssl nicht hin. Die Extension ist freigeschaltet, die entsprechenden Funktionen sind nun auch definiert, aber openssl_pkey_new() liefert nur ein FALSE und über openssl_error_string() bekomme ich
Code:
error:02001003:system library:fopen:No such process
error:2006D080:BIO routines:BIO_new_file:no such file
error:0E064002:configuration file routines:CONF_load:system lib
error:02001003:system library:fopen:No such process
error:2006D080:BIO routines:BIO_new_file:no such file
error:0E064002:configuration file routines:CONF_load:system lib
Das Problem findet sich im Netz häufiger, aber Lösungen habe ich keine finden können.

Das habe ich natürlich schon oft gelesen. Beide dlls sind auch vorhanden, die Konstanten habe ich auch selbst geschrieben, aber selbst mit absoluten Pfaden funktioniert es nicht. Da das in einer portablen xampp Umgebung laufen soll, wären Laufwerksbuchstaben eh nicht so toll, aber es geht ja nichtmal mit. :(
 
Und die .cnf Datei bzw. darin angegebene Pfade liegen so, dass der Webserver da drin lesen/schreiben darf?