Einzelnen Beitrag anzeigen

Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#4

Re: Text verschlüsseln mit BlowFish und SHA1

  Alt 11. Dez 2003, 12:14
Zitat:
1. Byte- oder BlockChiper ...
Definitionirrtum von mir, ich dachte ByteChiper sind die,
die mit Buffer=1Byte arbeiten. Hier geht’s aber mehr um
den Ciphermode.
Eigentlich genau das Gegenteil. StreamCipher versus BlockCipher unterscheiden sich nicht darin ob sie Byteweise oder so verschlüsseln, denn dies lässt sich auch mit einem CipherMode so regeln das beide Klassen identisch arbeiten. Der wichtige Unterschied besteht im internen Aufbau des Verschlüsselungsalgorithmus an sich. Angenommen wir haben einen 1 Byte StreamCipher und einen 1 Byte BlockCipher. Werden nun 2 Bytes verschlüselt, also Byte A und B einer Nachricht, dann wäre beim StreamCipher das Byte B immer abhänig vom Byte A. Bei einem BlockCipher im ECB Mode, also plain, ist Byte B niemals abhänig vom Byte A, da es ja ein anderer 1 Byte Block ist.

D.h. Bei StreamCiphern ist die Nachricht wie ein Strom von Informationen, die immer Byteweise abhänig voneinander verschlüsselt werden. Die Verschlüsselungsfunktion besteht darin das der StreamCipher selber einen Schlüsselstrom erzeugt und diesen mit dem Datenstrom verküpft, z.B. XOR. Der Streamcipher Algorithmus arbeitet also NIEMALS direkt mit dem eigentlichen Datenstrom. Beim Knacken versucht man also den Schlüsselstrom des Streamciphers zu finden.

Ein Blockcipher zerhackt den Datenstrom in Blöcke, und benutzt nun seinen Algorithmus um jeden Block für sich gesehen, zu verschlüsseln. D.h. ein Blockcipher arbeitet direkt mit dem Datenstrom. Somit ist die Verschlüsselung jedes einzelnen Blockes eines Datenstromes unabhänig von den anderen Blöcken. (im ECB Mode)

Während bei einem StreamCipher der gleiche Schlüsselstrom-Algorithmus zur Verschlüsselung und Entschlüsselung benutzt wird, werden beim Blockcipher zwei unterschiedliche Algorithmen benötigt. Ein Algorithmus zur Verschlüsselung und ein inverses Gegenteil zur Entschlüsslung. Das Passwort des Benutzers stellt nun sicher das beide Algorithmen mit den korrekten Daten auch korrekt funktionieren. D.h. das Passwort ist ein Schlüssel der die beiden unterschiedlichen Algortihmen des BlockCiphers synchronisiert, so daß der Entschlüsselungs-Algo das entschlüsseln kann was sein Gegenpart der Verschlüsselungsalgo. verschlüsselt hat.

So, ich hoffe diese vereinfachte Darstellung macht nun den Hauptunterschied zwischen Stromverschlüsselungen und Blockverschlüsselungen deutlich. Man dürfte sehr einfach ableiten können was dies für die Sicherheit, eg. Stärke des Algos. zu bedeuten hat.


Zitat:
2. Delphirandom
diesbezüglich brauche ich mir keine weiteren Sorgen (unsicher und so) machen?
Korrekt, wir nutzen ja SKey = SHA1(Salt, Key), und verhindern so das schlechter Zufall eine Bedeutung für SKey hat. Ein Angreifer kann nicht auf SKey ohne das korrekte Passwort kommen, und er kann den Prozess der Berechnung von SKey nicht umkehren. Um also einen schlechten Zufall sicher zu machen wird ein schlechter Zufall in Salt erzeugt, dann noch ein unverhersehbaren Schlüssel in Key erzeugt und per SHA1(Salt, Key) miteinander verküpft. Schon hat man einen YARROW PRNG. Der Key sollte zB. dann aus den Mausbewegungen eines Menschen bestehen.

Da wir aber SKey in C am Anfang einbetten, und der Cipher einen Feedback Modus benutzt, wird sogar noch die Verschlüsslung gestärkt. Betrachtet man in diesem Falle SKey als sicheren Zufallswert, so wird dadurch die Nachricht zufällig gemacht. Aus Sicht des Ciphers wird also eine "Zufallsnachricht" verschlüsselt. Ein Angreifer hat also keinerlei Angriffstellen mit bekannten Informationen um diese auszunutzen. Wichtig dabei ist aber das man SKey nicht ohne ein Geheimniss reproduzieren kann. Wäre SKey in C nur ein Zufallssalt durch Delphis Random() erzeugt, so wäre es wieder unsicher.

Zitat:
Ich habe versucht das "Besprochene" Testweise (mit DEC) nachzubauen....
In deiner Entschlüsselung rufst du 2 mal .DecodeBuffer() auf. WICHTIG dabei ist es das dann der zu dekodierende Buffer exakt eine Länge hat die ein mehrfaches von Cipher.Blocksize ist. Da Blowfish 8 Bytes Blocksize hat und SKey 20 bytes lang ist, muß man also im 1. Aufruf von .DecodeBuffer() exakt 24 Bytes entschlüsseln. Man entschlüsselt also schon 4 Bytes von der eigentlichen Nachricht mit.
Der nachfoldende Aufruf von .DecodeBuffer() entschlüsselt dann den Rest der Nachricht. Die konplette Nachricht wird dann zusammengesetzt aus den 4 Bytes + dem Rest.

Wird dies nicht beachtet so schlägt sofort das autom. Padding = Cipher Text Stealing des Feedback Modus (CBC, CTS usw.) zu. Dieses "Padding" ist nicht-reversibel. D.h. hat der Ciphermode einmal dieses Padding durchgeführt ist der interne Status des Cipher verändert worden. Exakt diese Eigenschaft des Ciphermodes ist dir zum Verhängnis geworden. Zur Verschlüsselnungsphase hast du die komplette Nachricht nur einemal "ge-padded" am Schluß, und zur Entschlüsselungsphase aber zweimal -> einmal beim entschlüsseln der 20 Bytes von SKey und dann man Schluß der restlichen Nachricht.
Deshalb bist du auf die Idee gekommen die 20 Bytes von SKey um 4 Bytes zu verlängern. Denn nun ist die Blockgröße wieder synchronisiert zum Ciphermode. Allerdings funktioniert dies dann aber nur mit Ciphern die zB. 1,2,4,8 Bytes Blockgröße haben. Ein 16 Bytes BlockCipher würde wiederum Schwierigkeiten machen. Deshalb ist es besser einfach x Blöcke der kompletten Nachricht am Anfang zu entschlüsseln. X sollte so groß sein das damit mehr als 20 Bytes entschlüsslt werden. Z.b. ein 16 Bytes Blockcipher entschlüsselt 2 Blöcke = 32 Bytes. Davon sind 20 Bytes = SKey und 12 Bytes von der Nachricht. Diese 12 bytes werden dann in den Zielstream gespeichert.
Es gibt Ciphermodis die dies umgehen können, zb. Bruce Schneiers CFB64 Modus. Intern arbeitt dieser Modus immer auf der Blockgröße des Ciphers. Im Falle von Blowfish also 8Bytes = 64 Bit, deshalb CFB64. Im Falle eines 16 Bytes Blockciphers würde dieser Modus dann CFB128 heissen. Wichtig ist aber nur das dieser Modus unabhänig ist von der Nachrichtenlänge funktioniert. Man kann also den Cipher in mehreren Gängen zB, jeweils mit 2 Bytes, dann 5 Bytes dann 12 bytes füttern, ohne das beim nachfolgendem entschlüsseln mit anderen Datenentnahmegrößen es zu Problemen kommt.


Gruß Hagen
  Mit Zitat antworten Zitat