Verbesserungsvorschläge für Hashüberprüfung

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Chr0medome
User
Beiträge: 30
Registriert: Freitag 20. Juli 2018, 15:39

Tagchen zusammen.

Ich habe jetzt ein neues Programm geschrieben, das sich mit Hashes beschäftigt.
Es beinhaltet 2 Funktionen:
Eine Funktion mit der man einen String mit md5 in den Hash umwandelt und außerdem eine Funktion, die 2 Hashwerte überprüft. Dabei kann unter anderem ein extra Dictionary verwendet werden, das aus Strings besteht, eine Liste, die mehrere Strings beinhaltet und auch die Eingabe von Zusatzzeichen, die an den String angehängt werden können, ist möglich.
Da ich gerne so optimiert wie möglich programmieren will, ist meine erste Frage, ob jemandem entweder Fehler auffallen oder es generelle Verbesserungsvorschläge gibt. Meine zweite Frage ist, wie ich es schaffen kann, das man bei der Funktion check_hash_md5() beispielsweise eine andere krypto Hashfunktion verwenden kann (ohne if,else), welche man vorher als variable übergibt?
So zum Beispiel:

Code: Alles auswählen

import hashlib
def check_hash(dictionary, my_hash, kryp_func):
	hash = hashlib.krypfunc(...)	
Mein Code:

Code: Alles auswählen

import hashlib
import os

def create_hash_md5(plaintext):
    hashed = hashlib.md5(plaintext.encode()).hexdigest()
    print(hashed)

def check_hash_md5(my_hash, dat = None, dic = None, extra_char = None,
                   extra_char_ammount = None):
    if dat and not dic:
        with open (dat, "r") as dic_file:
            for line in dic_file:
                if extra_char:
                    for char in extra_char:
                        current_element = line.strip() + char
                        hashed_element = hashlib.md5(current_element.encode()).hexdigest()
                        if hashed_element == my_hash:
                            print("Plaintext found:", current_element, "\n" + hashed_element)
                            os._exit(1)
                        else:
                            continue
                else:
                    current_element = hashlib.md5(line.strip().encode()).hexdigest()
                    if current_element == my_hash:
                        print("Plaintext found:", line.strip(), "\n" + current_element)
                        os._exit(1)
                    else:
                        continue
            print("Operation stopped")
                
    elif not dat and dic:
        for item in dic:
            hashed = hashlib.md5(item.strip().encode()).hexdigest()
            if hashed == my_hash:
                print("Plaintext found:", item, "\n" + hashed)
                os._exit(1)
            else:
                continue
        print("Operation stopped")
    else:
        return False

        
my_hash = "64170b387fb14dbfef2a1f85e7726bab" #create_hash_md5("piggishly!")
check_hash_md5(my_hash, "dictionary.txt", None, ["!", "?", ",", ".", "#", ":", ";"])
Vielen Dank im voraus!
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

`sys.exit()` hätte da schon nichts zu suchen gehabt aber `os._exit()` schon mal überhaupt gar nicht. `create_hash_md5()` gibt etwas aus statt zurück und `check_hash_md5()` gibt mal was aus oder bricht das Programm ab, macht eindeutig zu viele verschiedene Dinge, und die auch recht komisch.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Chr0medome: Bei `check_hash_md5()` wird das `extra_char_ammount`-Argument überhaupt nicht verwendet.

Die ``else: continue``-Zweige sind jeweils Überflüssig.

Beim Programmabbruch mit Rückgabecode ist die 1 IMHO komisch, denn das bedeutet ja es hat etwas *nicht* funktioniert.

Der Rückgabewert der Funktion, falls das Programm nicht durch sie abgebrochen wird, ist entweder `None` oder `False`, wobei die `None`\s implizit sind, was unschön ist, weil man nicht weiss ob das Absicht ist oder einfach nur nicht zuende gedacht. Zumal man von einer Funktion die `False` zurückgeben kann, eigentlich auch erwartet das es Fälle gibt in denen `True` zurückgegeben wird. Gerade auch bei dem Funktionsnamen.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Chr0medome
User
Beiträge: 30
Registriert: Freitag 20. Juli 2018, 15:39

__blackjack__ hat geschrieben: Dienstag 14. August 2018, 20:24 `sys.exit()` hätte da schon nichts zu suchen gehabt aber `os._exit()` schon mal überhaupt gar nicht. `create_hash_md5()` gibt etwas aus statt zurück und `check_hash_md5()` gibt mal was aus oder bricht das Programm ab, macht eindeutig zu viele verschiedene Dinge, und die auch recht komisch.
Wie würdest du es denn lösen, dass das gesamte Programm dann abbricht? Durch break wird doch nur die aktuelle Schleife beendet.
Das mit dem "zurückgeben" hast du bereits schon einmal kritisiert jedoch funktioniert return ... nicht warum auch immer?
Und bei mir funktioniert es einwandfrei... vermutlich funktioniert es bei dir nicht, da du nicht die dictionary.txt hast?
Chr0medome
User
Beiträge: 30
Registriert: Freitag 20. Juli 2018, 15:39

__blackjack__ hat geschrieben: Dienstag 14. August 2018, 20:46 @Chr0medome: Bei `check_hash_md5()` wird das `extra_char_ammount`-Argument überhaupt nicht verwendet.

Die ``else: continue``-Zweige sind jeweils Überflüssig.

Beim Programmabbruch mit Rückgabecode ist die 1 IMHO komisch, denn das bedeutet ja es hat etwas *nicht* funktioniert.

Der Rückgabewert der Funktion, falls das Programm nicht durch sie abgebrochen wird, ist entweder `None` oder `False`, wobei die `None`\s implizit sind, was unschön ist, weil man nicht weiss ob das Absicht ist oder einfach nur nicht zuende gedacht. Zumal man von einer Funktion die `False` zurückgeben kann, eigentlich auch erwartet das es Fälle gibt in denen `True` zurückgegeben wird. Gerade auch bei dem Funktionsnamen.
"extra_char_ammount" hab ich noch nicht eingefügt.
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Chr0medome: Ich würde das so lösen das eine normale Funktion nicht das ganze Programm abbrechen kann. Das ist keine sinnvolles Verhalten für eine Funktion. Und ``return`` funktioniert.

Ich habe das gar nicht laufen lassen. Es geht nicht darum ob das läuft oder nicht, sondern das das keine sinnvoller Code ist.

Re `extra_char_ammount`: Das heisst die Funktion soll *noch* mehr unterschiedliche Dinge tun‽ Die tut doch jetzt schon zu viel.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Chr0medome
User
Beiträge: 30
Registriert: Freitag 20. Juli 2018, 15:39

Wie siehts damit aus?

Code: Alles auswählen

import hashlib

def create_hash(plaintext): #using md5 (without spaces and empty lines)
    hashed = hashlib.md5(plaintext.strip().encode()).hexdigest() #creating hash
    return hashed

def compare_hashes(dic, hash_): #using a dictionary .txt data with strings(without extra characters)
    hash_ = create_hash(hash_) #calling function to create hash of the string
    with open(dic, "r") as dic: 
        for line in dic:
            current_element = create_hash(line)
            if current_element == hash_:
                return "Plaintext found:", line.strip(), "\n" + hash_
        print("Operation stopped")

def compare_hashes_extra_chars(dic, hash_, extra_chars): #using additional characters
    hash_ = create_hash(hash_) #calling function to create hash of the string
    with open(dic, "r") as dic: 
        for line in dic:
            for char in extra_chars:
                line = line.strip() + char
                current_element = create_hash(line) 
                if current_element == hash_:
                    return "Plaintext found:", line.strip(), "\n" + hash_
        print("Operation stopped")

compare_hashes_extra_chars("dictionary.txt", "piggishly!"
                           , ["!", "?", ",", ".", "#", ":", ";"])
compare_hashes("dictionary.txt", "piggishly")
Zuletzt geändert von Chr0medome am Dienstag 14. August 2018, 22:02, insgesamt 1-mal geändert.
Chr0medome
User
Beiträge: 30
Registriert: Freitag 20. Juli 2018, 15:39

Chr0medome hat geschrieben: Dienstag 14. August 2018, 20:11 Meine zweite Frage ist, wie ich es schaffen kann, das man bei der Funktion check_hash_md5() beispielsweise eine andere krypto Hashfunktion verwenden kann (ohne if,else), welche man vorher als variable übergibt?
So zum Beispiel:

Code: Alles auswählen

import hashlib
def check_hash(dictionary, my_hash, kryp_func):
	hash = hashlib.krypfunc(...)	
Dazu eine Idee?
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Chr0medome: Nun sind sich die beiden `compare_*()`-Funktionen so ähnlich, das man da problemlos eine draus machen kann um den fast identischen Code nicht zweimal im Programm haben zu müssen.

Die Rückgabewerte sind immer noch ziemlich schräg und unpassend. Entweder ein implizites `None` oder ein Tupel mit drei Zeichenketten. Das macht keinen Sinn. Wenn es in einer Funktion ein ``return`` gibt, dann erwartet man das alle Wege durch die Funktion entweder explizit etwas zurückgeben oder eine Ausnahme auslösen.

`dic` an sich ist schon kein guter Name, aber den einmal für den Dateinamen und gleich darauf für das Dateiobjekt selbst zu verwenden ist sehr verwirrend.

Zur zweiten Frage: Mach die Hash-Funktion zum Argument. Die haben ja alle die gleiche API. Genau damit man das machen kann.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Chr0medome
User
Beiträge: 30
Registriert: Freitag 20. Juli 2018, 15:39

also eher so??

Code: Alles auswählen

import hashlib

def create_hash(plaintext): 
    hashed = hashlib.md5(plaintext.strip().encode()).hexdigest() 
    return hashed

def compare_hashes(pw_file, hash_, extra_chars = None): 
    hash_ = create_hash(hash_)
    with open(pw_file, "r") as file: 
        for line in file:
            if not extra_chars:
                current_element = create_hash(line)
                if current_element == hash_:
                    print("Plaintext found:", line.strip(), "\n" + hash_)
                    break
                else:
                    print("Comparing...", line.strip(), ":" + current_element, "unequal to", hash_)
            else:
                for char in extra_chars:
                    current_element = create_hash(line.strip() + char) 
                    if current_element == hash_:
                        print("Plaintext found:", line.strip() + char, "\n" + hash_)
                        break
                    else:
                        print("Comparing...", line.strip() + char, ":" + current_element, "unequal to", hash_)
        print("Operation stopped")

compare_hashes("dictionary.txt", "2nd!", ["!", "?", ",", ".", "#", ":", ";"])
__blackjack__ hat geschrieben: Dienstag 14. August 2018, 22:11 Zur zweiten Frage: Mach die Hash-Funktion zum Argument. Die haben ja alle die gleiche API. Genau damit man das machen kann.
Perfekt danke!
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Warum benutzt Du einmal `line` und sonst immer `line.strip()`? Ansonsten steht im if-Block das quasi das selbe wie im else-Block, so dass man die zwei zusammenfassen kann.
Chr0medome
User
Beiträge: 30
Registriert: Freitag 20. Juli 2018, 15:39

Sirius3 hat geschrieben: Mittwoch 15. August 2018, 21:43 Ansonsten steht im if-Block das quasi das selbe wie im else-Block, so dass man die zwei zusammenfassen kann.
Wie genau sollte ich das denn zusammenfassen? Irgendwelche Vorschläge?
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Welchen Wert muß `char` haben, damit es das identische Ergebnis zum if-Block liefert?
Chr0medome
User
Beiträge: 30
Registriert: Freitag 20. Juli 2018, 15:39

Ahhhhh! Perfekt danke!
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Zur Vollständigkeit:

Code: Alles auswählen

from itertools import product
def compare_hashes(pw_file, hash_, extra_chars = ('',)): 
    hash_ = create_hash(hash_)
    with open(pw_file) as lines: 
        for line, char in product(lines, extra_chars):
            plaintext = line.strip() + char
            current_element = create_hash(plaintext) 
            if current_element == hash_:
                print("Plaintext found:", lplaintext)
                print(hash_)
                break
            else:
                print("Comparing {}: {} unequal to {}".format(
                    plaintext, current_element, hash_)
    print("Operation stopped")
Warum wird eigentlich `hash_` nochmal gehasht?
Chr0medome
User
Beiträge: 30
Registriert: Freitag 20. Juli 2018, 15:39

Sirius3 hat geschrieben: Sonntag 19. August 2018, 21:01 Warum wird eigentlich `hash_` nochmal gehasht?
Das hab ich nur als Übung eingebaut, weil ich zu faul war, jedes mal manuell einen neuen hash zu generieren und den dann zu übergeben.. Somit hab ich die Möglichkeit einen Klartext einzugeben, der noch nicht gehasht wurde, um den dann von "create_hash" hashen zu lassen.

Hab noch eine Frage zu deinem Code:

Code: Alles auswählen

def compare_hashes(pw_file, hash_, extra_chars = ('',)):
Ich verstehe den Ausdruck für "extra_chars" nicht so wirklich?
Bzw. welche Eingaben sind jetzt noch möglich?

Und hast du gegebenenfalls irgendein Tutorial über verschachtelte for-schleifen, so wie du das angewendet hast?
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

1) Was verstehst Du an ›extra_chars‹ nicht? Wenn ›extra_chars‹ beim Aufruf nicht angegeben wird, sollen keine Zeichen (also leere Zeichenkette) angefügt werden.

2) Du kannst Dir ja mal die Dokumentation zu itertools durchlesen, da gibt es viele interessante Funktionen.
Antworten