blowfish.pp wie sicher ?

Rund um die LCL und andere Komponenten
Antworten
corpsman
Beiträge: 1138
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus SVN Trunk, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

blowfish.pp wie sicher ?

Beitrag von corpsman »

Hallo Zusammen,

Als Aufarbeitung des letzten Stuttgarter Lazarus treffen und fürs neue bastle ich mir gerade einen Passwort Manager ( Demoprogram für Generische Klassen, Session Properties ..).

Klar das die eingegebenen Passwörter Verschlüsselt abgelegt werden müssen.

Nach etwas Recherche (eigentlich wollte ich die OpenSSL Lib einbinden) habe ich die blowfish.pp im FCL Verzeichnis gefunden. Wenn man es genau nimmt macht die alles was ich haben will und das auch noch Elegant.

Ein Blick auf die Wiki Page ( https://de.wikipedia.org/wiki/Blowfish ) läst gutes Hoffen:
Es ist kein effizienter Angriff auf die Blowfish-Verschlüsselung mit voller Rundenzahl bekannt.
Um Fehler durch "selbe" Passwörter zu Vermeiden nutze ich zusätzlich noch ein Salting ( https://de.wikipedia.org/wiki/Salt_(Kryptologie) ) für die Anwendung des Blowfish.

Unter der Annahme eines Offline Angriffs (meine Verschlüsselte Datenbank) wird geleackt und der Quellcode ist Verfügbar (weil hier gepostet ;) ):

Code: Alles auswählen

Procedure TPWM.SaveToFile(Const Filename: String; PassPhrase: String);
Var
  EncrytpStream: TBlowFishEncryptStream;
  fs: TFileStream;
  fSalt: UInt32;
Begin
  If (Not fmodified) Then exit; // Wenn Sich nichts geändert hat muss auch nichts gespeichert werden ..
  // Wenn die DB, geladen wurde hat sie ein "Altes" Passwort, das muss beim Speichern stimmen, andernfalls ist alles gut
  If (fPassword <> '') And (fPassword <> PassPhrase) Then Begin
    Raise Exception.Create('Error: invalid password, nothing is stored.');
    exit;
  End;
  (*
   * Die Idee ist, jedes Passwort zusätzlich zufällig zu "Salzen"
   * das Salz kann ganz einfach mit gespeichert werden.
   * => Das Bewirkt, dass bei jedem Speichern die Datenbank komplett neu und
   *    anders erzeugt wird. Selbst wenn sich eigentlich nichts ändert.
   *)
  // Dateihandle
  fs := TFileStream.Create(Filename, fmCreate Or fmOpenWrite);
  // Dateiversion
  fs.Write(PWM_FileVersion, SizeOf(PWM_FileVersion));
  // Salt
  fSalt := Random($FFFFFFFF);
  fs.Write(fSalt, SizeOf(fSalt));
  // Dann kommt der Verschlüsselte Teil
  EncrytpStream := TBlowFishEncryptStream.Create(inttostr(fSalt) + PassPhrase + inttostr(fSalt), fs);
  WriteMagicHeader(EncrytpStream); // Der Magic Header dient dazu zu erkennen ob die Entschlüsselte Datenbank gültige werte enthält =ist ein Constanter String
  SaveToStream(EncrytpStream);
  EncrytpStream.free;
  fs.Free;
  fmodified := false;
End;  
Wie seht ihr das, sind meine Daten halbwegs sicher, weil mein Masterpasswort geheim geblieben ist ?
Würdet ihr in dieses Beispiel eure Passwörter eingeben ?
Habt ihr Vorschläge das Sicherer zu machen / ein anderes Verschlüsselungsverfahren zu nehmen ?
--
Just try it

Warf
Beiträge: 1524
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: MacOS | Win 10 | Linux
CPU-Target: x86_64
Wohnort: Aachen

Re: blowfish.pp wie sicher ?

Beitrag von Warf »

Blowfish gehört nicht zu den sonderlich komplexen algorithmen, das sollte also im grunde kein problem sein. Auf die schnelle hab ich aber nix zum Modus gefunden. Wenn die Unit keine Implementierung davon bildet würde ich abraten, auf dem englischen wikipedia gibts ein paar bilder die das ganz schön erklären:
Bild
Falls die Blowfish Implementierung das nicht unterstützt würde ich dir empfehlen DCPCrypt oder so zu verwenden

Zu dem Salt, ein Salt wird verwendet um passwort Hashes die irgendwo gespeichert werden zu sichern damit 2 gleiche passwörter unterschiedliche hashes haben. Du speicherst aber den passwort Hash nirgendswo. Die einzige situation in der dir der Salt was bringen würde ist wenn 2 personen die selben daten mit dem selben passwort verschlüsseln, kannst du das feststellen, da die dateien identisch sind. Wenn du einen anderen Betriebsmodus als ECB verwendest allerdings bedeutet schon ein unterschiedliches Byte, das die Dateien komplett unterschiedlich sind. Ein security leak würde also dann entstehen wenn 2 verschiedene personen die exakt gleiche datenbank haben (also die exakt gleichen nutzrnamen und passwörter, verschlüsselt mit dem selben passwort), da du dann mit dem knacken der einen auch die andere geknackt hast. Aber ich behaupte mal das falls man 2 identische dateien hat, die wahrscheinlich die selbe datei von der gleichen Person sind.

Jetzt noch ein bisschen nitpicky: mit fPassword lässt du das passwort einfach im klartext irgendwo im ram rumlungern, wenn man also wie ich mit KeePass den passwort manager eigentlich dauerhaft offen hat, liegt das unverschlüsselte Master passwort dauerhaft im RAM (und sogar schlimmer, eventuell aufm pagefile/swap auf der platte). Wenn man also jetzt eine sicherheitslücke wie Spectre hat, oder einfach nach dem runterfahren des PC's den swap auf der platte rekonstruiert, kann man an das unverschlüsselte master passwort rankommen.
Lösung: Passwort hashen. Klar wird das Passwort mindestens während des hashens im klartext im ram liegen, wird aber danach wieder freigegeben und sehr wahrscheinlich überschrieben sodass das zeitfenster um an die daten zu kommen nur sehr kurz ist.

corpsman
Beiträge: 1138
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus SVN Trunk, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: blowfish.pp wie sicher ?

Beitrag von corpsman »

ui, das mit dem Fpassword ist erst später rein gekommen, das kann ich umbauen ;).

Der Quellcode vom Blowfish ist ja hier:

https://github.com/graemeg/freepascal/b ... lowfish.pp

über eine Mode kann ich da leider nichts rauslesen :(

werde mir das DCPCrypt mal ansehen, ...
--
Just try it

TSchnuckenbock
Beiträge: 13
Registriert: Do 20. Jul 2017, 23:47

Re: blowfish.pp wie sicher ?

Beitrag von TSchnuckenbock »

Ich meine mich zu erinnern, daß im internationalen Lazarus-Forum der User Xor-el viel bzgl. Verschlüsselung gemacht hat.
Sein Repo ist

https://github.com/Xor-el

Eventuell ist da was für dich dabei.

corpsman
Beiträge: 1138
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus SVN Trunk, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: blowfish.pp wie sicher ?

Beitrag von corpsman »

Sodale hab es nun umgestellt auf DCPCrypt und die MD5 hashes des Passwortes rein ( Was das Masterpasswort Sichert, aber die Daten die gespeichert sind nicht, dazu müsste ich die gespeicherten Daten im Ram ständig ver und entschlüsseln) => Daher ja die Annahme das die SW immer nur Kurz gestartet wird ;)

Code: Alles auswählen

Procedure TPWM.SaveToFile(Const Filename: String; PassPhrase: String);
Var
  EncrytpStream: TDCP_blowfish;
  fs: TFileStream;
  DataStream: TMemoryStream;
  fSalt: UInt32;
  PPMD5: String;
Begin
  If (Not fmodified) Then exit; // Wenn Sich nichts geändert hat muss auch nichts gespeichert werden ..
  PPMD5 := MD5Print(MD5String(PassPhrase));
  // Wenn die DB, geladen wurde hat sie ein "Altes" Passwort, das muss beim Speichern stimmen, andernfalls ist alles gut
  If (fMD5Password <> '') And (fMD5Password <> PPMD5) Then Begin
    Raise Exception.Create('Error: invalid password, nothing is stored.');
    exit;
  End;
  fMD5Password := PPMD5;
  (*
   * Die Idee ist, jedes Passwort zusätzlich zufällig zu "Salzen"
   * das Salz kann ganz einfach mit gespeichert werden.
   * => Das Bewirkt, dass bei jedem Speichern die Datenbank komplett neu und
   *    anders erzeugt wird. Selbst wenn sich eigentlich nichts ändert.
   *)
  // Dateihandle
  fs := TFileStream.Create(Filename, fmCreate Or fmOpenWrite);
  // Dateiversion
  fs.Write(PWM_FileVersion, SizeOf(PWM_FileVersion));
  // Salt
  fSalt := Random($FFFFFFFF);
  fs.Write(fSalt, SizeOf(fSalt));
  // Dann kommt der Verschlüsselte Teil
  DataStream := TMemoryStream.Create;
  WriteMagicHeader(DataStream); // Der Magic Header dient dazu zu erkennen ob die Entschlüsselte Datenbank gültige werte enthält =ist ein Constanter String
  SaveToStream(DataStream);
  DataStream.Seek(0, soBeginning);
  EncrytpStream := TDCP_blowfish.Create(Nil);
  EncrytpStream.InitStr(inttostr(fSalt) + PassPhrase + inttostr(fSalt), TDCP_sha256);
  EncrytpStream.CipherMode := cmCBC; // Cipher-Block Chaining (CBC)
  EncrytpStream.EncryptStream(DataStream, fs, DataStream.Size);
  EncrytpStream.free;
  DataStream.Free;
  fs.Free;
  fmodified := false;
End; 
Damit wäre ich zufrieden, ihr auch ?
--
Just try it

Socke
Lazarusforum e. V.
Beiträge: 2830
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: blowfish.pp wie sicher ?

Beitrag von Socke »

corpsman hat geschrieben:
Do 22. Okt 2020, 14:11
MD5 hashes des Passwortes rein
MD5 ist nicht mehr zu empfehlen; wenn du etwas neu implementiertst, solltest du besser direkt SHA256 (oder mehr Bits) verwenden.
Noch besser sind spezifische Funktionen wei PBKDF2, bcrypt oder scrypt. Für letztere habe ich auch eine Pascal-Implementierung gefunden: Scrypt for Delphi
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Warf
Beiträge: 1524
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: MacOS | Win 10 | Linux
CPU-Target: x86_64
Wohnort: Aachen

Re: blowfish.pp wie sicher ?

Beitrag von Warf »

Jetzt wo du nen hash hast soltest du diesen hash auch salten, sonst könnte jemand einfach den hash auslesen und gegen ein dictionary der beliebtesten passwörter gehashed vergleichen.

Zur Hash Funktion, MD5 hat zwar gravierende Sicherheitslücke, undzwar das man Kollisionen erzeugen kann (vor allem bei konstantem prefix) was es z.b. zum signieren und validieren von informationen gänzlich ungeeignet macht. Da es bei dir allerdings ja nur ein consistency check ist, und man durch den angriff nicht auf das Passwort rückschlüsse ziehen kann ist das für dich nicht so sehr von relevanz.
Aber, MD5 ist schnell zu berechnen (daher wird es bis heute immernoch gerne für nicht security wichtige checks verwendet wie in updatern für nicht security relevante programme, z.b. Spiele). Schnell zu berechnend zu sein ist für Passwörter aber keine gute Eigenschaft, da ein Legitimer Passwort Check ja normalerweise eh nur ein einziges mal Hashen muss. Im gegensatz dazu ist das Toll für einen bruteforce Angriff, da man damit schön viele hashes pro Sekunde checken kann.
SHA512, braucht im schnitt c.a. 80%-90% länger als MD5 auf gleicher Hardware, für den Bruteforcer heist das also das er effektiv doppelt so lang braucht

Scrypt was Socke vorgeschlagen hat macht intern praktisch einen SHA256 hash vom passwort plus einem salt. Der salt wird aus einem angegeben salt berechnet, wobei das ziel der berechnung möglichst langsam sein soll. Scrypt ist also praktisch eine methode um ein gesalteten SHA256 hash zu erzeugen der möglichst viel zeit in anspruch nimmt zu berechnen. Der Aufwand der benötigt wird um diesen salt zu berechnen kann dabei über parameter gesteuert werden.

Außerdem, wenn du DCPCrypt verwendest, kannst du auch TwoFish nehmen, das ist der nachfolge Algorithmus von Blowfish mit der wichtigsten änderung ist eine Vergrößerung der Block Größe und um mal Bruce Schneider, den erfinder der beiden ALgorithmen zu zitieren:
Bruce Schneier, 2007 hat geschrieben:At this point, though, I'm amazed it's still being used. If people ask, I recommend Twofish instead.
Andere optionen sind Rijandael und Serpent. In der competition um den neuen AES (advanced encryption standard) waren Twofish, Rijandael und Serpent die drei top favoriten. Rijandael hat gewonnen (und wird damit auch oft AES genannt) wegen seiner einfacheit und geschwindigkeit. Twofish ist in diesem Sinne sogar sicherer gegen bruteforce, da es einfach länger dauert damit ein dokument zu entschlüsseln.
Programme wie VeraCrypt (vormals TrueCrypt) benutzen einfach alle 3 auf einmal.

Mit DCPCrypt, da die alle von der selben Oberklasse ableiten, kannst du die Cipher extrem einfach austauschen und könntest es sogar einstellbar machen

corpsman
Beiträge: 1138
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus SVN Trunk, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: blowfish.pp wie sicher ?

Beitrag von corpsman »

Hallo Warf,

Danke für die Ausführung, ich denke ich stelle damit alles auf Rijandael um, da ich tatsächlich plane das Programm zu nutzen, jetzt wo es so viele Verbesserungen bekommen hat ;).

Die Variante das Verfahren Optional zu machen ist zwar Implementierungstechnisch interessant, aber ich habe die Erfahrung gemacht, dass wenn der User zu viel konfigurieren kann, er es lässt (weil verwirrt). Da kann ich auch gleich den Empfohlenen Standard implementieren ... :mrgreen:
--
Just try it

Socke
Lazarusforum e. V.
Beiträge: 2830
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: blowfish.pp wie sicher ?

Beitrag von Socke »

corpsman hat geschrieben:
Fr 23. Okt 2020, 07:11
Die Variante das Verfahren Optional zu machen ist zwar Implementierungstechnisch interessant, aber ich habe die Erfahrung gemacht, dass wenn der User zu viel konfigurieren kann, er es lässt (weil verwirrt). Da kann ich auch gleich den Empfohlenen Standard implementieren ... :mrgreen:
Leider ändern sich die Standards von Zeit zu Zeit. Bevor Rijndael der empfohlene Standard war, hatte man DES oder Triple-DES verwendet. Auch wenn der User dies nicht konfigurieren kann, ist es doch sinnvoll, den Algorithmus in der Software einfach an einer zentralen Stelle austauschen zu können.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

corpsman
Beiträge: 1138
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus SVN Trunk, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: blowfish.pp wie sicher ?

Beitrag von corpsman »

*g*

das eine schliest das andere nicht aus, ich habe in allen meinen Dateien die ich abspeichere immer eine Fileversion für das Passwort Manager beispiel sieht das z.B. so aus:

Code: Alles auswählen

  fs := TFileStream.Create(Filename, fmOpenRead);
  fFileVersion := PWM_FileVersion + 1;
  fs.read(fFileVersion, SizeOf(fFileVersion));
  If PWM_FileVersion < fFileVersion Then Begin // Die Geladene Datei ist neuer als die Programmversion => wir können das nicht laden
    FLastError := 'Invalid file version';
    result := false;
    fs.free;
    exit;
  End;
  fSalt := 0;
  fs.Read(fSalt, SizeOf(fSalt));
  If fFileVersion >= 4 Then Begin
    DecrytpStream := TDCP_rijndael.Create(Nil);
  End
  Else Begin
    DecrytpStream := TDCP_blowfish.Create(Nil);
  End;                             
Damit ist der Code dynamisch und Abwärtskompatibel. sollte irgendwann ein neuer Encryption Algorithmus kommen wird das If entsprechend erweitert ;)
--
Just try it

Antworten