Frage:
Lehren und Missverständnisse in Bezug auf Verschlüsselung und Kryptologie
goodguys_activate
2011-02-20 01:25:34 UTC
view on stackexchange narkive permalink

Kryptologie ist ein so weit gefasstes Thema, dass selbst erfahrene Programmierer in den ersten paar Fällen fast immer Fehler machen. Die Verschlüsselung ist jedoch ein so wichtiges Thema, dass wir uns diese Fehler oft nicht leisten können.

Mit dieser Frage soll ermittelt und aufgelistet werden, was nicht mit einem bestimmten Algorithmus oder einer bestimmten API zu tun hat. Auf diese Weise können wir aus den Erfahrungen anderer lernen und die Verbreitung schlechter Praktiken verhindern.

Um diese Frage konstruktiv zu halten,

  1. Fügen Sie bitte ein "falsches" Beispiel
  2. hinzu
  3. Erklären Sie, was an diesem Beispiel falsch ist.
  4. Geben Sie eine korrekte Implementierung an (falls zutreffend).
  5. Geben Sie nach besten Kräften Referenzen zu Nr. 2 und Nr. 3 an.
Die häufigsten Fehler sind keine Fehler im Code, sondern falsche Vorstellungen über die Verwendung der Kryptografie. Mit anderen Worten, der Entwickler würde wahrscheinlich in jeder Sprache den gleichen Fehler machen. Daher empfehle ich, die Frage so zu erweitern, dass sie sich nicht so auf Code konzentriert. Die meisten Fehler sind konzeptionelle Fehler, keine Codierungsfehler.
Auch wenn eine Antwort akzeptiert wird, fügen Sie weiterhin die gewonnenen Erkenntnisse hinzu. Zumindest wird es lehrreich sein.
Außerdem eine kurze und einfache Präsentation von Colin Percival (tarsnap): http://www.bsdcan.org/2010/schedule/attachments/135_crypto1hr.pdf
Machen Sie keine Kryptographie, wenn Sie "Nicht tun" -Listen lesen müssen. Bitten Sie einen auf Kryptografie spezialisierten Sicherheitsingenieur um Hilfe. :) :)
Verwandte Metadiskussion: [Klarstellung zwischen "Rollen Ihrer eigenen Kryptografie" und "Implementieren eines Standards"] (http://meta.security.stackexchange.com/q/1119/396)
In den meisten Fällen führen Sie keine Kryptografie durch, wenn Sie der Meinung sind, dass Sie die Liste "Nicht tun" nicht erstellen müssen (https://en.wikipedia.org/wiki/Dunning%E2%80%93Kruger_effect) - Dave war sich sicher seine Umsetzung war sicher.
Obwohl diese Frage einige sehr wichtige Themen abdeckt, passt das Format nicht gut zu SE-Sites, da im Grunde genommen eine "Liste von X" abgefragt wird, die nicht gut funktioniert.
21 antworten:
#1
+76
D.W.
2011-02-20 09:52:34 UTC
view on stackexchange narkive permalink

Rollen Sie keine eigene Krypto.

Erfinden Sie keinen eigenen Verschlüsselungsalgorithmus oder -protokoll. das ist extrem fehleranfällig. Wie Bruce Schneier gerne sagt:

"Jeder kann einen Verschlüsselungsalgorithmus erfinden, den er selbst nicht brechen kann. Es ist viel schwieriger, einen zu erfinden, den niemand sonst brechen kann."

Krypto-Algorithmen sind sehr kompliziert und müssen intensiv überprüft werden, um sicherzustellen, dass sie sicher sind. Wenn Sie Ihre eigenen erfinden, werden Sie das nicht bekommen, und es ist sehr leicht, mit etwas Unsicherem zu enden, ohne es zu merken.

Verwenden Sie stattdessen einen standardmäßigen kryptografischen Algorithmus und ein Standardprotokoll. Es besteht die Möglichkeit, dass jemand anderes zuvor auf Ihr Problem gestoßen ist und einen geeigneten Algorithmus für diesen Zweck entwickelt hat.

Am besten verwenden Sie ein gut geprüftes Schema auf hoher Ebene: Verwenden Sie für die Kommunikationssicherheit TLS (oder SSL) ); Verwenden Sie für ruhende Daten GPG (oder PGP). Wenn Sie dies nicht tun können, verwenden Sie anstelle von a eine übergeordnete Kryptobibliothek wie cryptlib, GPGME, Keyczar oder NaCL Low-Level-One wie OpenSSL, CryptoAPI, JCE usw. Vielen Dank an Nate Lawson für diesen Vorschlag.

Eigentlich sollte dies Regel Nummer 1 sein - was alle unsere anderen Regeln ungültig machen würde. Es gibt wahrscheinlich nur wenige hundert Menschen auf der Welt, die Krypto entwerfen oder implementieren sollten. Der Rest von uns sollte nur ihre (gesunde) API verwenden.
Was ist die beste Option für einen .NET-Entwickler? Irgendwelche Tutorials oder Beispiele? Für einen Nicht-Krypto-Experten ist es schwierig, Fehlinformationen anhand der Gültigkeit zu ermitteln.
Es ist besonders verlockend für den kreativen Ingenieur, der in der Vergangenheit schwierige Probleme gelöst hat, die Krypto jemand anderem zu überlassen. Außerhalb von Krypto gibt es immer noch viele schwierige und wichtige Probleme zu lösen. Schauen Sie sich die Beispiele von Menschen an, die in der Krypto kritische Fehler gemacht haben, und lösen Sie etwas anderes.
+1 Die Crypto-API bietet zu viel Flexibilität, um den Laienentwickler in Schwierigkeiten zu bringen. Es gibt viele Beispiele im Internet (und auf der Support-Website von MSFT), die gegen mindestens eine der auf dieser Seite gewonnenen Erkenntnisse verstoßen. Einige Entwickler vergessen, Dinge wie den Austausch, die Validierung und den Widerruf von Schlüsseln zu berücksichtigen. Hier wird es dornig. Wo werden die Schlüssel aufbewahrt? Wie werden Schlüssel veröffentlicht? Wie werden Schlüssel validiert? Wie erfolgt die Tastenrotation? Selbst wenn der Entwickler das Glück hat, die Mathematik oder die Kombination von Funktionen (CBC, Block, Stream usw.) richtig zu machen, ist das Protokoll möglicherweise fehlerhaft.
Für eine High-Level-Option für .net habe ich [keyczar to C #] portiert (http://jbtule.github.com/keyczar-dotnet/).
"TLS verwenden" ohne Kleingedrucktes ist keine so gute Idee, wenn wir [dies] sehen (http://www.isg.rhul.ac.uk/tls/)
Es kann keine Regel der Kryptologie sein, keine Krypto zu erfinden, und es ist kein Missbrauch einer vorhandenen API oder eines vorhandenen Algorithmus.
#2
+47
D.W.
2011-02-20 09:36:29 UTC
view on stackexchange narkive permalink

Verwenden Sie keine Verschlüsselung ohne Nachrichtenauthentifizierung.

Es ist ein sehr häufiger Fehler, Daten zu verschlüsseln, ohne sie auch zu authentifizieren.

Beispiel: Der Entwickler möchte eine Nachricht geheim halten, verschlüsselt die Nachricht daher im AES-CBC-Modus. Der Fehler: Dies ist für die Sicherheit bei aktiven Angriffen, Wiederholungsangriffen, Reaktionsangriffen usw. nicht ausreichend. Es sind Angriffe auf die Verschlüsselung ohne Nachrichtenauthentifizierung bekannt, und die Angriffe können sehr schwerwiegend sein. Das Update besteht darin, die Nachrichtenauthentifizierung hinzuzufügen.

Dieser Fehler hat zu schwerwiegenden Sicherheitslücken in bereitgestellten Systemen geführt, die Verschlüsselung ohne Authentifizierung verwendeten, einschließlich ASP.NET, XML Verschlüsselung, Amazon EC2, JavaServer Faces, Ruby on Rails, OWASP ESAPI, IPSEC, WEP, erneut ASP.NET und SSH2. Sie möchten nicht der nächste in dieser Liste sein.

Um diese Probleme zu vermeiden, müssen Sie bei jeder Anwendung der Verschlüsselung die Nachrichtenauthentifizierung verwenden. Sie haben zwei Möglichkeiten, dies zu tun:

  • Die wahrscheinlich einfachste Lösung besteht darin, ein Verschlüsselungsschema zu verwenden, das authentifizierte Verschlüsselung bietet, z. B. GCM, CWC, EAX, CCM, OCB. (Siehe auch: 1.) Das authentifizierte Verschlüsselungsschema übernimmt dies für Sie, sodass Sie nicht darüber nachdenken müssen.

  • Alternativ: Sie können Ihre eigene Nachrichtenauthentifizierung wie folgt anwenden. Verschlüsseln Sie zuerst die Nachricht unter Verwendung eines geeigneten Verschlüsselungsschemas mit symmetrischem Schlüssel (z. B. AES-CBC). Nehmen Sie dann den gesamten Chiffretext (einschließlich aller IVs, Nonces oder anderer Werte, die für die Entschlüsselung erforderlich sind), wenden Sie einen Nachrichtenauthentifizierungscode an (z. B. AES-CMAC, SHA1-HMAC, SHA256-HMAC) und hängen Sie den resultierenden MAC-Digest an den an Chiffretext vor der Übertragung. Überprüfen Sie auf der Empfangsseite, ob der MAC-Digest gültig ist, bevor Sie ihn entschlüsseln. Dies wird als Verschlüsselungs- und Authentifizierungskonstruktion bezeichnet. (Siehe auch: 1, 2.) Dies funktioniert ebenfalls einwandfrei, erfordert jedoch etwas mehr Sorgfalt von Ihnen.

C # - und Java-Benutzer sollten sich [BouncyCastle] ansehen (http://www.bouncycastle.org/csharp/).
@makerofthings7: GCM-Verschlüsselung ist im Oracle-Anbieter in Java 7 enthalten. Sie wird auch für TLS (innerhalb eines RFC) und XML-Verschlüsselung v1.1 vorgeschlagen. Die Bouncy-Implementierung ist mit der Implementierung innerhalb des Sun-Anbieters kompatibel (mit Ausnahme von Unterschieden hinsichtlich authentifizierter Daten und der genauen ausgelösten Ausnahme).
Für diejenigen, die mit Kryptografie noch nicht vertraut sind (daher diesen Beitrag lesen), hat "Authentifizierung" nichts mit "Anmelden" oder der Verwendung Ihrer Anmeldeinformationen zu tun. Es ist so etwas wie eine Prüfsumme. In Wirklichkeit ist es die Kombination von Mathematik und Prozessen, die letztendlich viel mehr bewirkt, als nur die Daten zu überprüfen. (@D.W. Was halten Sie von dieser Erklärung für Laien?)
@makerofthings7, tolle Erklärung! Vielleicht wäre es klarer, wenn sich der Artikel eher auf "Nachrichtenauthentifizierung" als nur auf generische Authentifizierung beziehen würde. Ich werde das jetzt ändern.
#3
+36
D.W.
2011-02-20 11:29:57 UTC
view on stackexchange narkive permalink

Seien Sie vorsichtig, wenn Sie mehrere Zeichenfolgen vor dem Hashing verketten.

Ein Fehler, den ich manchmal sehe: Die Leute möchten einen Hash der Zeichenfolgen S und T. Sie verketten sie, um eine zu erhalten einzelne Zeichenfolge S || T, dann Hash, um H (S || T) zu erhalten. Dies ist fehlerhaft.

Das Problem: Durch die Verkettung wird die Grenze zwischen den beiden Zeichenfolgen nicht eindeutig. Beispiel: eingebaut || sicher = gebaut || unsicher . Anders ausgedrückt, der Hash H (S || T) identifiziert die Zeichenfolge S und T nicht eindeutig. Daher kann der Angreifer möglicherweise die Grenze zwischen den beiden Zeichenfolgen ändern, ohne den Hash zu ändern. Wenn Alice beispielsweise die beiden Zeichenfolgen integriert und sicher senden möchte, kann der Angreifer sie in die beiden Zeichenfolgen erstellt und ändern unsicher ohne den Hash ungültig zu machen.

Ähnliche Probleme treten auf, wenn eine digitale Signatur oder ein Nachrichtenauthentifizierungscode auf eine Verkettung von Zeichenfolgen angewendet wird.

Der Fix: statt einer einfachen Verkettung Verwenden Sie eine Codierung, die eindeutig decodierbar ist. Anstatt H (S || T) zu berechnen, könnten Sie beispielsweise H (Länge (S) || S || T) berechnen, wobei Länge (S) ein 32-Bit-Wert ist, der die Länge von S in Bytes angibt. Eine andere Möglichkeit besteht darin, H (H (S) || H (T)) oder sogar H (H (S) || T) zu verwenden.

Für ein reales Beispiel dieses Fehlers Siehe diesen Fehler in Amazon Web Services oder diesen Fehler in Flickr [pdf].

Ich werfe normalerweise HMAC darauf. Etwas teurer, aber zumindest muss ich es nicht selbst implementieren.
@CodeInChaos, Diese Probleme gelten auch für HMAC. HMAC hilft nichts, wenn Sie mehrere Zeichenfolgen verketten, bevor Sie sie an HMAC weiterleiten.
Was ich damit gemeint habe ist, dass ich einen als Schlüssel benutze, den anderen als Nachricht.
@CodeInChaos, gut, verwenden Sie alles, was für Sie funktioniert, wenn Sie sich in Ihren kryptografischen Fähigkeiten sicher genug sind, um Fehler abzuwenden. Persönlich würde ich diesen Ansatz anderen nicht empfehlen. (1) Dafür wurde HMAC nicht entwickelt. Wenn es also sicher ist, haben Sie "Glück". (2) Dies ist auf zwei Felder beschränkt. Wenn Sie drei Felder haben, müssen Sie etwas komplexeres tun. Dies könnte genauso gut von Anfang an eine angemessene Verteidigung verwenden, beispielsweise die Verwendung einer eindeutig decodierbaren Codierung (z. B. Voranstellen der Länge vor jedem zu verkettenden Feld).
Wie wäre es mit H (H (S) || H (T))? Da die Ausgabe von H () eine feste Länge hat, können Sie die Grenze nicht verschieben. Wenn Sie Hashes als Eingaben für die Verkettung verwenden, ist es außerdem sehr schwierig, eine Zeichenfolge auf einer Seite einer der Eingaben in einen gewünschten Wert umzuwandeln. Der einzige Nachteil, den ich sehe, ist, dass Sie jetzt 3 Hashes anstelle von einem machen. Aber andererseits sollten Hashes langsam sein, also ist es vielleicht doch keine schlechte Sache;)
@Marcin, yup, das ist ein weiterer vernünftiger Weg, dies zu tun. Ich habe Ihren Vorschlag zu meiner Antwort hinzugefügt. Danke für den Vorschlag! (Es kann einige sehr dunkle Fälle geben, in denen dies keine gute Lösung ist - z. B. wenn S ein Geheimnis ist, H (S) allgemein bekannt ist, T eine Herausforderung ist und der Zweck darin bestand, dass der Absender das Wissen über S nachweist indem ich einen Hash von S und T zurückschicke - aber ich werde mir keine Sorgen um diese sehr seltenen Sonderfälle machen.)
@Marcin "_hashes sollen langsam sein_" nein, sie sollen ** nicht ** langsam sein, und sie sind ** auch nicht ** langsam
Hier ist es erforderlich, die Grenze eindeutig zu kennen: Der Hash-Concatenate-Hash-Ansatz erfordert, dass Sie mindestens alle bis auf ein Element hashen - ein Element an einer bekannten Position kann nicht gehasht werden. Daher können Sie die Verwendung von H (S) vermeiden, wenn dies eine bekannte Größe für die Authentifizierung ist. Verwenden Sie stattdessen S, aber Hashing aller anderen Komponenten. Seien Sie trotzdem vorsichtig, da die zugrunde liegende Mathematik Sie unter Varianten der Verkettung und des erneuten Hashings beißen kann.
Ich bin ein Crypto-n00b, daher mag dies eine dumme Frage sein, aber wenn Sie versuchen, den Hash von zwei Zeichenfolgen "gebaut" und "sicher" zu erhalten, warum nicht den Hash H ("gebaut" || [somedelimiter "verwenden? ] || `sicher`)?
@Matt, yup, das kann funktionieren! Sie müssen jedoch alle Instanzen des Trennzeichens in diesen Zeichenfolgen umgehen (andernfalls gibt unweigerlich jemand eine Zeichenfolge ein, die das Trennzeichen enthält, und dann fällt dieser Ansatz auseinander). Dies erhöht die Komplexität, die in den Alternativen nicht vorhanden ist. Und wenn Sie dies anderen empfehlen, wird einer Ihrer Zuhörer unweigerlich vergessen, Begrenzern zu entkommen. Wenn sie vergessen, dem Trennzeichen zu entkommen, schlägt dieses Schema leise fehl: Es ist unsicher, aber sie werden es im normalen Betrieb wahrscheinlich nicht bemerken. Also ja, es funktioniert - aber es ist vielleicht nicht meine erste Wahl.
`H (json_encode (array (" builtin "," sicher ")))` könnte es tun. Und @penguat. Realex Payments verwendet bei der Verarbeitung von Kreditkarten einen Hash dieser Form: "H (H (verschiedene) | secret)".
Was ??? Diese Antwort macht keinen Sinn. Wenn die Daten nicht eindeutig sind, muss es keinen Angreifer geben. Alice weiß nicht, wie sie "eingebaut" interpretieren soll, weil Bob kein Leerzeichen eingefügt hat. Diese Mehrdeutigkeit ist kein vom Angreifer eingeführtes Problem, sondern liegt in der gewählten Datendarstellung. Wie können wir etwas verdauen, wenn wir nicht verketten können? Jede Nachricht, die länger als ein Bit ist, ist eine Verkettung.
@Kaz, Ihre Verwirrung wäre völlig gültig, wenn wir über die Formatierung der Eingabe für die Verschlüsselung sprechen würden (wobei der Empfänger entschlüsselt und dann versucht, den Klartext zu verstehen). Aber das ist hier nicht der Fall. Hier geht es darum, die Eingabe in eine Hash-Funktion zu formatieren. Hier gibt es kein Analogon zum Entschlüsseln; Der Empfänger nimmt niemals den Klartext und versucht dann, ihn zu analysieren. Stattdessen generiert der Empfänger denselben Klartext neu, hasht ihn und prüft, ob er mit dem vom Absender gesendeten Hash übereinstimmt. Daher scheint das Protokoll in Abwesenheit eines Angreifers einwandfrei zu funktionieren.
@D.W. Habe ich verschlüsseln gesagt? Ich wollte "Digest" schreiben. Dort behoben. Gut, dass s.e. Lassen Sie uns Kommentare Stunden nach dem Schreiben bearbeiten.
Okay, wir haben zwei Saiten "eingebaut" und "sicher". Wir setzen sie so zusammen, dass es keine "sicher gebaute" Grenze gibt. Wo die Spaltung liegt, ist in der Nachricht in keiner Weise vertreten. Keine Rahmenbits oder Bytes, keine Längenfelder, nichts. Und dann haben wir es. Und so "ändert der Angreifer jetzt die Grenze". Wie ändert der Angreifer das, was nicht da ist?
Und wenn ich zwei Bits zusammenstelle und sie hashe, verkette ich dann nicht Strings? Wir müssen also jedes Bit separat hashen, damit es identifiziert wird. Wir möchten nicht, dass Angreifer Grenzen zwischen Bits verschieben, sodass 00 1 plötzlich zu 0 11 wird.
@Kaz, hier ist ein Fall, den ich mehrmals gesehen habe: Der Absender sendet eine Nachricht mit zwei Teilen, "eingebaut" und "sicher". Die Nachricht ist Klartext, und in der Nachricht wird die Unterteilung explizit angegeben. Um seine Integrität zu schützen, hängt der Absender einen MAC oder Hash oder eine Signatur an die Verkettung der Nachrichtenteile an. Der Fehler: Ein Mann in der Mitte kann die eingebaute / sichere Nachricht in erstellt / unsicher ändern. Beide haben denselben Hash / dieselbe Signatur / denselben MAC, sodass der Empfänger ihn nicht erkennen kann. Lesen Sie die beiden Beispiele, auf die ich verweise (AWS und Flickr), um zu verstehen, wie dies detaillierter geschehen kann. Ja, es ist ein echter Fehler.
@DW Nun ja, da die Unterteilung in der Nachricht explizit ist, aber diese Bits nicht im Hash enthalten sind !!! Hash-Payload nicht und lassen Sie die Header- oder Metadaten weg. Hash die ganze Nachricht. Dies ist kein Verkettungsproblem. Was auch immer Sie von einem Hash ausschließen, wird dadurch nicht geschützt, unabhängig davon, was es ist. Längenfeld, das die Nutzlast in zwei Teile aufteilt, Zeitstempel oder irgendetwas anderes.
#4
+29
Alex Holst
2011-02-20 02:11:32 UTC
view on stackexchange narkive permalink

Nonces oder IVs nicht wiederverwenden

Viele Betriebsarten erfordern eine IV (Initialisierungsvektor). Sie dürfen denselben Wert niemals zweimal für eine IV wiederverwenden. Dies kann alle Sicherheitsgarantien aufheben und eine katastrophale Sicherheitsverletzung verursachen.

  • Für Stream-Chiffrier-Betriebsmodi wie den CTR-Modus oder den OFB-Modus ist die Wiederverwendung einer IV eine Sicherheitskatastrophe. Dies kann dazu führen, dass die verschlüsselten Nachrichten trivial wiederhergestellt werden können.

  • Bei anderen Betriebsmodi wie dem CBC-Modus kann die Wiederverwendung einer IV in einigen Fällen auch Angriffe zur Wiederherstellung von Klartext erleichtern

Unabhängig von der verwendeten Betriebsart sollten Sie die IV nicht wiederverwenden. Wenn Sie sich fragen, wie Sie es richtig machen sollen, finden Sie in der NIST-Spezifikation eine detaillierte Dokumentation zur ordnungsgemäßen Verwendung der Blockverschlüsselungsmodi.

Das Tarsnap-Projekt bietet ein gutes Beispiel dafür diese Falle. Tarsnap verschlüsselt Sicherungsdaten, indem es sie in Blöcke unterteilt und dann jeden Block mit AES im CTR-Modus verschlüsselt. In den Versionen 1.0.22 bis 1.0.27 von Tarsnap wurde dieselbe IV versehentlich wiederverwendet, um die Wiederherstellung von Klartext zu ermöglichen.

Wie ist das passiert? Um den Tarsnap-Code zu vereinfachen - und in der Hoffnung, das Fehlerpotential zu verringern - nutzte Colin Percival die Gelegenheit, den AES-CTR-Code in eine neue Datei (lib / crypto / crypto_aesctr.c im Tarsnap-Quellcode) umzuwandeln ) und modifizierte die vorhandenen Stellen, an denen AES-CTR verwendet wurde, um diese Routinen zu nutzen. Der neue Code sieht folgendermaßen aus:

 / * Verschlüsseln Sie die Daten. * / - aes_ctr (& encr_aes-> key, encr_aes-> nonce ++, buf, len, - filebuf + CRYPTO_FILE_HLEN); + if ((stream = + crypto_aesctr_init (& encr_aes-> key, encr_aes-> nonce)) == NULL) + goto err0; + crypto_aesctr_stream (stream, buf, filebuf + CRYPTO_FILE_HLEN, len); + crypto_aesctr_free (stream); 

Während des Refactorings wurde der encr_aes->nonce ++ versehentlich in encr_aes->nonce umgewandelt, und als Ergebnis wurde derselbe Nonce-Wert wiederholt verwendet . Insbesondere wird der CTR-Nonce-Wert nicht erhöht, nachdem jeder Block verschlüsselt wurde. (Der CTR-Zähler wird korrekt inkrementiert, nachdem jeweils 16 Datenbytes verarbeitet wurden. Dieser Zähler wird jedoch für jeden neuen Block auf Null zurückgesetzt.) Ausführliche Informationen werden von Colin Percival unter folgender Adresse beschrieben: http://www.daemonology.net /blog/2011-01-18-tarsnap-critical-security-bug.html

Versuchen Sie, diese Antwort auf diesen Effekt zu betiteln (+1), da sich das Problem um eine Nonce dreht. F: Ist ein Nonce normalerweise ++ oder sollte es zufällig sein?
@makerofthings, hängt vom Algorithmus ab. Einige Algorithmen und Betriebsmodi erfordern zufällige Nonces (z. B. CBC-Modus); andere erfordern nur, dass die Nonces verschieden sind, und daher reicht ein Zähler aus (z. B. CTR-Modus). Hoffentlich würde die Spezifikation für Algorithmus / Betriebsmodus beschreiben, was erforderlich ist.
Ich schlage vor, die Antwort so zu bearbeiten, dass sie auch IVs enthält. Die korrekte Verwendung von IV / Nonce sind sehr ähnliche Ideen.
Nonce ist einmal N. Ja, verwenden Sie die Variable N nur einmal. Singular. Wiederhole nicht. Die Stärke des zugehörigen Algorithmus wird durch Wiederholung von N beeinträchtigt.
Hier ist ein falsches Beispiel: WEP hat RC4 mit einer 24-Bit-Nonce implementiert, die nach jeder Nachricht zunimmt. Dies führte zu zwei Problemen: (1) Nachdem 2 ^ 24 Pakete gesendet wurden, wurden Nonces wiederverwendet. (2) RC4 war nicht dafür ausgelegt, Nonces "eng verwandt" zu haben, wobei bekannt ist, dass jede nachfolgende Verschlüsselung ++ der Wert der vorherigen war.
Hier ein richtiges Beispiel: Angenommen, ein Krypto-Designer möchte nicht denselben Schlüssel für mehrere Nachrichten wiederverwenden. Eine Lösung besteht darin, einen Schlüssel zu generieren und ihn mithilfe eines PRG zu erweitern. Verwenden Sie dann nur jedes Vielfache von "x" -Bits als Schlüssel. Wobei Segment 1 == Schlüssel 1, Segment 2 == Schlüssel 2.
#5
+29
D.W.
2011-02-20 10:06:23 UTC
view on stackexchange narkive permalink

Stellen Sie sicher, dass Sie Zufallszahlengeneratoren mit ausreichender Entropie setzen.

Stellen Sie sicher, dass Sie Pseudozufallszahlengeneratoren mit Kryptostärke verwenden, um beispielsweise Schlüssel zu generieren, IVs / Nonces usw. auszuwählen Verwenden Sie nicht rand () , random () , drand48 () usw.

Stellen Sie sicher, dass Sie Setzen Sie den Pseudozufallszahlengenerator mit genügend Entropie. Säe es nicht mit der Tageszeit; Das ist zu erraten.

Beispiele: srand (Zeit (NULL)) ist sehr schlecht. Ein guter Weg, um Ihr PRNG zu setzen, besteht darin, 128 Bits oder echte Zufallszahlen zu erfassen, z. B. aus / dev / urandom , CryptGenRandom oder ähnlichem. Verwenden Sie in Java SecureRandom und nicht Random. Verwenden Sie in .NET System.Security.Cryptography.RandomNumberGenerator, nicht System.Random. Verwenden Sie in Python random.SystemRandom, nicht random. Vielen Dank an Nate Lawson für einige Beispiele.

Beispiel aus der Praxis: Siehe diesen Fehler in früheren Versionen des Browsers von Netscape, der es einem Angreifer ermöglichte, SSL zu brechen.

Ich erinnere mich, dass ich Basic auf meinem Apple gelernt habe] [e. Ich habe ein Spiel geschrieben und brauchte eine zufällige Eingabe, also habe ich RND (1) verwendet. Ich musste immer wieder neu starten, um mein Spiel zu debuggen, und ich bemerkte, dass das zufällige Element nach dem Start immer in der gleichen Reihenfolge ablief. Damals lernte ich Pseudozufallszahlengeneratoren kennen. Wenn Sie zufällige Samen benötigen, bietet Random.org eine kostenlose Zufallszahlengenerierung basierend auf Umgebungsgeräuschen.
Random.org eignet sich am besten für Simulationen und andere nicht sicherheitsrelevante Zwecke. Random.org ist keine gute Basis für einen Startwert für ein kryptografisches PRNG, da Sie nicht darauf vertrauen können, dass es anderen unbekannt ist.
#6
+20
goodguys_activate
2011-02-20 01:34:06 UTC
view on stackexchange narkive permalink

Verwenden Sie keine Blockverschlüsselung mit EZB für die symmetrische Verschlüsselung.

(Gilt für AES, 3DES, ...)

Hier ist ein Beitrag und ein sehr ähnlicher Microsoft KB-Artikel darüber, wie der EZB-Modus zu Code führt, der nicht verschlüsselt ist.

Siehe auch diesen ähnlichen Beitrag von Rook

Nur Textnachricht:

alt text

Dieselbe Nachricht, die im EZB-Modus verschlüsselt ist (egal welche Verschlüsselung Sie verwenden): alt text

Die GENAUE gleiche Nachricht im CBC-Modus (auch hier spielt es keine Rolle, was Verschlüsselung, die Sie verwenden): alt text

Der falsche Weg

  public static string Encrypt (Zeichenfolge toEncrypt, Zeichenfolgenschlüssel, bool useHashing) { byte [] keyArray = UTF8Encoding.UTF8.GetBytes (Schlüssel); byte [] toEncryptArray = UTF8Encoding.UTF8.GetBytes (toEncrypt); if (useHashing) keyArray = new MD5CryptoServiceProvider (). ComputeHash (keyRider; ) {Key = keyArray, Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7}; ICryptoTransform cTransform = tdes.CreateEncryptor (); Byte [] resultArray = cTransform.TransformFinalBlock (toEncryptArray, 0, toEncryptBray.Tr; (resultArray, 0, resultArray.Length);}  

Der Fehler befindet sich in der folgenden Zeile

{Key = keyArray, Mode = CipherMode.ECB , Padding = PaddingMode.PKCS7};


Der richtige Weg

Die guten Leute von Microsoft haben mir den folgenden Code geschickt, um den oben verlinkten KB-Artikel zu korrigieren. Dies wird im Fall # 111021973179005

angegeben

Dieser Beispielcode verwendet AES zum Verschlüsseln von Daten, und der Schlüssel für die AES-Verschlüsselung ist der von SHA256 generierte Hashcode. AES ist der AES-Algorithmus (Advanced Encryption Standard). Der AES-Algorithmus basiert auf Permutationen und Substitutionen. Permutationen sind Umordnungen von Daten, und Substitutionen ersetzen eine Dateneinheit durch eine andere. AES führt Permutationen und Substitutionen mit verschiedenen Techniken durch. Weitere Informationen zu AES finden Sie im Artikel „Schützen Sie Ihre Daten mit dem neuen erweiterten Verschlüsselungsstandard“ im MSDN Magazine unter http://msdn.microsoft.com/en-us/magazine/cc164055.aspx.

SHA ist der sichere Hash-Algorithmus. SHA-2 (SHA-224, SHA-256, SHA-384, SHA-512) wird jetzt empfohlen. Weitere Informationen zu Hash-Werten in .NET Framework finden Sie unter http://msdn.microsoft.com/en-us/library/92f9ye3s.aspx#hash_values ​​.

Der Standardwert des Betriebsmodus des symmetrischen Algorithmus für AesCryptoServiceProvider ist CBC. CBC ist der Cipher Block Chaining-Modus. Es führt Feedback ein. Bevor jeder Klartextblock verschlüsselt wird, wird er durch eine bitweise exklusive ODER-Verknüpfung mit dem Chiffretext des vorherigen Blocks kombiniert. Dies stellt sicher, dass selbst wenn der Klartext viele identische Blöcke enthält, diese jeweils in einen anderen Chiffretextblock verschlüsselt werden. Der Initialisierungsvektor wird mit dem ersten Klartextblock durch eine bitweise ausschließliche ODER-Verknüpfung kombiniert, bevor der Block verschlüsselt wird. Wenn ein einzelnes Bit des Chiffretextblocks entstellt wird, wird auch der entsprechende Klartextblock entstellt. Außerdem wird ein Bit im nachfolgenden Block an derselben Position wie das ursprüngliche verstümmelte Bit entstellt. Weitere Informationen zu CipherMode finden Sie unter http://msdn.microsoft.com/en-us/library/system.security.cryptography.ciphermode.aspx.

Hier ist der Beispielcode.

  // Diese Funktion wird zum Verschlüsseln der Daten mit Schlüssel und iv verwendet.
Byte [] verschlüsseln (Byte [] Daten, Byte [] Schlüssel, Byte [] iv) {// Einen AESCryptoProvider erstellen. using (var aesCryptoProvider = new AesCryptoServiceProvider ()) {// Initialisiere den AESCryptoProvider mit Schlüssel und iv. aesCryptoProvider.KeySize = key.Length * 8; aesCryptoProvider.IV = iv; aesCryptoProvider.Key = key; // Verschlüsselung aus dem AESCryptoProvider erstellen. using (ICryptoTransform encryptor = aesCryptoProvider.CreateEncryptor ()) {// Speicherstrom zum Speichern der verschlüsselten Daten erstellen. using (MemoryStream stream = new MemoryStream ()) {// Erstellen Sie einen CryptoStream, um die Daten zu verschlüsseln. using (CryptoStream cryptoStream = neuer CryptoStream (Stream, Verschlüsseler, CryptoStreamMode.Write)) // Daten verschlüsseln. cryptoStream.Write (data, 0, data.Length); // die verschlüsselten Daten zurückgeben. return stream.ToArray (); }}}} // Diese Funktion wird zum Entschlüsseln der Daten mit Schlüssel und iv.byte [] verwendet. Entschlüsseln (Byte [] Daten, Byte [] Schlüssel, Byte [] iv) {// Erstellen Sie einen AESCryptoServiceProvider. using (var aesCryptoProvider = new AesCryptoServiceProvider ()) {// Initialisiere den AESCryptoServiceProvier mit key und iv. aesCryptoProvider.KeySize = key.Length * 8; aesCryptoProvider.IV = iv; aesCryptoProvider.Key = key; // Entschlüsseler aus dem AESCryptoServiceProvider erstellen. using (ICryptoTransform decryptor = aesCryptoProvider.CreateDecryptor ()) {// Erstellt einen Speicherstrom mit den verschlüsselten Daten. using (MemoryStream stream = neuer MemoryStream (Daten)) {// Erstellen Sie einen CryptoStream, um die verschlüsselten Daten zu entschlüsseln. using (CryptoStream cryptoStream = neuer CryptoStream (Stream, Entschlüsseler, CryptoStreamMode.Read)) {// Ein Byte-Puffer-Array erstellen.
Byte [] readData = neues Byte [1024]; int readDataCount = 0; // Erstellen Sie einen Speicherstrom zum Speichern der entschlüsselten Daten. using (MemoryStream resultStream = new MemoryStream ()) {do {// Daten entschlüsseln und in das readData-Pufferarray schreiben. readDataCount = cryptoStream.Read (readData, 0, readData.Length); // Schreibe die entschlüsselten Daten in resultStream. resultStream.Write (readData, 0, readDataCount); } // Überprüfen Sie, ob sich noch mehr verschlüsselte Daten im Stream befinden. while (readDataCount > 0); // Die entschlüsselten Daten zurückgeben. return resultStream.ToArray (); }}}}}} // Diese Funktion wird zum Generieren einer gültigen Schlüsselbinärdatei mit UTF8-Codierung und SHA256-Hash-Algorithmus verwendet. Byte [] GetKey (Zeichenfolgenschlüssel) {// SHA256-Hash-Algorithmusklasse erstellen. using (SHA256Managed sha256 = new SHA256Managed ()) // Dekodiere den String-Schlüssel in binär und berechne die Hash-Binärdatei des Schlüssels. return sha256.ComputeHash (Encoding.UTF8.GetBytes (Schlüssel));}  

Weitere Informationen zu den Klassen im Beispielcode finden Sie unter den folgenden Links:

· AesCryptoServiceProvider-Klasse

· SHA256Managed Class

· CryptoStream-Klasse

Darüber hinaus gibt es mehrere Artikel, die zum besseren Verständnis der Kryptografie in .NET Framework beitragen können. Weitere Informationen finden Sie unter den folgenden Links:

· Cryptographic Services

· .NET Framework-Kryptografiemodell

· Eine einfache Anleitung zur Kryptografie

· Verschlüsselung ohne Geheimnisse

Ich schlage vor, alles nach "Der richtige Weg" zu löschen. Der Vorschlag von Coda Hale weist eine Reihe von Schwächen auf. Es macht mehrere Fehler, die ich in anderen Antworten hier dokumentiert habe: Es verwendet Verschlüsselung ohne Nachrichtenauthentifizierung (ein schwerwiegender Fehler), es erstellt den Schlüssel als Hash eines Passworts (ein schwerwiegender Fehler), es unternimmt keinen Versuch, die umfassende Schlüsselsuche zu verlangsamen (Ein weiterer schwerwiegender Fehler). Meine Empfehlung für den richtigen Umgang damit ist im letzten Absatz meiner Antwort mit dem Titel "Rollen Sie nicht Ihre eigene Krypto" beschrieben.
Ich schlage vor, alle Inhalte nach "Haftungsausschluss" und "einigen Highlights" zu löschen. Ich denke, die meisten von ihnen sind für Ihren hochrangigen Standpunkt zur Vermeidung der EZB nicht relevant und lenken ab. Sei präzise. Stattdessen würde ich vorschlagen, dass Ihr Rat für den richtigen Weg lautet: Verwenden Sie einen sicheren Betriebsmodus, z. B. den CBC-Modus oder den CTR-Modus. Vergessen Sie nicht, die anderen Ratschläge auf dieser Seite zu befolgen, einschließlich der Verwendung der Nachrichtenauthentifizierung, der entsprechenden Generierung von Schlüsseln usw. Wenn Sie dies zu einem Community-Wiki machen möchten, würde ich diese Antwort gerne entsprechend bearbeiten.
@D.W. Ja, Sie können einige oder alle Antworten als CW bearbeiten. Mein Gedanke gegen die gesamte Frage CW ist, Anreize für Plakate zu schaffen, aber ich überlasse diese Entscheidung Ihnen, Leute. Ich möchte nur das Richtige lernen und die schlechten Praktiken verlernen
Beachten Sie, dass dieser Fehler in Java, das standardmäßig / ECB / PKCS5Padding verwendet (z. B. `Cipher.getInstance (" AES ")`), noch einfacher zu machen ist. Wenn Sie zu CBC wechseln, wird eine auf Null gesetzte IV verwendet (mehr oder weniger ein NONCE, siehe die Antwort dazu) standardmäßig auch.
Wie haben Sie das Bild so verschlüsselt?
@Matt, dieses Bild ist das Ergebnis eines erfolgreichen Angriffs. Angenommen, eine Datei mit dem Namen TUX.BMP versucht, sie anzuschauen, stellt jedoch fest, dass sie verschlüsselt ist. Anschließend zeigt er die verschlüsselten Bytes an und vermutet CBC, wenn er ein nicht zufälliges Muster sieht. Anschließend ersetzt er die ersten paar Blöcke durch einen bekanntermaßen guten BMP-Dateikopf und optimiert ihn, bis die Zeilen und Spalten ausgerichtet sind. Ich habe vor einigen Jahren in Blackhat gesehen, wie ein Forscher ein Werkzeug verwendet hat, um dies zu tun. Ich glaube, das Werkzeug hieß Rumint.
#7
+20
D.W.
2011-02-20 09:50:34 UTC
view on stackexchange narkive permalink

Verwenden Sie nicht denselben Schlüssel für die Verschlüsselung und Authentifizierung. Verwenden Sie nicht denselben Schlüssel für die Verschlüsselung und das Signieren.

Ein Schlüssel sollte nicht für mehrere Zwecke wiederverwendet werden. Dies kann verschiedene subtile Angriffe auslösen.

Wenn Sie beispielsweise ein RSA-Paar aus privatem und öffentlichem Schlüssel haben, sollten Sie es nicht beide zur Verschlüsselung verwenden (mit dem öffentlichen Schlüssel verschlüsseln, mit dem privaten Schlüssel entschlüsseln). und zum Signieren (mit dem privaten Schlüssel signieren, mit dem öffentlichen Schlüssel überprüfen): Wählen Sie einen einzelnen Zweck aus und verwenden Sie ihn nur für diesen einen Zweck. Wenn Sie beide Fähigkeiten benötigen, generieren Sie zwei Schlüsselpaare, eines zum Signieren und eines zum Ver- / Entschlüsseln.

Bei symmetrischer Kryptografie sollten Sie einen Schlüssel für die Verschlüsselung und einen separaten unabhängigen Schlüssel für die Nachrichtenauthentifizierung verwenden. Verwenden Sie nicht denselben Schlüssel für beide Zwecke.

Arbeitet s / MIME gegen diese Empfehlung? AFAIK Ich habe nur einen Schlüssel und kann signieren und verschlüsseln.
Meiner Meinung nach ist das größte Problem bei der Verwendung der gleichen Schlüssel für beide Verwendungszwecke das Problem der Strafverfolgung. In vielen Ländern können Sie jetzt aufgefordert werden, Ihre Verschlüsselungsschlüssel abzugeben, und das würde in der Praxis bedeuten, dass sie Ihren Namen unterschreiben können.
Ja, viele Algorithmen verwenden dasselbe Schlüsselpaar zum Signieren und Verschlüsseln, wobei PGP und S / MIME die offensichtlichen Beispiele sind. Es ist nicht unbedingt ein mathematisches Problem.
PGP verwendet ** nicht ** dasselbe Schlüsselpaar zum Signieren und Verschlüsseln. Ein privater PGP-Schlüssel besteht vielmehr aus einem Hauptschlüssel, der zum Signieren verwendet wird, und einem oder mehreren Unterschlüsseln, die zum Verschlüsseln verwendet werden. Die Unterschlüssel sind vor dem Benutzer verborgen, daher die Verwirrung, aber Sie können sie mit "gpg --list-secret-keys" anzeigen.
#8
+17
Chris Dale
2012-06-25 16:46:15 UTC
view on stackexchange narkive permalink

Kerckhoffs Prinzip: Ein Kryptosystem sollte sicher sein, auch wenn alles am System außer dem Schlüssel öffentlich bekannt ist.

Ein falsches Beispiel: LANMAN-Hashes stark>

Die LANMAN-Hashes wären schwer herauszufinden, wenn niemand den Algorithmus kennen würde. Sobald der Algorithmus jedoch bekannt war, ist es jetzt sehr trivial, ihn zu knacken.

Der Algorithmus lautet wie folgt ( aus Wikipedia):

  1. Das ASCII-Passwort des Benutzers wird in Großbuchstaben konvertiert.
  2. Dieses Kennwort wird auf 14 Byte null aufgefüllt.
  3. Das Kennwort mit fester Länge wird in zwei Hälften mit sieben Bytes aufgeteilt.
  4. Mit diesen Werten werden zwei DES-Schlüssel erstellt, einer von jeder 7-Byte-Hälfte
  5. Jeder der beiden Schlüssel wird zum DES-Verschlüsseln der konstanten ASCII-Zeichenfolge „KGS! @ # $%“ verwendet, was zu zwei 8-Byte-Chiffretextwerten führt.
  6. Diese beiden Chiffretextwerte werden zu einem 16-Byte-Wert verkettet, bei dem es sich um den LM-Hash handelt.
  7. ol>

    Da Sie jetzt den Chiffretext dieser Fakten kennen, können Sie dies jetzt sehr gut Teilen Sie den Chiffretext leicht in zwei Chiffretexte auf, von denen Sie wissen, dass sie in Großbuchstaben geschrieben sind, was zu einem begrenzten Satz von Zeichen führt, die das Kennwort möglicherweise sein könnte.

    Ein korrektes Beispiel: AES-Verschlüsselung

  • Bekannter Algorithmus
  • Skaliert mit Technologie. Erhöhen Sie die Schlüsselgröße, wenn Sie mehr kryptografischen Schwung benötigen
#9
+13
curiousguy
2011-09-28 09:03:50 UTC
view on stackexchange narkive permalink

In einem kryptografischen Protokoll: Machen Sie jede authentifizierte Nachricht erkennbar: Keine zwei Nachrichten sollten gleich aussehen.

Eine Verallgemeinerung / Variante von:

  • Seien Sie vorsichtig, wenn Sie mehrere Zeichenfolgen vor dem Hashing verketten.
  • Verwenden Sie Schlüssel nicht wieder.
  • Verwenden Sie Nonces nicht wieder.

Während eines Durchlauf des kryptografischen Protokolls Viele Nachrichten, die ohne ein Geheimnis (Schlüssel oder Nonce) nicht gefälscht werden können, können ausgetauscht werden. Diese Nachrichten können vom Empfangenen überprüft werden, weil er einen öffentlichen (Signatur-) Schlüssel kennt oder weil nur er und der Absender einen symmetrischen Schlüssel oder Nonce kennen. Dadurch wird sichergestellt, dass diese Nachrichten nicht geändert wurden.

Dies stellt jedoch nicht sicher, dass diese Nachrichten während des gleichen Protokolllaufs ausgegeben wurden: Möglicherweise hat ein Gegner sie erfasst diese Nachrichten zuvor oder während einer gleichzeitigen Ausführung des Protokolls. Ein Gegner kann viele gleichzeitige Läufe eines kryptografischen Protokolls starten, um gültige Nachrichten zu erfassen und unverändert wiederzuverwenden.

Durch geschickte Wiedergabe von Nachrichten kann möglicherweise ein Protokoll angegriffen werden, ohne einen Primärschlüssel zu gefährden, ohne ein RNG anzugreifen , jede Chiffre usw.

Indem jede authentifizierte Nachricht des Protokolls für den Empfänger offensichtlich eindeutig gemacht wird, werden die Möglichkeiten zur Wiedergabe nicht geänderter Nachrichten verringert (nicht beseitigt).

Tatsächlich muss eine Nonce kein Geheimnis sein, sondern nur einmal verwendet werden (innerhalb einer bestimmten Zeitspanne, z. B. der Gültigkeit des entsprechenden geheimen Schlüssels).
@PaŭloEbermann Viele Verwendungen einer Nonce erfordern keine Geheimhaltung, aber einige Protokollformalismen bezeichnen das zur Authentifizierung von Nachrichten verwendete * Geheimnis * eher als "Nonce" als als Schlüssel, da es nicht als Verschlüsselungsschlüssel verwendet wird.
#10
+13
D.W.
2011-02-20 11:39:43 UTC
view on stackexchange narkive permalink

Versuchen Sie, die Verwendung von Kennwörtern als Verschlüsselungsschlüssel zu vermeiden.

Eine häufige Schwachstelle in vielen Systemen ist die Verwendung eines Kennworts oder einer Passphrase oder eines Hashs eines Kennworts oder einer Passphrase als den Verschlüsselungs- / Entschlüsselungsschlüssel. Das Problem ist, dass dies sehr anfällig für Offline-Keysearch-Angriffe ist. Die meisten Benutzer wählen Passwörter, die nicht über ausreichende Entropie verfügen, um solchen Angriffen zu widerstehen.

Die beste Lösung besteht darin, einen wirklich zufälligen Verschlüsselungs- / Entschlüsselungsschlüssel zu verwenden, der nicht deterministisch aus einem Passwort / einer Passphrase generiert wird.

Wenn Sie jedoch eine basierend auf einem Kennwort / einer Passphrase verwenden müssen, verwenden Sie ein geeignetes Schema, um die umfassende Schlüsselsuche zu verlangsamen. Ich empfehle PBKDF2, das iteratives Hashing (in Anlehnung an H (H (H (.... H (Passwort) ...))) verwendet, um die Wörterbuchsuche zu verlangsamen. Stellen Sie sicher, dass ausreichend viele Iterationen verwendet werden, damit dieser Prozess beispielsweise 100 ms auf dem Computer des Benutzers dauert, um den Schlüssel zu generieren.

Als Anfänger gebe ich zu, dass ich das getan habe. Wenn der Schlüssel zufällig ist und daher nicht zu merken ist, empfehlen Sie, die Schlüssel irgendwo in physischer Form zu speichern? Nur so kann ich ein System mit rein zufälligen Schlüsseln implementieren.
@AdamCross, * "Wenn der Schlüssel zufällig ist und daher nicht zu merken ist, empfehlen Sie, Schlüssel irgendwo in physischer Form zu speichern?" * - Nun, irgendwo gespeichert, kann er entweder in elektronischer oder physischer Form gespeichert werden. Nicht elektronische Form muss nicht unbedingt in allen Situationen gegenüber elektronischer Form privilegiert sein. Um ein Beispiel zu geben ... Sie können SSL verwenden, um eine sichere Verbindung zu einer Website herzustellen. Der von Ihnen verwendete SSL-Sitzungsschlüssel wird nirgendwo in nicht elektronischer Form gespeichert und nicht aus einer Passphrase abgeleitet.
haha um zu verdeutlichen, mit "physischer Form" meine ich einen anderen Ort als meinen Kopf --- aber das ergab keinen Sinn, da mein Kopf auch physisch ist.
#11
+8
D.W.
2011-02-20 09:48:24 UTC
view on stackexchange narkive permalink

Verwenden Sie nicht denselben Schlüssel in beide Richtungen.

Bei der Netzwerkkommunikation besteht ein häufiger Fehler darin, denselben Schlüssel für die Kommunikation in A-> B-Richtung zu verwenden wie für die B-> A-Richtung. Dies ist eine schlechte Idee, da sie häufig Wiederholungsangriffe ermöglicht, bei denen etwas A, das an B gesendet wurde, an A zurückgespielt wird.

Der sicherste Ansatz besteht darin, zwei unabhängige Schlüssel auszuhandeln, einen für jede Richtung. Alternativ können Sie einen einzelnen Schlüssel K aushandeln und dann K1 = AES (K, 00..0) für eine Richtung und K2 = AES (K, 11..1) für die andere Richtung verwenden.

Oder Sie können einen SSC, einen sicheren Sitzungszähler, für jede Verschlüsselung erhöhen lassen (innerhalb der Halbduplex-Kommunikation). Ich habe sogar ein Beispiel gesehen, in dem der letzte Chiffretextblock der anderen Partei als IV für den nächsten Block verwendet wurde, aber das könnte zu einigen besonderen Angriffen führen.
@owlstead, Ja, die Verwendung des letzten Chiffretextblocks als IV für den nächsten Block zusammen mit dem CBC-Modus führte zum BEAST-Angriff auf SSL. P.S. Ein SSC könnte die beiden Kanäle trennen, aber Sie müssten vorsichtig damit sein. Sie müssten es sowohl für das Senden als auch für das Empfangen erhöhen (die Verwendung von zwei SSCs, einer für jede Richtung, würde den Zweck zunichte machen). Außerdem muss der SSC beide Seiten synchronisieren und toleriert keine Paketverluste, was in einigen Einstellungen problematisch sein kann. Es kann einfacher sein, nur zwei unabhängige Schlüssel zu verwenden.
Interessanterweise kenne ich einige Speicherkarten, die dieses Schema mit dem letzten Teil des Chiffrierblocks als IV für den nächsten verwenden. Ich werde es untersuchen. Danke D.W., ich schätze, meine Vermutung war richtig.
Dies öffnet auch die Tür für einen Zwei-Zeit-Pad-Angriff, der Microsoft PPTP-Bit. Die erste Version von PPTP verwendete denselben Schlüssel im Client und auf dem Server
#12
+8
D.W.
2011-02-20 09:44:44 UTC
view on stackexchange narkive permalink

Verwenden Sie keine unsicheren Schlüssellängen.

Stellen Sie sicher, dass Sie Algorithmen mit einem ausreichend langen Schlüssel verwenden.

Für die Kryptografie mit symmetrischen Schlüsseln ist I ' d empfehlen mindestens einen 80-Bit-Schlüssel, und wenn möglich, ist ein 128-Bit-Schlüssel eine gute Idee. Verwenden Sie keine 40-Bit-Krypto. Es ist unsicher und kann von Amateuren leicht zerstört werden, indem einfach jeder mögliche Schlüssel ausgiebig ausprobiert wird. Verwenden Sie kein 56-Bit-DES. Es ist nicht trivial zu brechen, aber es liegt in der Reichweite engagierter Angreifer, DES zu brechen. Ein 128-Bit-Algorithmus wie AES ist nicht wesentlich langsamer als 40-Bit-Krypto. Sie haben also keine Entschuldigung für die Verwendung von mieser Krypto.

Bei der Kryptografie mit öffentlichem Schlüssel hängen die Empfehlungen zur Schlüssellänge vom Algorithmus ab und das erforderliche Sicherheitsniveau. Das Erhöhen der Schlüsselgröße beeinträchtigt auch die Leistung, sodass ein massiver Overkill nicht wirtschaftlich ist. Dies erfordert daher etwas mehr Überlegungen als die Auswahl der Schlüsselgrößen für symmetrische Schlüssel. Für RSA, El Gamal oder Diffie-Hellman würde ich empfehlen, dass der Schlüssel mindestens 1024 Bit beträgt. 1024-Bit-Schlüssel befinden sich jedoch am Rande dessen, was in naher Zukunft knackbar werden könnte, und werden für den modernen Gebrauch im Allgemeinen nicht empfohlen. Wenn möglich, würde ich 1536- oder sogar 2048-Bit-Schlüssel empfehlen. Für die Kryptographie mit elliptischen Kurven erscheinen 160-Bit-Schlüssel angemessen, und 224-Bit-Schlüssel sind besser. Sie können sich auch auf veröffentlichte Richtlinien beziehen, die grobe Äquivalenzen zwischen symmetrischen und öffentlichen Schlüsselgrößen festlegen.

NIST empfiehlt Ende 2010 mehr als 1024-Bit-Schlüssel: http://securitymusings.com/article/1587/algorithm-and-key-length-deprecation
Einziger Satz, mit dem ich nicht einverstanden bin: "Dies ist heutzutage ein weniger häufiger Fehler" "... Immer noch einer der häufigsten Kryptofehler, die ich nach" Keine Verschlüsselung "und" Rolling your own crypto "sehe.
@AviD, @nealmcb, danke für das Feedback. Ich habe bearbeitet, um @AviD's Kommentar zu reflektieren. Beachten Sie, dass ich dies zu einem Community-Wiki gemacht habe. Sie können es also jederzeit bearbeiten, um die Empfehlungen zu verbessern und Fehler zu korrigieren.
#13
+3
Shane Hansen
2012-09-08 21:55:43 UTC
view on stackexchange narkive permalink

Verwenden Sie den richtigen Modus

Verlassen Sie sich aus Sicherheitsgründen nicht auf die Standardeinstellungen der Bibliothek. Insbesondere implementieren viele Bibliotheken, die AES implementieren, den in FIPS 197 beschriebenen Algorithmus, der als EZB-Modus (Electronic Code Book) bezeichnet wird. Dies ist im Wesentlichen eine einfache Abbildung von:

  AES (Klartext [32]) ] Byte, Schlüssel [32] Byte) -> Chiffretext [32] Byte  

ist sehr unsicher. Die Argumentation ist einfach, während die Anzahl der möglichen Schlüssel im Schlüsselraum ziemlich groß ist, ist das schwache Glied hier die Menge der Entropie in der Nachricht. Wie immer beschreibt xkcd.com besser als ich http://xkcd.com/257/

Es ist sehr wichtig, so etwas wie CBC (Cipher Block Chaining) zu verwenden, was im Grunde genommen der Fall ist macht Chiffretext [i] zu einer Zuordnung:

  Chiffretext [i] = SomeFunction (Chiffretext [i-1], Nachricht [i], Schlüssel)  

Um nur auf einige Sprachbibliotheken hinzuweisen, bei denen diese Art von Fehler leicht zu begehen ist: http://golang.org/pkg/crypto/aes/ bietet eine AES-Implementierung, die bei naiver Verwendung funktioniert Ergebnis im EZB-Modus.

Die Pycrypto-Bibliothek verwendet beim Erstellen eines neuen AES-Objekts standardmäßig den EZB-Modus.

OpenSSL macht dies richtig. Jeder AES-Aufruf bezieht sich explizit auf die Funktionsweise. Wirklich das Sicherste, was IMO ist, ist zu versuchen, keine Low-Level-Krypto wie diese selbst zu machen. Wenn Sie dazu gezwungen sind, gehen Sie so vor, als würden Sie (vorsichtig) auf Glasscherben gehen, und stellen Sie sicher, dass Ihre Benutzer berechtigt sind, Ihnen ihr Vertrauen zu schenken, um ihre Daten zu schützen.

Danke für diese Antwort, Shane! Eine Frage: Wird dies bereits durch die andere Antwort [Verwenden Sie keine Blockverschlüsselung mit EZB für die symmetrische Verschlüsselung] (http://security.stackexchange.com/a/2203/971) abgedeckt?
#14
+3
D.W.
2012-10-17 19:57:20 UTC
view on stackexchange narkive permalink

Verwenden Sie denselben Schlüssel nicht auf vielen Geräten erneut.

Je häufiger Sie einen kryptografischen Schlüssel gemeinsam nutzen, desto weniger wahrscheinlich ist es, dass Sie ihn behalten können Geheimnis. Einige bereitgestellte Systeme haben auf jedem Gerät im System denselben symmetrischen Schlüssel wiederverwendet. Das Problem dabei ist, dass früher oder später jemand den Schlüssel von einem einzelnen Gerät extrahiert und dann alle anderen Geräte angreifen kann. Tun Sie das also nicht.

Siehe auch "Symmetrische Verschlüsselung nicht # 6: Teilen Sie keinen einzelnen Schlüssel für viele Geräte" in diesem Blog-Artikel. Dank an Matthew Green.

#15
+3
John Deters
2013-05-15 22:04:48 UTC
view on stackexchange narkive permalink

Ein einmaliges Pad ist kein einmaliges Pad, wenn der Schlüssel durch einen Algorithmus gedehnt wird.

Die Kennung "einmaliges Pad" (auch als Vernam-Chiffre bezeichnet) wird häufig falsch angewendet verschiedene kryptografische Lösungen, um unzerbrechliche Sicherheit zu beanspruchen. Aber per Definition ist eine Vernam-Chiffre genau dann sicher, wenn alle drei dieser Bedingungen erfüllt sind:

  • Das Schlüsselmaterial ist wirklich unvorhersehbar; UND
  • Das Schlüsselmaterial hat die gleiche Länge wie der Klartext. UND
  • Das Schlüsselmaterial wird niemals wiederverwendet.

Jeder Verstoß gegen diese Bedingungen bedeutet, dass es sich nicht mehr um eine einmalige Pad-Verschlüsselung handelt.

Der häufigste Fehler besteht darin, dass ein kurzer Schlüssel mit einem Algorithmus gestreckt wird. Diese Aktion verstößt gegen die Unvorhersehbarkeitsregel (unabhängig von der Schlüssellängenregel). Sobald dies erledigt ist, wird das einmalige Pad mathematisch in den Algorithmus zum Strecken der Schlüssel umgewandelt. Das Kombinieren des Kurzschlüssels mit zufälligen Bytes ändert nur den Suchraum, der erforderlich ist, um den Algorithmus zum Strecken der Schlüssel brutal zu erzwingen. In ähnlicher Weise verwandelt die Verwendung von "zufällig generierten" Bytes den Zufallszahlengeneratoralgorithmus in einen Sicherheitsalgorithmus.

Hier ist ein einfaches Beispiel. Ich habe eine Nachricht, dass ich mit einem "One-Time-Pad" verschlüsseln werde, das eine kryptografisch sichere Funktion als Schlüsselgenerator verwendet. Ich habe einen geheimen Schlüssel ausgewählt und ihm dann eine Zufallszahl hinzugefügt, um sicherzustellen, dass er nicht wiederverwendet wird. Da ich den Schlüssel nicht wiederverwende, gibt es keine Möglichkeit, den Chiffretext durch Subtrahieren einer Nachricht von einer anderen anzugreifen.

  Klartext: 1234567890123456789012345678901234567890 Schlüsselmaterial: 757578fbf23ffa4d748e0800dd7c424a46feb0ccOTP ------ Chiffretext: 67412E83622DCE1B0C1E1A348B04D25872A8C85C  

Das Schlüsselmaterial wurde sicher mit SHA-1 generiert, um mein geheimes Passwort (plus zufällig) zu hashen, um es zu erweitern. Jeder Angreifer, der den verwendeten Stretching-Algorithmus * kennt, ist SHA-1. Er kann ihn angreifen, indem er verschiedene Eingaben in SHA-1 versucht und die Ausgabe mit dem Chiffretext XOR-verknüpft. Das Erraten des "OTP" -Schlüssels ist jetzt nicht schwieriger als das Erraten der kombinierten Eingaben in den kryptografischen Algorithmus. Diese Eigenschaft gilt unabhängig davon, welcher kryptografische Basisalgorithmus ausgewählt wurde, welche Komplexitätsmaße er enthält oder wie er implementiert oder festgelegt wird.

Möglicherweise verfügen Sie über einen sehr guten Algorithmus zum Strecken von Schlüsseln. Möglicherweise haben Sie auch einen sehr sicheren Zufallszahlengenerator. Ihr Algorithmus ist jedoch per Definition kein einmaliges Pad und hat daher nicht die unzerbrechliche Eigenschaft eines einmaligen Pads.

* Die Anwendung des Kerckhoff-Prinzips bedeutet, dass Sie davon ausgehen müssen, dass der Angreifer immer bestimmen kann die verwendeten Algorithmen.

Würden Sie "Da ich den Schlüssel nicht wiederverwenden werde, gibt es keine Möglichkeit, den Chiffretext durch Subtrahieren einer Nachricht von einer anderen anzugreifen" bearbeiten und Text hinzufügen, der besagt, dass andere Angriffe möglich sind? BEISPIEL: ein Zwei-Zeit-Pad, ein schlechtes Protokoll oder eine andere Vorspannung (PPTP, WEP bzw. RC4). Ein unerkannter Laie kann falsch lesen, was Sie geschrieben haben, und denken, dass OTP "perfekte Geheimhaltung" in einem anderen Sinne des Wortes bietet. Da Sie dieses Thema ansprechen, ist es hilfreich, zu erläutern, was eine gültige PNG / PRG-Schlüsselbahre ist.
Hinweis: In einem OTP gibt es keine Nachrichtenauthentifizierung. Änderungen an einem OTP werden nicht erkannt.
Hinweis: Ein * sicheres PRG * ähnelt einem OTP. Es ist eines, das alle effizienten statistischen Tests mit einem vernachlässigbaren Ergebnis hat und dass es für eine PRG unmöglich ist, jeden theoretischen statistischen Test zu erfüllen. Diese "Lockerung" der Sicherheit ist für die Effizienz erforderlich, da "Perfect Secrecy" eine sichere Übertragung eines OTP erfordert, das groß genug ist, um der Größe der Nachricht zu entsprechen. BEISPIEL: Alle OTP-Übertragungen erfordern, dass das Geheimnis sicher übertragen wird (was undefiniert ist, wie). Es ist effizienter, diese sichere Methode zu verwenden, um die Daten überhaupt zu senden.
Es ist die "Ähnlichkeit", die die Menschen dazu bringt, die ausgefallenen Behauptungen der Unzerbrechlichkeit aufzustellen, und es ist diese "Effizienz", die die Unvorhersehbarkeit der Vernam-Chiffre bricht. Niemand sagte, dass die Schlüsselgenerierung, Schlüsselverwaltung oder Schlüsselverteilung mit einem OTP einfach oder praktisch ist - es ist keine der oben genannten. Es ist so schwer, dass die Leute trotz des Versprechens einer mathematisch perfekten Geheimhaltung immer noch andere Chiffren verwenden. Kein "Key Stretching" kann diese Wahrheit ändern.
Ein "sicheres PRNG" könnte verwendet werden, um die Bits zu generieren, aber wenn es wirklich sicher ist, haben Sie immer noch alle Verteilungsprobleme, da Sie ihre Generierung nicht auf dem Computer des Empfängers duplizieren können - wenn Sie könnten, wäre dieser Status der Schlüssel, nicht der Bits.
#16
+1
Watson Ladd
2012-09-08 21:05:27 UTC
view on stackexchange narkive permalink

Vertrauen Sie Standards nicht.

In der Kryptografie gibt es viele Standards, und manchmal müssen Sie sie verwenden. Aber nehmen Sie nicht an, dass die Leute, die die Standards schreiben, die Kryptographie, die sie brauchten, angemessen verstanden haben. Zum Beispiel wurde EAX in einem Netzwerkstandard überarbeitet. EAX hat einen Sicherheitsnachweis. Die überarbeitete Version hat dies nicht getan.

MD5 ist ein Standard. Es ist jetzt kaputt. Chip und PIN wurden dank einer Vielzahl gefährlicher Funktionen wiederholt gebrochen. GPG unterstützt weiterhin DSA-Schlüssel, die für Komfort zu kurz sind. SSL verfügt über Optionen, die nicht verwendet werden sollten, und erfordert Sorgfalt, um sie zu vermeiden.

Was kann dagegen getan werden? Seien Sie vorsichtig, verstehen Sie die bekannten Risiken und halten Sie sich an die Erforschung neuer Risiken.

MD5 ist ein Standard, stimmt. Es wurde jedoch durch einen aktuelleren Standard, SHA, ersetzt. In den meisten Szenarien sollten Standards aus vielen Gründen befolgt werden. Interoperabilität ist ein sehr großer Faktor.
Dies ist eine sehr irreführende Aussage. Der Wortlaut impliziert, dass der Leser "NON-Standards vertrauen" sollte, was eindeutig nicht wahr ist. Die meisten Sicherheitsstandards entstehen erst nach umfangreichen Feldtests in der Praxis. Diese Tests sind weitaus gründlicher, als jede einzelne Organisation generieren kann, um zu beweisen, dass ihr nicht standardmäßiges System sicher ist.
#17
+1
goodguys_activate
2013-05-20 20:47:19 UTC
view on stackexchange narkive permalink

Verwenden Sie bei der Festplattenverschlüsselung kein OTP oder keine Stream-Verschlüsselung.

Beispiel 1

Angenommen, zwei Dateien werden gespeichert Verwenden einer Stream-Verschlüsselung / OTP. Wenn die Datei nach einer geringfügigen Bearbeitung erneut gespeichert wird, kann ein Angreifer feststellen, dass nur bestimmte Bits geändert wurden, und auf Informationen zum Dokument schließen. (Stellen Sie sich vor, Sie ändern die Anrede "Lieber Bob" in "Liebe Alice".)

Beispiel 2

Die Ausgabe enthält keine Integrität: Ein Angreifer kann Ändern Sie den Chiffretext und den Inhalt der Daten, indem Sie die Daten einfach XOR-verknüpfen.

zum Mitnehmen: Änderungen am Chiffretext werden nicht erkannt und haben vorhersehbare Auswirkungen auf den Klartext.

Lösung

Verwenden Sie für diese Situationen eine Blockverschlüsselung, die die Überprüfung der Nachrichtenintegrität umfasst.

#18
  0
goodguys_activate
2013-05-20 21:08:44 UTC
view on stackexchange narkive permalink

Verwenden Sie ein One Time Pad (OTP) oder einen Stream-Verschlüsselungsschlüssel niemals mehr als einmal.

Ein zweimal angewendetes OTP bedeutet, dass die mit "perfekter Geheimhaltung" verschlüsselten Daten entschlüsselt werden im klaren. Dies geschieht, weil die Daten zweimal XOR'ed werden.

Beispiel

Angenommen, ein OTP / oder Stream mit demselben Schlüssel wird wiederverwendet.

Ein Angreifer sammelt viele Daten von einem Client an einen Server gesendet, und XORs eine Menge von zwei Paketen zusammen, bis die beiden Pakete sich gegenseitig entschlüsseln (oder eine Teilmenge darin).

Die ASCII-Codierung weist eine ausreichende Redundanz auf, was bedeutet, dass bei ausreichendem Chiffretext die ursprünglichen Nachrichten (zusammen mit dem geheimen OTP-Schlüssel) decodiert werden können.

Beispiele aus der realen Welt

  • Projekt Verona (1941-46) für ein Beispiel eines OTP, das von den Russen verwendet wurde und anschließend verwendet wurde Entschlüsselt vom US-Geheimdienst

  • Microsoft PPTPv1 verschlüsselt sowohl den Client als auch den Server Daten mit demselben Schlüssel.

  • WEP wird wiederverwendet der gleiche Schlüssel, sobald 2 ^ 24 Pakete gesendet wurden oder wenn eine NIC-Karte zurückgesetzt wurde. Das erste Problem ist darauf zurückzuführen, dass die IV 24 Bit lang ist, was dazu führt, dass nach der Übertragung von 16 Millionen Frames ein Zwei-Zeit-Pad erstellt wird. Das zweite Problem tritt bei Hardware-Implementierungen auf, bei denen die IV nach einem Aus- und Einschalten auf Null zurückgesetzt wird, was zu einem Zwei-Zeit-Pad führt. Dieses Problem ist leicht zu erkennen, da die IV im Klartext gesendet wird.

Empfehlungen

  • Für jede Sitzung sollte ein neuer Schlüssel erstellt werden (z. B. TLS).

  • Der Client sollte ein OTP (oder eine Stream-Verschlüsselung mit PRG) mit dem Server und dem Server verwenden sollte beim Verschlüsseln von Daten mit dem Client einen anderen Schlüssel verwenden

  • Anstatt viele, viele Schlüssel zu generieren, ist es möglich, einen einzelnen Schlüssel zu einem langen Stream zu erweitern Verwenden Sie eine PRG (vorausgesetzt, Sie vertrauen der PRG) und verwenden Sie jedes Segment dieser Erweiterung als Schlüssel.

  • Beachten Sie, dass nicht alle PRGs im Inkrementierungsmodus ausgeführt werden und möglicherweise zufällige Eingaben erforderlich sind. (RC4 hat dieses Problem im Inkrement-Modus)

#19
  0
goodguys_activate
2013-05-20 21:26:00 UTC
view on stackexchange narkive permalink

RC4 nicht verwenden

RC4 wurde 1987 für die Verwendung als Stream-Chiffre entwickelt. Es wird in HTTPS und WEP verwendet.

Es gibt Schwächen

  1. Die anfängliche Ausgabe weist eine Verzerrung auf: Pr [2. Byte = 0] = 2/256
  2. Die Wahrscheinlichkeit, dass 16 Bits gleich Null sind, beträgt 1/256 ^ 2 + 1/256 ^ 3. Dies tritt auf, nachdem mehrere Gigs von Daten verschlüsselt wurden.
  3. Anfällig für verwandte Schlüsselangriffe, bei denen sich nur die IV ändert, der Schlüssel jedoch gleich bleibt.
  4. ol>

    Take away Wenn Sie RC4 verwenden müssen, ignorieren Sie die ersten 256 Bytes, da diese voreingenommen sind. Wenn Sie RC4 für Datenauftritte verwenden, ermöglicht die Verzerrung in RC4 Angriffe auf alle zuvor verschlüsselten Daten.

#20
  0
goodguys_activate
2013-05-20 21:49:46 UTC
view on stackexchange narkive permalink

Verwenden Sie moderne Stream-Prozessoren, die in Hardware oder Software ordnungsgemäß funktionieren.

Nicht alle Stream-Chiffren sind für die Implementierung in Hardware oder Software ausgelegt. LFSR (Linear Feedback Shift Register) ist ein Beispiel für eine weit verbreitete Hardware-Verschlüsselung, die leicht beschädigt werden kann.

LFSR wird verwendet in:

  • DVD-Verschlüsselung (auch als CSS bezeichnet) 2 LFSR
  • GSM-Verschlüsselung (A5 / 1.2) 3 LSFR
  • Bluetooth (E0): 4 LFSR

Die Hardware für die oben genannten Zwecke ist weit verbreitet und daher schwer zu aktualisieren oder auf den neuesten Stand zu bringen. Alle oben genannten Punkte sind stark beschädigt und sollten für eine sichere Kommunikation nicht als vertrauenswürdig eingestuft werden.

Angriff:

Da der Schlüssel während der Verschlüsselung in zwei Abschnitte unterteilt wird ( 17 Bit und 25 Bit) und diese Bits werden verwendet, um denselben Chiffretext zu verschlüsseln. Es ist möglich, Kenntnisse des MPEG-Formats zu verwenden und einen 17-Bit-Schlüssel zu erzwingen, um den 25-Bit-Schlüssel zu extrapolieren.

Dies ist Kaum neu, aber FOSS ist leicht zu finden, was dieses Problem demonstriert.

Lösung:

Das eStream-Projekt (2008) ) qualifizierte 5 Stream-Chiffren, die verwendet werden sollten. Ein bemerkenswerter Unterschied besteht darin, dass die Chiffren anstelle eines Schlüssels mit einer IV einen Schlüssel, eine Nonce und einen Zähler verwenden. Salsa20 funktioniert auf diese Weise und ist so konzipiert, dass es sowohl in Hardware als auch in Software problemlos verwendet werden kann. Insbesondere ist es im x86 SSE2-Befehlssatz enthalten.

Neben

Die modernen Chiffren sind nicht nur sicherer, sondern auch schneller:

  PRG-Geschwindigkeit (MB / s) RC4 126 (veraltet) Salsa20 / 12 643 (modern) Sosemaunk 727 (modern)  
#21
  0
goodguys_activate
2013-05-23 09:42:28 UTC
view on stackexchange narkive permalink

Verwenden Sie nur MACs, die nicht für Angriffe auf Nachrichtenerweiterungen anfällig sind.

Ein MAC ist ein Hash-Code, der die Nachrichtenintegrität (keine Änderungen usw.) einer bestimmten Ebene sicherstellt Text. Viele Implementierungen und veröffentlichte Standards schützen einen MAC nicht vor einem Angreifer, der zusätzliche Daten an den MAC anfügt.

Die Lösung hierfür besteht darin, dass die MAC-Implementierung einen zweiten (anderen) Schlüssel verwendet und die endgültige Ausgabe neu verschlüsselt.

ECBC und NMAC sind Beispiele für Chiffren, die das korrekt verhindern Nachrichtenerweiterungsangriff.

Lösung:

  • Verwenden Sie Encrypted CBC (ECBC) anstelle von raw CBC
  • Verwenden Sie NMAC anstelle von cascade


Diese Fragen und Antworten wurden automatisch aus der englischen Sprache übersetzt.Der ursprüngliche Inhalt ist auf stackexchange verfügbar. Wir danken ihm für die cc by-sa 2.0-Lizenz, unter der er vertrieben wird.
Loading...