Mein Ver/Entschlüsseln - Eure Meinung

Für allgemeine Fragen zur Programmierung mit PureBasic.
BSP
Beiträge: 188
Registriert: 01.02.2009 14:04

Mein Ver/Entschlüsseln - Eure Meinung

Beitrag von BSP »

Hallo Leute.
Bitte nicht schimpfen oder lästern.
Ich bastle mir einen eigenen Passworttresor.
Ich weiß, entsprechende Prgs gibt es inzwischen viele.
Trotzdem interessiert mich Eure Meinung zu meinem Prg.
Wo sind die Fehler? Die Schwachstellen??

A. Das Masterpasswort muß man später direkt eingeben.
Es ist nirgendwo im Prg vermerkt.
Das Passwort darf eine variable Länge haben.

B. Aus dem Passwort wird ein Schlüssel generiert.
Wie sicher ist dieser Schlüssel? Was sagt Ihr dazu?

C. Aus der Kombination des Passworts und dem Schlüssel werden dann die weiteren Texte, Passworte, Ver/Entschlüsselt.
Auch hierzu bitte ich Euch um Eure Meinung.

Ich danke Euch schon mal für Eure Mühe.
Hier also mein Muster- Prg. (Muster weil, es wird später in einem größeren Prg verbaut).

Code: Alles auswählen


Procedure.s Get_Passwort()
  ;passwort$ = InputRequester("Passwort", "Passwort Eingeben !", "", #PB_InputRequester_Password)
  passwort$ = "Passwort" ; So ists richtig
  ;passwort$ = "Password" ; Das ist falsch
  ProcedureReturn passwort$
EndProcedure

Procedure.d Create_Schluessel(passwort$)
  schluessel.d = 1
  For i = 1 To Len(passwort$)
    b = Asc(Mid(passwort$, i, 1))
    If b % 2
      schluessel = schluessel * b
    Else
      schluessel = schluessel / b
    EndIf
  Next
  schluessel = schluessel / Len(passwort$)
  
  ; Nachkommastellen abschneiden
  a$ = StrD(schluessel)
  schluessel = Val(StringField(a$, 1, "."))
  
  ProcedureReturn schluessel
EndProcedure

Procedure.s Verschluesseln(passwort$, schluessel.d, text$)
  c$ = ""
  j = 1
  For i = 1 To Len(text$)
    b.d = Asc(Mid(passwort$, j, 1)) * schluessel
    a.d = Asc(Mid(text$, i, 1)) * b
    c$ + StrD(a, 0) + ","
    j + 1 : If j > Len(passwort$) : j = 1 : EndIf
  Next
  ProcedureReturn c$
EndProcedure

Procedure.s Entschluesseln(passwort$, schluessel.d, c$)
  text$ = ""
  j = 1
  For i = 1 To CountString(c$, ",")
    a = Val(StringField(c$,i,","))
    b = Asc(Mid(passwort$, j, 1))
    a = a / (b * schluessel)
    text$ + Chr(a)
    j + 1 : If j > Len(passwort$) : j = 1 : EndIf
  Next
  ProcedureReturn text$
EndProcedure

; ---

passwort$ = Get_Passwort()
Debug passwort$

schluessel.d = Create_Schluessel(passwort$)
Debug schluessel

text$ = "aVerschlüsselter Text"

testcode$ = "15535520,16700684,23253230,26246220,27397370,21999978,23735712,25081056,40360320,22332310,26476450,23253230,25729704,25777752,23051028,26474448,5125120,16312296,23253230,27627600,27635608,"


c$ = Verschluesseln(passwort$, schluessel, text$)
Debug c$
  
text$ = Entschluesseln(passwort$, schluessel, c$)
Debug text$

text$ = Entschluesseln(passwort$, schluessel, testcode$)
Debug testcode$
If text$ = "aVerschlüsselter Text"
  Debug "Passwort OK"
Else
  Debug "Passwort Falsch"
EndIf

PB 5.31 (x86) & (x64) Win10
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Mein Ver/Entschlüsseln - Eure Meinung

Beitrag von ts-soft »

BSP hat geschrieben: A. Das Masterpasswort muß man später direkt eingeben.
Es ist nirgendwo im Prg vermerkt.
Aber einen Fingerprint (Hashwert) zum Passwort solltest Du einfügen, um zu checken ob das Passwort auch stimmt.
Ist besser als die Programm nur Müll produzieren zu lassen, bei falschem Passwort.

PS: Die Zeile: testcode$ = "15535520,16700684...." ohne leerzeichen zerstört das Boardlayout. Es wird leserlicher,
wenn Du ein paar Leerzeichen nach den Kommas einführst.

Gruß
Thomas
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
man-in-black
Beiträge: 362
Registriert: 21.08.2006 17:39

Re: Mein Ver/Entschlüsseln - Eure Meinung

Beitrag von man-in-black »

Hi,

wieso sollten wir lästern? ;)

Vorweg, mich haben diese Zeilen gestört:

Code: Alles auswählen

 ; Nachkommastellen abschneiden
  a$ = StrD(schluessel)
  schluessel = Val(StringField(a$, 1, "."))
Das kann man auch mit Abwärtrunden (Round(...,#PB_Round_Down)) lösen

Positiv:
es ist zwingend ein Passwort notwendig, um die Daten zu lesen
-->Tool einfach cracken bringt nichts

Negativ:
-dein Schlüssel ist zu kurz bzw. zu unsicher erstellt (modulo ist aber schonmal ein Anfang)
-der verschlüsselte Text ist riesig (aber für PWs noch i.O.)
-Umweg über Strings (-> bremst)



Ausführlicher:

Gegen einen Schlüssel kann man nichts sagen. Leider ist der bei dir durch die Division in jedem zweiten Schritt
sehr klein. Setzt man ganz "dumm" Bruteforce (alle Kombinationen durchprobieren) ein, ist er kaum ein Hindernis.
Moderne Kryptographieverfahren setzen hier auf Primzahlen und mathematische Operationen, die kaum/ gar nicht reversibel sind.
Es wird dabei ausgenutzt, dass die pseudo Umkehrfunktionen sehr viel Zeit in anspruch nehmen. Bruteforce ist daher möglich,
aber nicht in einem Menschenleben machbar. ;)
Das hat paradoxerweise den Vorteil, dass das Verschlüsselungsverfahren selbst bekannt sein kann.

Ein wichtiger Punkt beim "rumprobieren" ist eine Prüfung auf Sinnhaftigkeit des entschlüsselten Textes. Hierzu braucht der
Computer eine Regel/Gegenkontrolle wie z.B. ein Wörterbuch. Baust du, wie ts-soft vorgeschlagen hat, eine Hashprüfung ein,
hat es der Cracker später seeehr viel einfacher. Dann wird das Bruteforce Passwort in erster Linie gegen den Hash getestet
und nicht der verschlüsselte Text selbst entschlüsselt -> extremer Zeitgewinn beim Knacken!
(Das gilt natürlich nur, wenn der Hash auf dem gleichen PC gespeichert ist.)
Bei großen Datenmengen würde ich aber ts-softs Vorschlag einbauen, zumindest einen Kompromiss.

Du könntest aber dem späteren Nutzer vorschlagen, einen Kontrollwert in die Passwortliste einzusetzen. Diesen
muss er dann selbst validieren. (z.B. das zweite Passwort der Liste heißt 1234567)
Kann man auch durch das Programm abfragen lassen. (Quasi 2 Passwörter)

Es wird zwar Müll produziert, wenn das Passwort falsch ist, aber
a) man wird i.d.R nur 1-2 Mal entschlüsseln
b) deine Passwortliste ist von der Größe lachhaft ggü. anderen Anwendungsgebieten (-> zeitunkritisch).

Das als kurzen Einblick. Dein Vorgehen finde ich aber grundsätzlich schonmal gut. :allright:

MFG
MIB
(hab alles, kann alles, weiß alles!!^^)

Bild
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8679
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Mein Ver/Entschlüsseln - Eure Meinung

Beitrag von NicTheQuick »

Create_Schluessel macht überhaupt keinen Sinn. Sobald mehr Zeichen mit geradem ASCII-Code als welche mit ungeradem dabei sind, steht vor dem Komma eine Null. Wird dann auch noch durch die Anzahl Zeichen insgesamt geteilt, wird der resultierende Wert nur noch kleiner. Schneidest du jetzt alle Nachkommastellen ab, hast du die komplette Entropie verloren, die das Passwort vorher hatte. Das sieht man hier deutlich:

Code: Alles auswählen

Debug Create_Schluessel("b")
Debug Create_Schluessel("ab")
Debug Create_Schluessel("aabb")
Debug Create_Schluessel("aaabbb")
Alles ergibt 0.

Außerdem wird nur darauf geachtet, ob ein Buchstabe ungerade oder gerade ist, auf die Position oder seinen eigentlichen Wert wird nicht geachtet:

Code: Alles auswählen

Debug Create_Schluessel("abc")
Debug Create_Schluessel("cba")
Debug Create_Schluessel("acb")
Ergibt immer 32.0.

Abgesehen davon arbeiten Doubles mit 64 Bit, viel mehr als 64 Bit Information kannst du also nie in ihnen unterbringen. Es hat schon seinen Grund, dass man nicht seine eigenen Hash- und Verschlüsselungsfunktionen erfinden soll, sondern Verfahren nutzen soll, die kryptografisch sicher sind.

Wenn der Schlüssel 0 ist, wie es ja mit über 50% Chance sein kann, dann gibt Verschluesseln() nur Nullen zurück, egal wie der zu verschlüsselnde Text oder Passwort vorher waren. Versuchst du mit einem solchen Schlüssel zu Entschlüsseln, bekommst du eine Division durch Null.

Deswegen mein Rat: Nutze SHA2 und aufwärts um Hashs aus deinen Passwörtern zu erstellen, speichere die auch ab um sie überprüfen zu können. Füttere mit diesem Hash dann die AES-Decoder und -Encoder.
Bild
BSP
Beiträge: 188
Registriert: 01.02.2009 14:04

Re: Mein Ver/Entschlüsseln - Eure Meinung

Beitrag von BSP »

Vielen Dank schon mal Euch Dreien, Thomas & MIB & besonders Nick

Hallo Thomas
Die Zeile Testcode$.....
dient ja gerade der Passwortüberprüfung.
Sie ist der Verschlüsselte Code von "aVerschlüsselter Text", erzeugt vom Prg selber.
Sie tauch später im Prg nicht mehr auf sondern wird der ersten Datensatz in der generierten Datenbank.
Hier habe ich die Werte für einen Funktionstest aus dem Debuger in das Prg kopiert.
Ich habe mir überlegt das, wenn ein neues Masterpasswort eingegeben wird,
das Prg als erste Zeile in der Datenbank den Code eines Testwortes, hier "aVerschlüsselter Text" generiert und später zur Überprüfung heran zieht.
So darf dieses Testwort ruhig lesbar im Prg stehen, man muss ja erstmal das Passwort kennen, damit der scheinbar wirre Code aus der Datenbank wieder das Testwort ergibt.

Hallo MIB.
"; Nachkommastellen abschneiden"
Ja, da habe ich wohl glatt eine PB- Funktion übersehen, Danke für den Hinweis.

Nun zum Schlüssel. Meine Überlegungen waren folgende.
Ob der Schlüssel im Schleifendurchlauf Multiplizert oder Dividiert wird hängt ja davon ab,
welchen Nachkommawert ein im Passwort überprüftes Zeichen hat.
Kennt man das Passwort nicht ist es unmöglich vorherzusagen, wann geteilt und wann malgenommen wird.
Am Ende der Schlüsselgenerierung teil ich den Schlüssel noch durch die Länge des Passwortes.
Auch hier: Kennt man das Passwort nicht weiß man vorher nicht, durch welchen Wert nun geteilt wird.
Hier könnte ich ja vieleicht auch Multiplizieren statt teilen, oder einen Potenzwert aus der Passwortlänge nehmen, o.ä. ?

Zum knacken der Werte. Wie müsste man vorgehen, hmm.
Ich erzeuge ein Testwort aus lauter aaa..
Teile ich nun den "Codewert / ascii- a" erhalte ich "b*schlüssel". Wobei "b" ja der Asciwert eines Passwortzeichens ist.
Nun müsset ich eine Schleife 0 bis 255 laufen lassen, wo bei jedem erhaltenen "b*schlüssel" Wert dann der Schlüssel übrig bleibt.
also "schlüssel = (b * schlüssel) / schleifenwert".

Tja, hmm. Wie ich also nun selber sehe, auch alles nicht gut.
Für schnelle Rechner von Heute auch kein Problem mehr.
Also wieder von vorne.
Internet stöbern, begreifen versuchen, von der Fülle der Informationen erschlagen werden und aufgeben.
Fazit: Meine Pin fürs Onlinebanking hat noch lange nichts in dem PC zu suchen. Grins.

Nun gut. Danke jedenfalls, das Ihr Euch mal mein Prg angesehen habt.
MfG: Bernd

PS. Und nun nachträglich noch einen großen Dank an Nick. (Nachträglich weil, ich hatte den oberen Teil bereits geschrieben).
Lange Rede kurzer Sinn.
Wie Du mir zeigst ist meine ganze Vorgehensweise absoluter Unsinn.
Aber so sehe ich nun zumindest wie richtig es war, mein Prg doch mal in diesem Forum zu zeigen.
Ich hätte mich sonst in falscher Sicherheit gewogen.

Also nochmal großen Dank an Euch Allen.
Bernd
PB 5.31 (x86) & (x64) Win10
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: Mein Ver/Entschlüsseln - Eure Meinung

Beitrag von GPI »

Ich würde folgendermaßen den "Verschlüsselungsschlüssel" mit
CryptRandomData(*Puffer, Länge)
erzeugen, und dann das MasterPasswort nehmen, diesen Schlüssel mit XOR bearbeiten und *DANN* den gexorten Schlüssel normal abspeichern (bspw. mit Base64). Du wirst ihn für alle Einträge brauchen!

Wenn man den Verschlüsselungsschlüssel braucht, lädt man ihn aus der Datei, XOR den mit von User eingegebenen MasterPasswort und benutzt ihn anschließend einfach.

zum Verschlüsseln der Passwörter würde ich:
Das Passwort als UTF8 in einen Buffer schreiben, ein Sonderzeichen (darf nicht als Passwort-Zeichen erlaubt sein. Bspw. Ascii-10, oder Zufällig Ascii-Zeichen 0-31) als Trennzeichen hinzufügen und dann mit 30-50 zufälligen Müll-Zeichen auffüllen (damit mehr Daten verschlüsselt werden, als benötigt)
MIt CryptRandomData einen Initalvektor erzeugen
Mit AESEncoder das Passwort mit den Verschlüsselungsschlüssel und den Initalvektor verschlüsseln
den Initalvektor mit den MasterPasswort XORn und abspeichern, gefolgt von den AES-Verschlüsselten Daten.

Zum Entschlüsseln muss man halt alles genau umgekehrt machen, nach den Sonderzeichen suchen (bspw. den ersten Sonderzeichen in Bereich 0-31) und dann das Passwort mit der Länge auslesen.

Beim XORN musst du halt aufpassen. Das MasterPasswort darf bei 256Bit-Verschlüsselung maximal 32Bytes lang sein. Wobei ich das MasterPasswort in UTF8 umwandeln würde - Unicode halte ich nicht für geeignet, weil es 2 Zeichen hat und eins in der Regel ein Leerzeichen ist. Wenn du längere Passwörter erlauben willst, musst du beim XOR halt wieder bei der ersten Stelle anfangen. Aber mal ehrlich: Wenn 32 Zeichen für ein Passwort nicht reicht, dann hat man verloren.

Problematisch bleibt aber weiterhin, das du (wenn auch gexort) den Verschlüsselungsschlüssel abspeichern musst. Damit sind halt BruteForce-Methoden möglich, sobald man zugriff erlangt. Dieses Problem haben allerdings alle solche Tools.

Edit: Was mir noch kommt: Nie, wirklich nie nie nie nicht von passwort eine unverschlüsselte MD5, CRC oder sonstige Prüfsumme abspeichern. *IMMER* Verschlüsseln. Bei einer Brutforce-Attacke müsste der "Hacker" immer sämtliche Schritte von oben durchgehen und dann kontrollieren, ob was sinnvolles rauskommt. Das dauert, sehr sehr lange. Eine MD5/CRC ist auf Geschwindigkeit ausgelegt. Ein Hacker würde da immer erst versuchen, das Passwort mittels MD5 zu überprüfen, bevor ein echter Entschlüsselungsversuch erfolgt. Das kann die Zeiten von Jahren auf Stunden reduzieren. Zudem gibt es meines Wissens nach MD5-Listen, die dann gleich potentielle Passwörter auflisten.
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Benutzeravatar
TroaX
Beiträge: 661
Registriert: 08.03.2013 14:27
Computerausstattung: PC: Ryzen 9 3950X, 96 GB RAM, RX6800XT, 2.5 TB SSD, 21:9 Display, Pop_OS! | Lappi: Ryzen 7 5800H, 16 GB RAM, 1 TB SSD, Pop_OS!
Wohnort: NRW
Kontaktdaten:

Re: Mein Ver/Entschlüsseln - Eure Meinung

Beitrag von TroaX »

Wow ihr seid aber beim erzeugen von Schlüsseln kreativ :mrgreen:

1. Gegen Bruteforce kann man sich den ganzen Käse sparen. Die Ver-/Entschlüsselungsroutinen (AES) verwenden immer das gleiche Interface und erfordern immer die gleichen Eingabedaten (Ein Hoch auf Standards). Da könnt ihr die Bits hin und her schubsen, wie ihr wollt. Bruteforce-Attacken sind zwar nicht die effektivsten. Aber wer das wirklich vorhat, der setzt nicht am Tool an, sondern beim Algorithmus. Es ist definitiv effektiver, die Daten direkt mit Zufallsdaten oder durchzählen zu entschlüsseln, als die Schlüsselerzeugung des Tools selbst zu penetrieren.

2. Wer beim cracken der Verschlüsselung Zeit sparen will, verwendet entweder Dictonaries oder Rainbow-Tables und jagt dann diese durch die Routinen des Tools. Und da ist wie auch schon beim Login auf Webseiten die Divise: "Je länger ein Durchgang dauert, um so länger dauert das cracken!"
Ihr legt den Fokus einfach viel zu stark darauf, aus dem Master-Passwort Datensalat zu machen und vergesst dabei, das ihr kaum Zeit dabei verschwendet. Die Key-Derivation-Funktionen wie das Blowfisch-Passwort der password_hash Bibliothek (PHP) oder PBKDF2 gehören mittlerweile zu den Quasi-Standards in der Passwortsicherheit. Der Grund dafür ist einleuchtend. Egal wie viele Schritte ihr beim verschleiern eures Passwortes macht. Wenn ein Angreifer mit einem kompilierten Cracking-Tool 100.000 Durchläufe die Sekunde schafft, ist es deutlich unsicherer, als wenn eine Derivation-Funktion von sich aus in der Sekunde 300.000 Durchläufe macht und der Cracker dadurch nur ein Versuch pro Sekunde schafft!

3. Die Auflösung des Schlüssels sowie der Initialisierungsvektor haben eine feste Auflösung. Wer also 256 Bit fährt (was definitiv zu empfehlen ist), kann dort auch nur 256 Bit unterbringen. Nicht 257 und auch nicht 255. 256 Bit! Egal wie aufwendig man den Schlüssel erzeugt und wie lang das ganze ist. Man muss es immer auf die 256 Bit herunterbrechen oder aufblasen. Einfach abschneiden ist Fatal, da es die Kollisionswahrscheinlichkeit erhöht. Aufblasen ist auch nicht Ideal, da die unnötige Luft irgendwo gespeichert sein muss, damit die Schlüsselerzeugung die Luft nicht selbst noch Bruteforcen muss. Das sinnvollste ist und bleibt ein Hash in 256 Bit länge, ohne großartig dran rumzuwursten. Denn der Wertebereich für Druckbare Zeichen ist deutlich geringer als der Wertebereich, der in die Bytes gepackt werden kann. Krytografische Hashfunktionen sind daraufhin optimiert, so eindeutig wie möglich eine Repräsentation eines Datenstücks zu erzeugen und dabei den vollständigen Wertebereich eines Bytes zu nutzen. Die Hexadezimale Darstellung eines solchen Hashes ist im Grunde auch nichts anderes als eine Repräsentation der Zahlen, die dadurch erzeugt wurden. Am Ende sind es 256³² Zahlen-Kombinationen und es ist vollkommen egal, wie ihr sie bekommen habt. Beim Bruteforcen schubst man die Zahlen dort direkt rein und dann interessiert das Wie nicht mehr. Aber sollte man auf Grund von unnötig aufgeblasenen Quelldaten eine Kollision erzeugen, kann es schon wieder ungemütlich werden.

PS: Ich habe da noch etwas vergessen zu erwähnen. Die Passwortlänge sollte zwar eine Mindestanzahl an Zeichen haben. Aber das obere Limit sollte hoch liegen. Sogar bis 128 Zeichen würde ich erlauben, da die Auflösung an Druckbaren Zeichen viel geringer ist als die an Bytes. Aus diesem Grund sollte man auch niemals den Einsatz einer Zeichenklasse verbieten, da man das Passwort um Auflösung beraubt und dadurch erheblich weniger Kombinationen probiert werden müssen. Sonderzeichen müssen erlaubt sein! Denn es macht einen riesigen Unterschied, ob Cracker nun generell Sonderzeichen mit einbeziehen müssen oder ausschließen können.

4. Zwischenverschlüsselung von Daten macht auch wenig Sinn. Denn die Daten für die Verschlüsselung müssen ja auch irgendwo herkommen. Man benötigt dort auch wieder einen Schlüssel und mit dem CBC Verfahren einen Vektor. Wie soll man sich das Vorstellen? Man verschlüsselt den Initialisierungsvektor für die Hauptverschlüssellung sowie dem Passwort als Hash mit welchem Schlüssel und welchem Vektor nochmal? Das Datenstück ist im Vergleich zum vollständig zu verschlüsselndem Dokument sehr klein, was die Entschlüssellungszeit drastisch senkt. Je nach Implementierung kann man sich mit dieser Idee sogar eine Hintertür öffnen. Sowas würde ich generell schon einmal lassen.

5. Das Entschlüsseln dauert in der Masse relativ lang. Man selbst als Nutzer merkt es allerdings kaum, da man es ja nicht 1.000 mal oder öfter hintereinander macht. Speichert also das Passwort nirgends als Hash. Das ist Blödsinn. Ihr würdet euch selbst einer effektiven Crackerbremse berauben, da man versuchen wird, den Hash zu cracken als die Daten. Und wer das Passwort zum Hash hat, kommt auch an die Daten!

Ich würde also so vorgehen:
1. Programm wird zum ersten mal gestartet und man muss das Masterpasswort festlegen. Dabei werden mindestens 8 Stellen vorausgestzt. Die Länge kann gerne bis 64 oder mehr sein. Es wird ein kryptografisch sicherer Salt erzeugt, der dann an das Passwort gehängt oder davor gesetzt wird. Dann wird eine Datei erzeugt, in der eine Zufallszahl zwischen 100.000 und 899.999 sowie der Salt geschrieben werden. Der Salt sowie auch diese Zahl brauchen nicht geheim sein, da der Salt gegen Dictonaries helfen soll und die Zahl gegen Rainbow-Tables. In beiden Fällen liegen unveränderliche Datenbestände vor, die nicht mal so eben in ein paar Monaten auf genau diesen Salt oder die Anzahl der Cycles verändert werden kann.

2. Das Passwort und der Salt werden zusammen um die zufällig generierte Anzahl + 100.000 (also mindestens 200.000 und maximal 999.999) mit sich selbst gehashed (Key-Derivation Funktion wie PBKDF2). Dictonary-Attacken rechnen also mindestens pro Passwort zwischen einer und 4 Sekunden. Völlig ineffektiv. Das versucht keiner!

3. Es werden 10 Initialisierungsvektoren erzeugt und gespeichert. Diese müssen auch nicht geheim sein, da das Programm diesen sowieso benötigt. Ich verwende die 10 als Pepper. Es wird nur mit einem verschlüsselt. Nur welcher wird bei jedem Verschlüssellungsdurchgang zufällig gewählt. Da ich als Nutzer der Software das Passwort natürlich richtig eingebe, werden die Daten mit jedem Vektor entschlüsselt, bis ein Vektor ein valides Ergebnis liefert und die Daten offen liegen. Bis hierhin wird der Schlüssel sowie das Passwort nirgends gespeichert und das bleibt auch so. Im Idealfall aber muss beim Bruteforcen sowie bei den anderen Angriffsmethoden jeder Vektor zusätzlich zur Derivation-Funktion probiert werden, was den zeitlichen Aufwand um das 10fache anschwellen lassen kann. Man darf niemals vergessen, das der Nutzer bei korrekter Eingabe seines Passworts nur geringe zeitliche Einbußen hat (bis auf die Derivation. Aber für die Sicherheit kann er im Ernstfall auch mal 1-4 Sekunden warten).

4. Um eine Erfolgreiche Ver- und Entschlüsselung festzustellen, werden die Daten in einem etablierten und prüfbaren Format gespeichert. Dafür bieten sich JSON, XML oder SQLite an. Ich würde aber die ersten beiden vorziehen. Liefert CatchJSON oder XMLStatus keinen Fehler, war Passwort sowie Initialisierungsvektor richtig und die Daten werden bereitgestellt. Liefern sie aber 0 bzw. Fehler zurück, macht das Programm mit dem nächsten Vektor weiter. Hat er alle Vektoren durch und alle liefern Fehler, ist das Passwort falsch! Und dafür musste wie schon gesagt nirgends das Passwort gespeichert werden.

5. Verschlüsselt so viel wie möglich in einem Dokument. Verschlüsselt niemals jedes Passwort aus dem Manager einzeln. Denn die größe des Dokuments ist entscheidend für die Entschlüssellungsdauer und diese ist wiederum entscheidend für das Bruteforcen. Wenn 100 Zeichen pro Dokument verschlüsselt werden, dann ist wahrscheinlich das Auswürfeln eines Schlüssels für den nächsten Versucht langsamer als das entschlüsseln selbst. Ich empfehle daher, den kompletten Bestand auf einmal zu verschlüsseln und dabei auch noch ein wenig aufzupusten. Dafür eignet sich XML am besten. Nehme einfach Knoten mit aussagekräftige Namen und keine Abkürzungen. Dadurch wird das Dokument gut aufgeblasen und es dauert länger.

6. Um die Routinen des Tools selbst nicht für das cracken zu missbrauchen, sollte das Tool nach jeder z.B. dritten Falscheingabe ein Delay erzeugen und die nächste Eingabe herauszögern. Ein paar Sekunden reichen dafür schon und die Effektivität für das Cracken über das Programm selbst sinkt erheblich.

Zusammengefasst:
Rohe Bruteforce-Attacken kann man weder verhindern, noch erschweren, da AES in jeder Sprache identische Daten zum arbeiten benötigt. Schlüssel in fester Länge und Vektor in fester länge. Wer also mit Bruteforcing das Dokument knacken will, geht überhaupt nicht den Umweg über die Schlüsselerzeugung, sondern jagd seine Daten direkt in den AES-Algorithmus.

Für Dictonary sowie Rainbow-Table Attacken auf den Schlüssel sorgen Salt's und eine Variable Anzahl an Cycles für eine Key-Derivationfunktion der Schlüssel für Sicherheit. Beides muss nicht geheim gehalten werden. Denn nur weil ein Angreifer den Salt kennt, tauchen in den Dictonaries nicht von heut auf morgen Passwörter mit dem Salt auf. Genauso ist es mit den Cycles. Nur weil der Angreifer jetzt weiß, das die Derivation-Function 321.574 mal durchläuft, füllen sich die Rainbow-Tables nicht mit Hashes, die auf diese Anzahl passen. Und wer jetzt bedenken wegen dem Salt und dem Bruteforcen hat. Für diesen Zweck benötigt man dann wieder die Derivation, die durch die Anzahl an Durchläufen für Bruteforcing völlig ineffektiv ist!

Durch die möglichst Hohe Auflösung des Passwortes zwischen 8 und 64 Zeichen oder noch mehr ist außerdem das Spektrum an möglichen Passwörtern gigantisch. Mit den ganzen Mittelchen ist die effektivste Angriffsart zweifelsfrei der Bruteforce direkt auf den Algorithmus. Und wie ich schon gesagt habe, kann man gegen diesen nichts ausrichten und bei 256³² Kombinationen für den Schlüssel und wenn gewünscht 10 unterschiedlichen Vektoren ist das vor allem bei einem großen Dokument verschwenkte Zeit. Die Mühe macht sich keiner.

PS: PBKDF2 für PureBasic gibt es:
Code: https://github.com/reVerBxTc/PBExpress/ ... ecurity.pb
Doku: https://github.com/reVerBxTc/PBExpress/ ... rity-Modul

Ist aber auch hier im Forum zu finden: http://www.purebasic.fr/german/viewtopi ... =8&t=29268
PC: Ryzen 9 3950X | 96 GB RAM | RX6800XT | 2,5 TB NVMe | Pop_OS!
Notebook: 16" 3:2 | Ryzen 7 5800H | 16 GB RAM | Radeon Vega | 1TB NVMe | Pop_OS!
NAS: Fritz.Box :lol:
Coding: Purebasic 6.04 | PHP | HTML | CSS | Javascript
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8679
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Mein Ver/Entschlüsseln - Eure Meinung

Beitrag von NicTheQuick »

@TroaX :allright:
Bild
BSP
Beiträge: 188
Registriert: 01.02.2009 14:04

Re: Mein Ver/Entschlüsseln - Eure Meinung

Beitrag von BSP »

Hallo Allerseits.
Danke für Eure bisherige und hoffentlich auch zukünftige Mühe.

Ich habe nun viel gelesen aber noch nicht viel verstanden.

Was haltet Ihr von folgenden Beispiel?
Eine "Matrix" und ein SHA3- Code sind in einer Datei vermerkt.
Wie leicht bekommt Ihr daraus das Passwort? Und warum?

Code: Alles auswählen

UseSHA3Fingerprint()

Procedure.s erzeuge_schluessel(passwort$, matrix$)
  For i = 1 To Len(passwort$)
    a1 = i
    a2 = i + 1
    If a2 > Len(passwort$) : a2 - Len(passwort$) : EndIf
    p = Asc(Mid(passwort$, a1, 1))
    w = Asc(Mid(passwort$, a2, 1))
    For j = p To p + w
      pw$ + Mid(matrix$, j, 1)
    Next
  Next
  ProcedureReturn pw$
EndProcedure

; --- Ein neues Passwort eingeben.
passw$ = "Passwort"
passwort$ = InputRequester("", "", passw$) ; Wird von Hand eingegeben, nur zu testen vorgegeben
; Die Matrix wird jedesmal neu erzeugt, wenn neues Passwort erzeugt wird.
For i = 1 To 512
  matrix$ + Hex(Random(15))
Next
Debug matrix$ ; Wird so auf Laufwerk gespeichert

pw$ = erzeuge_schluessel(passwort$, matrix$)
pw$ = erzeuge_schluessel(StringFingerprint(pw$, #PB_Cipher_SHA3, 512), matrix$)

Debug pw$
SHA3$ = StringFingerprint(pw$, #PB_Cipher_SHA3, 512)
Debug SHA3$ ; Wird so auf Laufwerk gespeichert

; --- Beim Programmstart
passwort$ = InputRequester("", "", passw$) ; Wird von Hand eingegeben, nur zu testen vorgegeben
pw$ = erzeuge_schluessel(passwort$, matrix$)
pw$ = erzeuge_schluessel(StringFingerprint(pw$, #PB_Cipher_SHA3, 512), matrix$)
If StringFingerprint(pw$, #PB_Cipher_SHA3, 512) = SHA3$
  Debug "Passwort Ok"
  ; Programm wird fortgeführt
Else
  Debug "Passwort Falsch"
  ; Programm wird abgebrochen
EndIf


PB 5.31 (x86) & (x64) Win10
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8679
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Mein Ver/Entschlüsseln - Eure Meinung

Beitrag von NicTheQuick »

Da hier SHA3 benutzt wird, kann ich nur Bruteforcen. Der Sinn der 'erzeuge_schluessel'-Funktion erschließt sich mir zwar nicht ganz, aber wenn man die etwas schneller gemacht hat, kann man die ins Bruteforcen miteinbeziehen.

Die 'erzeuge_schluessel'-Funktion erinnert mich an Security through Obscurity. Sie ist zwar nicht geheim, aber man versteht nicht, was sie tun soll und warum sie sicher ist. Es gibt keine Beweise dafür. Klar ist schon mal, dass die Matrix nicht komplett ausgenutzt wird und die Matrix vorher auch nicht mit einem kryptographisch sicheren Zufallsgenerator wie zum Beispiel 'CryptRandomData()' gefüllt wurde. Ich bin nicht ganz sicher, ob nicht sogar die Entropie des Passworts durch die Funktion herabgesetzt wird. Ich bin zu faul das nachzurechnen.

Da hier aber keine Runden gemacht werden, kann das Bruteforcen sehr schnell ablaufen und eventuell findet man dann ein richtiges Passwort. Es kommt also immer noch stark auf die Länge des Passworts an, ob Bruteforcen hier funktioniert oder nicht.
Bild
Antworten