2012-06-10 16 views
7

Ich habe nur einige sehr rudimentäre theoretische Kenntnisse über RSA.Exchange Public/Private Key in PKCS # 1 OAEP Verschlüsselung/Entschlüsselung

Beim Lesen verschiedener Quellen über die Verwendung in der Praxis schien PKCS # 1 OAEP eine gute Sache zu sein.

Für eine Test-Implementierung verwende ich Python mit PyCrypto. Z.B. this ist ein Beispiel mit PKCS # 1 OAEP.

Die Verschlüsselung mit dem öffentlichen Schlüssel und die Entschlüsselung mit dem privaten Schlüssel funktioniert einwandfrei. Z.B. Die Öffentlichkeit kann einige Daten mit dem privaten Schlüssel an Person X senden.

Von meinem grundlegenden Verständnis, wie RSA funktioniert, dachte ich, dass ich nur den öffentlichen/privaten Schlüssel austauschen kann, d.h. ich kann den öffentlichen Schlüssel zum Verschlüsseln und den privaten Schlüssel zum Entschlüsseln verwenden. Z.B. Person X kann einige Daten mit ihrem eigenen privaten Schlüssel verschlüsseln, und die Öffentlichkeit kann sie mit dem öffentlichen Schlüssel entschlüsseln. Wenn die Entschlüsselung funktioniert, gibt dies eine Art Beweis, dass die Daten von Person X stammen.

PyCrypto beschwert sich, wenn ich versuche, mit dem öffentlichen Schlüssel zu entschlüsseln.

Von den PyCrypto Quellcode zu lesen, in der _RSAKey._decrypt Funktion (here), so scheint es, dass der Schlüssel Objekt selbst weiß, ob es die private oder öffentliche Schlüssel ist, und unterscheidet sich zwischen ihnen (zu meiner Überraschung, wieder auf Grund meiner sehr einfach RSA Verständnis).

Von dort sieht es so aus, als könnte ich die Entschlüsselungsfunktion hacken, so dass sie den öffentlichen Schlüssel verwendet. Oder etwas anders: Ich könnte einfach den öffentlichen Exponenten e und den privaten Exponenten d in den Schlüsselobjekten austauschen.

Aber das alles scheint so zu sein, dass es nicht so verwendet werden soll. Also wollte ich hier nach meinen Missverständnissen fragen.

Auch nur aus Neugier, erzeugen ich einige Tasten (RSA.generate(2048)) und sah n, e und d. In allen Fällen war n und d sehr groß, während e in allen Fällen Konstante (65537) war (hätte ich nicht erwartet).

Ich denke von all dem, dass ich nicht wirklich e und d austauschen sollte.

Also ich denke, ich sollte eine andere Methode für die Signatur wie PKCS1_PSS verwenden.


Einige Code für die Verschlüsselungs-/Entschlüsselungs, wenn jemand interessiert: (. binstruct ist ein kleines Modul, das/Strukturen Baumdaten dekodieren kodieren kann - ähnlich wie JSON/BSON)

def randomString(l): 
    import random 
    return ''.join(chr(random.randint(0, 0xFF)) for i in range(l)) 

def genkeypair(): 
    from Crypto.PublicKey import RSA 
    key = RSA.generate(2048) 
    pubkey = key.publickey().exportKey("DER") 
    privkey = key.exportKey("DER") 
    return (pubkey,privkey) 

def encrypt(v, rsapubkey): 
    from Crypto.PublicKey import RSA 
    rsakey = RSA.importKey(rsapubkey) 
    from Crypto.Cipher import PKCS1_OAEP 
    rsa = PKCS1_OAEP.new(rsakey) 
    import binstruct 
    from array import array 
    aeskey = randomString(32) 
    iv = randomString(16) 
    from Crypto.Cipher import AES 
    aes = AES.new(aeskey, AES.MODE_CBC, iv) 
    data = binstruct.varEncode(v) 
    data += array("B", (0,) * (-len(data) % 16)) 
    out = binstruct.strEncode(rsa.encrypt(aeskey + iv)) 
    out += array("B", aes.encrypt(data)) 
    return out 

def decrypt(stream, rsaprivkey): 
    from array import array 
    from StringIO import StringIO 
    if isinstance(stream, array): stream = stream.tostring() 
    if isinstance(stream, str): stream = StringIO(stream) 
    from Crypto.PublicKey import RSA 
    rsakey = RSA.importKey(rsaprivkey) 
    from Crypto.Cipher import PKCS1_OAEP 
    rsa = PKCS1_OAEP.new(rsakey) 
    import binstruct 
    aesdata = binstruct.strDecode(stream) 
    aesdata = rsa.decrypt(aesdata) 
    aeskey = aesdata[0:32] 
    iv = aesdata[32:] 
    from Crypto.Cipher import AES 
    aes = AES.new(aeskey, AES.MODE_CBC, iv) 
    class Stream: 
     buffer = [] 
     def read1(self): 
      if len(self.buffer) == 0: 
       nextIn = stream.read(16) 
       self.buffer += list(aes.decrypt(nextIn)) 
      return self.buffer.pop(0) 
     def read(self, n): 
      return "".join([self.read1() for i in range(n)]) 
    v = binstruct.varDecode(Stream()) 
    return v 

Das ist, wo ich dachte, ich könnte auch encrypt mit dem privaten Schlüssel und und decrypt mit dem öffentlichen Schlüssel verwenden.


Die endgültige Umsetzung mit (hoffentlich) richtige Signierung/Authentifizierung kann here in binstruct gefunden werden.

+0

"PyCrypto beschwert sich, wenn ich versuche, mit dem öffentlichen Schlüssel zu entschlüsseln". Bitte seien Sie genauer und zeigen Sie Ihren Code. –

+0

@GregS: Es wird 'TypeError (" Kein privater Schlüssel ")' in '_RSAKey._decrypt' ausgelöst. Wie Sie aus dem verknüpften Code sehen können. Das ist, was ich gesagt habe. Es scheint, dass es den privaten Schlüssel beim Entschlüsseln benötigt. – Albert

+0

Wenn Sie nur über rudimentäre Kenntnisse der Kryptographie verfügen, können Sie die API nicht so verwenden, wie sie nicht verwendet werden soll. Ich habe 10 Jahre Erfahrung und bin sogar ziemlich vorsichtig, wenn ich kryptografische Bibliotheken auf eine Art und Weise verwende, die ich nicht sollte - und ich versuche, dies so weit wie möglich zu vermeiden. –

Antwort

15

Ihr allgemeines Verständnis über die Rolle der öffentlichen und privaten Schlüssel Vertauschen ist richtig. Am Ende wird RSA basiert auf der Tatsache, dass

m^(ed) congruent m (mod n) 

Was normalerweise RSA-Verschlüsselung trug den Titel ist in der Regel der Betrieb

m^e mod n, 

die Nachricht an die E-te Potenz erhöhen, wobei e der öffentliche Schlüssel .

Decryption ist dann

(m^e)^d mod n, 

die verschlüsselte Nachricht an die d-te Potenz mit d der private Schlüssel ist. Jetzt, da die Regeln der Potenzierung und die Tatsache, dass die Multiplikation kommutativ ist (diese halten nach wie vor in der modularen Arithmetik) haben wir, dass

m congruent (m^e)^d congruent m^(ed) congruent m^(de) congruent (m^d)^e, 

und daher erhalten Sie das gleiche Ergebnis, wenn Sie die Vorgänge in umgekehrter Reihenfolge anwenden.

Sie hatten recht, wenn Sie annehmen, dass die Umkehrung zu digitalen Signaturen führt, weil jeder die Signatur mit dem öffentlichen Schlüssel e verifizieren ("entschlüsseln") kann, sodass die Nachricht nur authentisch war, wenn sie "verschlüsselt" (signiert) wurde der entsprechende private Schlüssel d.

Wie sich herausstellt, PyCrypto nur versucht, Sie zu verhindern, dass eine Verwechslung für die anderen hier, OpenSSL oder Ruby OpenSSL können Sie for example beides tun: public_encrypt/public_decrypt und private_encrypt/private_decrypt.

So viel zur Theorie, jetzt, warum es gibt gute Gründe für nicht lassen Sie sie austauschbar verwendet werden. Was ich gerade beschrieben habe, wird oft als "Lehrbuch RSA" bezeichnet und ist noch lange nicht sicher. Um das Ergebnis in der Praxis nutzbar zu machen, muss auf zusätzliche Dinge geachtet werden. Und deshalb gibt es in PyCrypto eine dedizierte signature package - das macht effektiv das, was du beschrieben hast, aber kümmert sich auch zusätzlich um die Dinge, die ich erwähnt habe. Während es gut für unser Verständnis ist, zu wissen, wie diese Dinge funktionieren, sollten wir solche Pakete immer in der Praxis verwenden, weil sie bereits die Fehler gemacht und korrigiert haben, die wir wahrscheinlich einführen würden, wenn wir unsere eigenen rollen.

Warum e ist immer 65537. Es muss nicht wirklich ein fester Wert sein, aber es wird allgemein als eine sehr kleine Zahl mit so wenig 1 in seiner binären Darstellung wie möglich gewählt (65537 ist 10001) . In der Vergangenheit wurden auch e = 3 oder e = 17 gewählt, sie wurden jedoch in der Praxis als nicht sicher angesehen, da sie angegriffen werden konnten, indem einfach die dritte oder 17. Wurzel des Geheimtextes genommen wurde. Wenn e = 3 und m = 3, dann ist 3^3 27, und es braucht kein Genie, um herauszufinden, dass m 3 ist, vorausgesetzt, dass der Chiffretext 27 ist, unabhängig vom Modul n (das typischerweise viel größer ist). Die Gefahr liegt also darin, dass der Chiffretext selbst nach der Potenzierung nicht die "Modulgrenze" durchquert und uns daher erlaubt, einfach die e-te Wurzel zu nehmen, um zu der ursprünglichen Nachricht zu gelangen. Mit typischen Modulen von 1024 - 4096 Bits ist dies kein Problem mehr mit e = 65537.

Wenige 1en in der binären Darstellung ist auch gut für die Berechnung schnell m^e. Modulare Exponentiation wird oft unter Verwendung eines Multiply and Square Algorithmus implementiert, und die Leistung ist am besten für kleine e mit wenigen Einsen. Warum wird es auf diese Weise gewählt und nicht umgekehrt, zum Beispiel mit einem kleinen d mit wenigen 1? Nun, für Anfänger wäre d einfacher zu erraten. Ein zweiter Vorteil besteht darin, dass Sie mit digitalen Signaturen ein Dokument normalerweise einmal signieren, es jedoch häufig verifizieren. Das bedeutet, dass einmal ausgeführt wird, aber oft, so dass Sie die häufigste Aufgabe am besten ausführen, während die seltene Aufgabe schlecht ausgeführt werden kann.

Edit:

Sie gefragt, ob ich könnte weiter erklären, was Systeme wie RSA-PSS tun, um sicher zu sein.

Wenn Sie vergleichen, was OAEP für die Verschlüsselung tut und was PSS für Signaturen tut, sehen die beiden ziemlich ähnlich aus. Und tatsächlich sind sie beide, sie führen beide eine Randomisierung in den Prozess ein, die unter bestimmten Annahmen eine nachweisbare Sicherheit von OAEP und PSS ermöglicht. Ich fand auch diese paper, um hilfreich zu sein. Nachweisbare Sicherheit ist ein großer Vorteil gegenüber der PKCS 1.5-Verschlüsselung und -Signaturen der alten Schule, die sich unter denselben Annahmen als nicht nachweisbar sicher erweisen (Kernpunkt: kein deterministisches Schema möglich, Randomisierung ist wesentlich). Ein offensichtlicher Unterschied zwischen den vorgeschlagenen Signatur- und Verschlüsselungsschemata besteht darin, dass die Signaturschemata immer vorschreiben, dass die zu signierende Nachricht zuerst gehasht wird. Dies ist nicht nur im Hinblick auf die Effizienz sinnvoll, sondern verhindert auch einige Angriffe, die sonst möglich wären. Und ich denke, das führt zu dem Grund, warum wir immer Signaturschemata für Signaturen und Verschlüsselungsschemata für die Verschlüsselung verwenden sollten: Die vorgeschlagenen Schemata sind mit Sicherheitshinweisen versehen, unsere handgemachten Schemata nicht.

Kryptografen erfinden diese Schemata, um das Leben von uns Normalsterblichen einfacher zu machen - sie geben uns Werkzeuge, die im Idealfall keinen Missbrauch oder Missbrauch zulassen, indem wir die Anzahl der Optionen auf ein Minimum reduzieren. Selbst wenn Sie beispielsweise mit RSA-OAEP ein gutes Signaturschema erstellen, weiß jemand, der es verwendet, möglicherweise nicht, warum sie ihre Nachrichten zuerst hashen sollten, bevor sie die Signatur anwenden. Diese Art von Missbrauch ist mit RSA-PSS nicht möglich.

Sie fragte auch nach etwas gutes Lesematerial. Obwohl dies ein sehr subjektives Thema ist, genoss ich wirklich diese:

Die praktische Seite:

  • Applied Cryptography - immer noch ein Klassiker und lesenswert. Einige Sicherheitsleute sagen, dass es gefährlich ist, weil es Leute dazu bringt zu glauben, dass sie genug wissen, um ihr eigenes Krypto zu schreiben. Aber ich denke, wir sind alle Erwachsene, nicht wahr? Es ist immer noch großartig, ein Gefühl für "was ist da draußen" zu haben

  • Cryptography Engineering - Hat einige gute praktische Ratschläge und erwähnt auch die Vorbehalte bei der Implementierung von Kryptografie-Code.

  • Handbook of Applied Cryptography - Es ist kostenlos und hat immer noch eine Menge guter Ratschläge, insbesondere im Hinblick auf die Implementierungen.

Die theoretische Seite:

  • Modern Cryptography - Es ist ein Hybrid zwischen Theorie und Praxis und eine Menge Einblicke hat, wie die Dinge in der Praxis schief gehen.

  • Cryptography - Theory and Practice - das war ein Spiel für mich Wechsler, ich Liebe dieses Buch. Wenn Sie nur ein Buch lesen, lassen Sie es dieses sein :)

  • Introduction to Modern Cryptography - macht einen großen Job bei der Erklärung der "modernen Ansatz" und wie die Sicherheitsnachweise tatsächlich funktionieren und unter welchen Annahmen.

  • Foundations of Cryptography I&II - Wenn Sie nach dem vorherigen Buch immer noch nicht genug von der Theorie der Einwegfunktionen und Freunde bekommen können, dann ist dies Ihr Buch. Sehr technisch.

Sicherheit ist nicht nur Kryptographie:

  • Security engineering - hat zahlreiche Beispiele, wie solide Prinzipien

  • Information Security in der Praxis schief gehen können - ähnlich wie Security Engineering, illustriert Sicherheit in einem Umfang breiter als nur Kryptographie.

Abgesehen davon versuche ich durch das Lesen neueren Arbeiten über neue Angriffe auf dem Laufenden zu halten, Technologien etc. Ich r/netsec sehr hilfreich, sowie folgende Forscher und Praktiker auf Twitter gefunden, sie Post interessantes Material regelmäßig .

Schließlich, wenn Sie die Zeit haben, nehmen Sie die Kryptographie Kurse auf Coursera und Udacity! Ich denke, sie werden in den nächsten Wochen wieder anfangen, sie sind wirklich großartig, ich bin mir sicher, dass du es nicht bereuen wirst. Sie hatten viele praktische Übungen, die viel Spaß machen und verschiedene Möglichkeiten zum Angriff auf Kryptographie-Implementierungen veranschaulichen.

+1

Danke, sehr hilfreich! - "Weitere Dinge müssen erledigt werden [..]. [Das Signaturpaket] kümmert sich zusätzlich um die Dinge, die ich erwähnt habe". Ich denke, du hast diese Dinge nicht explizit erwähnt oder ich habe sie nicht verstanden. Welche zusätzlichen Dinge? Esp., Warum RSASSA-PSS und nicht RSAES-OAEP (Verschlüsselung mit dem privaten Schlüssel) für die Signatur verwenden? - Kannst du vielleicht einige weiterführende Quellen dazu empfehlen, wie man von theoretischem RSA-Wissen zum praktischen Gebrauch kommt? (Weil ich selbst für die meisten Bibliotheken meist nur triviale Beispiele sehe.) – Albert

+0

@Albert Ich habe meine Antwort aktualisiert, hoffe das hilft? – emboss

Verwandte Themen