Einzelnen Beitrag anzeigen

Benutzerbild von negaH
negaH

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

Re: Dateien verschlüsseln - aber wie?

  Alt 2. Okt 2003, 08:45
Zitat:
So weit so gut, es gibt ja die Aktionen paEncode (zum Verschlüsseln), paDecode (entschlüsseln) und dann noch paWipe. Über die Funktion des Letzten bin ich mir nicht im Klaren. Wiped das die Quelldatei oder was?
Jetzt dringen wir tiefer in die DEC Klassen ein, und man erkennt viele Sünden die ich heute nicht mehr so designen würde. TCipher/THash und TRandom sind alle von der gleichen Klasse TProtection abgeleitet. Jede Klasse wie TCipher/THash/TRandom implementieren ihre EIGENEN Methoden die natürlich Algorithmen spezifisch sind. D.h. ein TCipher hat die Methoden .En-/DecodeBuffer, .En-/DecodeString() usw. zum Ver- und Entschlüsseln. Ein THash wiederum seine .CalcXYZ usw Methoden. Diese Methoden unterstützen KEINE ProgressCallback.

Aber in TProtection gibt es ebenfalls ähnliche Methoden, die für ALLE von TProtection abgeleiteten Klassen gültig sind, Zb. TProtection .CodeStream(). Man kann also mit einem Cipher/Hash/Random ebenfalls über diese Methoden von TProtection Daten verschlüsseln. Kryptographisch gesehen würde ich aus heutiger Sicht meine damaligen Absichten als naiv bezeichnen, und nicht mehr auf die TProtection Methoden zurückgreifen. Man kann zwar tatsächlich auch mit einer Hash-Funktion eine Verschlüsselung machen, man nennt diese offiziell MDC=Message Digest Cipher, heutzutage würde ich aber grundsätzliche solche Verfahren ablehnen. Nungut, DEC enthält sie und somit muß ich auch darauf eingehen. Nur die Methoden von TProtection enthalten die Möglichkeit eine Progress-Callback zu benutzen. Hier im Forum findest du in der Codelibrary einen TProgressStreamAdapter der diese Progressfunktionalität viel eleganter lösst. Die im DEC enthaltene Callback ist global und nicht threadsafe und funktioniert nur mit den TProtection.CodeXXXX Methoden. Also wiederum einige Nachteile. Um denoch einen Progress zu coden schauste mal in DECUtil.pas rein, dort findest du eine globale Variable "Progress: TProgressEvent". Diese musst du vor der Benutzung von TProtection.CodeXXXX() auf eine eigene Eventmethode setzen und danach wieder auf nil. Genauso gehen auch die Manager Components vor.

Zitat:
Gibt es eigentlich eine Funktion zum Wipen von Dateien, sodass ich die Option "Quelldatei nach Verschlüsseln wipen" einbauen kann?
Jo, eben paWipe Du erzeugt einen TCipher oder TRandom und benutzt dann die Methoden von TProtection mit der Action paWipe statt paEncode.

Zitat:
Und: Der CipherManager verfügt über ein OnProgress Event. Wie kann ich darauf zugreifen, wenn ich den Manager nicht verwende (was bei mir der Fall ist)?
Ähm, oben schon beantwortet.

@Luckie:
Zitat:
Eine Frage noch: Das Passwort wird im Header logischerweise nur als Hash-Wert gespeichert oder?
Es sollte überhaupt nicht mehr gespeichert werden, egal in welcher Form. Ansonsten sind bei bekannter Hashtransformation des Passwortes immer Wörterbuch-Angriffe möglich die mit schlecht gewähltem Passwort sehr efizient sein können.

Also wichtigste Regel: Ein Passwort ist ein Geheimnis das meistens durch den Menschen sehr schlecht und weit unter den Sicherheitsanforderungen ausgewählt wurde. Deshalb gehört dieses Passwort NUR in's Hirn und sollte in keinerlei Form gespeichert werden. Es sei denn, es würde mit einem viel besseren Passwort verschlüsselt oder transformiert.

Zitat:
Den Header darf man natürlich nicht mit verschlüsseln, also erst die Datei verschlüsseln und dann den Header dazupacken. Beim Entschlüsseln Header auslesen, Passwort überprüfen, Header aus der verschlüsselten Datei entfernen, entschlüsseln.
Dies ist korrekt. In meinem obigen Postings wurde das berücksichtigt. JEDE Funktion die mit Stream's arbeitet, sollte immer ausgehend von der aktuellen Stream.Position mit dem Stream arbeiten. So zumindestens arbeitet die VCL und auch DEC. Werden also aus einem Stream 8 Bytes gelesen und erst danach mit Cipher.DecodeStream() gearbeitet, so beginnt der Cipher mit dem 9'ten Byte im Stream zu entschlüsseln. Einzigste Aussnahme beim DEC ist wenn man z.b. Cipher.DecodeStream(Source, Dest, -1); sprich Size = -1 aufruft. Dann wird intern Stream.Position := 0; gesetzt.
Auch solche "Ausnahmen" würde ich heutzutage NICHT mehr so programmieren.

Zitat:
Der Passwort Hash wird ja ein String. Wie schreibt man denn ein Header-Record mit eienm Delphi HugeString, also mit einem String dessen Länge man nicht kennt? Somit ist ja auch die Headergröße nicht bekannt. Oder kann man davon ausgehen, dass ein Hash nicht länger wird als 255 Zeichen?
Ein Hash erzeugt immer einen binären Digest fester Länge. Z.b. SHA1 eben 20 Bytes. Wird dieser Hash konvertiert, durch TStringFormat_xxxx Klassen, dann werden zwar diese 20 Bytes expandiert, aber trotzdem hat der String dann mit dem gleichen Hash immernoch feste Länge.

Ein Header mit variabler Größe sollte nach dem Ident zur Erkennung des Headers eine Größenangabe in Bytes enthalten. Der Ident und die Größenangabe haben dann feste Länge und können nun direkt ausgelesen werden. Somit besteht ein Header variabler Größe im Grunde genommen aus ZWEI Teilen. Einen festen Part am Anfang aus Ident + Größenangabe und einem variablen Teil gleich danach der exakt Header.Size Bytes groß ist.
Generell bevorzuge ich aber Header die immer feste Länge haben, meistens 16,32,48 Bytes. Der Rest der fehlenden Bytes um auf diese Größen zu kommen wird einfach reserviert. Damit sind dann auch Erweiterungen des Headers möglich.

Auf eine Verschlüsselung des Headers sollte verzichtet werden, da sonst "known plaintext attacks" möglich sind. Gleich nach dem Header sollte man die Daten verschlüsselt speichern. ABER, diese Daten sollten mit Cipher.BufSize Bytes Zufallsdaten am Anfang erweitert werden.

Gruß Hagen
  Mit Zitat antworten Zitat