Wie zufällige Hashes erzeugen?

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.
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Mittwoch 31. Oktober 2007, 15:02

Ich suche einen Weg, eindeutige Zufallshashes zu erzeugen, die ich z.B. in Webanwendungen anstelle von numerischen, fortlaufenden IDs nutzen kann.

Mit den bekannten und weniger bekannten Hash-Algorithmen benötige ich ja einen Ausgangswert, der gehasht wird - auf den möchte ich aber verzichten können.

Gibt es eine Methode, die Zufallsnamen (nicht Dateinamen) erzeugt?
Benutzeravatar
lutz.horn
User
Beiträge: 205
Registriert: Dienstag 8. November 2005, 12:57
Wohnort: Pforzheim

Mittwoch 31. Oktober 2007, 15:13

Du kannts z. B. mit http://pypi.python.org/pypi/uuid/ UUIDs erzeugen und diese dann nach Wunsch verwenden.
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Mittwoch 31. Oktober 2007, 15:32

MD5 oder SHA1 berechnen lassen, z.B. so:
http://code.djangoproject.com/browser/d ... els.py#L21

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Mittwoch 31. Oktober 2007, 15:50

Was spricht dagegen, als Seed für die Hashfunktion `time.time()` zu verwenden? Ist zwar nicht kryptografisch sicher aber ich glaube das willst du auch nicht, oder?
My god, it's full of CARs! | Leonidasvoice vs Modvoice
rafael
User
Beiträge: 189
Registriert: Mittwoch 26. Juli 2006, 16:13

Mittwoch 31. Oktober 2007, 16:10

Wie wäre es mit sowas wie hier?
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Mittwoch 31. Oktober 2007, 19:41

lutz.horn hat geschrieben:Du kannts z. B. mit http://pypi.python.org/pypi/uuid/ UUIDs erzeugen und diese dann nach Wunsch verwenden.
Danke, `uuid` hatte ich vergessen. Das sieht soweit (s.u.) gut aus.

Leonidas hat geschrieben:Was spricht dagegen, als Seed für die Hashfunktion `time.time()` zu verwenden? Ist zwar nicht kryptografisch sicher aber ich glaube das willst du auch nicht, oder?
Es geht mir dabei nicht um Kryptografie, sondern darum, (weitgehend) eindeutige Ergebnisse zu erhalten. Wenn ich den Timestamp verwende, so dachte ich, erhalte ich bei theoretisch möglichen mehreren parallelen Zugriffen ja identische Hashes (da ich ja sonst keinen Wert habe, den ich in den Hash mit einbeziehen kann). Jedoch habe ich außer acht gelassen, dass `time.time()` eine Fließkommazahl liefert, bei der Kollisionen durch parallele Aufrufe (die entsprechend so einen eindeutigen Hash erfordern) in einer Webanwendung praktisch fast auszuschließen sind.

So gesehen ist dieser Ansatz möglich, entsprechend sind auch die beiden von jens und rafael genannten Lösungen denkbar.

Zwar kommen nun doch mehrere Wege, eindeutige Hashes (nicht zwangsweise Hashes, aber ich bleibe mal bei dieser Bezeichnung) zu erzeugen, in Frage. Jedoch scheint auch keiner davon die Einschränkung der Ergebnislänge zu erlauben...

...denn es gibt eine weitere Einschränkung, die ich... ääh... erst jetzt nenne, damit es spannend bleibt ;): Ich möchte vorzugsweise relativ kurze eindeutige Werte erhalten, wie ich sie etwa von Blogger für hochgeladene Bilder und von Jottit (cool!) für Wikiseiten ohne zugewiesene Subdomain kenne. Diese haben teilweise schätzungsweise um die 6-9 Zeichen Länge und verwenden nicht nur hexadezimale Zeichen, sondern bedienen sich Zahlen und unseres Alphabets sowie auch der Unterscheidung von Groß-/Kleinbuchstaben. Letzteres ist mir nicht unbedingt wichtig, aber die erhöhte Zahl von möglichen Zeichen erlaubt es natürlich, in geringerer Stringlänge mehr Variationen zuzulassen. Einen Algorithmus, der mir dieses bietet, suche ich. Muss da wohl doch was eigenes her?
BlackJack

Mittwoch 31. Oktober 2007, 20:04

Wenn es möglichst kurz und eindeutig sein soll, würde sich dann nicht ein fortlaufender Zähler zur Basis 46 anbieten? Also Buchstaben und Dezimaliffern als "Ziffern"? Vielleicht auch Gross- und Kleinschreibung. Und für die "user friendliness" sollte man einige Zeichen rausnehmen bzw. synonym verwenden können, also 0 und O oder 1 und l zum Beispiel. Der Nutzer sollte beides eingeben dürfen, damit man auch URLs eingeben kann, die mal jemand auf ein Blatt Papier gekritzelt hat und man nicht mehr so recht weiss ob das nun eine Null oder ein grosses O war.
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Donnerstag 1. November 2007, 11:17

Ich habe einfach einen simplen Passwort-Generator für Short-URLs verwendet. Zugegeben, sind nicht allzu schön.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Donnerstag 1. November 2007, 14:07

BlackJack hat geschrieben:Wenn es möglichst kurz und eindeutig sein soll, würde sich dann nicht ein fortlaufender Zähler zur Basis 46 anbieten? Also Buchstaben und Dezimaliffern als "Ziffern"? Vielleicht auch Gross- und Kleinschreibung.
Gerade etwas fortlaufendes möchte ich nicht. Denn genau dann ist es ja wieder möglich, weitere IDs zu erraten, das soll vermieden werden. Auch soll kein z.B. chronologischer Zusammenhang durch in-Reihenfolge-setzen ermittelbar sein.
Oder verstehe ich deinen Ansatz da vielleicht nicht richtig?
BlackJack hat geschrieben:Und für die "user friendliness" sollte man einige Zeichen rausnehmen bzw. synonym verwenden können, also 0 und O oder 1 und l zum Beispiel. Der Nutzer sollte beides eingeben dürfen, damit man auch URLs eingeben kann, die mal jemand auf ein Blatt Papier gekritzelt hat und man nicht mehr so recht weiss ob das nun eine Null oder ein grosses O war.
User-friendly muss es nicht sein, der Benutzer soll die Namen nicht von Hand eingeben oder dergleichen.

Leonidas hat geschrieben:Ich habe einfach einen simplen Passwort-Generator für Short-URLs verwendet. Zugegeben, sind nicht allzu schön.
Doch, ziemlich genau sowas schwebt mir vor!

Wie erstellst du diese? Es ist ja schön und gut, wenn man Hashes über MD5, SHA* und Konsorten erstellen kann, aber wenn man davon nur die ersten z.B. acht Zeichen verwendet, ist es mit der Eindeutigkeit relativ schnell geschehen.
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Donnerstag 1. November 2007, 15:06

Y0Gi hat geschrieben:
Leonidas hat geschrieben:Ich habe einfach einen simplen Passwort-Generator für Short-URLs verwendet. Zugegeben, sind nicht allzu schön.
Doch, ziemlich genau sowas schwebt mir vor!

Wie erstellst du diese? Es ist ja schön und gut, wenn man Hashes über MD5, SHA* und Konsorten erstellen kann, aber wenn man davon nur die ersten z.B. acht Zeichen verwendet, ist es mit der Eindeutigkeit relativ schnell geschehen.
Habe mich mal auf den alten Server verbunden (Last login: Fri Jun 1 18:14:00 2007 :oops:), und nachgeschaut:

Code: Alles auswählen

import string
def gen_short(length=8, chars=string.letters + string.digits):
    """Generator for random, short sequences.
    Modified from a password generator in the Python Cookbook
    http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/59873"""
    return ''.join(random.choice(chars) for i in range(length))
Wobei du die von BlackJack vorgeschlagenen Änderungen, wie etwa das Entfernen von 0, O, l, 1, I ganz einfach dort implementieren kannst.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Freitag 2. November 2007, 08:08

Wenn es eh eine fortlaufende Nummer gibt, warum dann nicht die mit time.time() kombinieren und daraus eine MD5 oder SHA1 bilden? Die dürfte auch dann eindeutig sein, wenn zwei User gleichzeitig eine ID bekommen ;)

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Freitag 2. November 2007, 11:51

Leonidas: OK, das ist jetzt wirklich ein simpler Ansatz :) Der beinhaltet ja leider nicht die von Hashverfahren annehmbaren großen Unwahrscheinlichkeiten von Kollisionen, aber selbst da wäre eine Prüfung auf einen bereits vorhandenen Wert keine schlechte Idee. Dann werde ich es wohl so lösen und habe da den Baum vor lauter Wäldern nicht gesehen.

jens hat geschrieben:Wenn es eh eine fortlaufende Nummer gibt, warum dann nicht die mit time.time() kombinieren und daraus eine MD5 oder SHA1 bilden? Die dürfte auch dann eindeutig sein, wenn zwei User gleichzeitig eine ID bekommen ;)
Wer sagt, dass es eine fortlaufende Nummer gibt? Ich habe doch mindestens einmal geschrieben, dass dem nicht so ist/sein sollte?
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Freitag 2. November 2007, 12:13

Hallo YOgi!

lutz.horn hat es in diesem Beitrag http://www.python-forum.de/post-81208.html#81208 schon geschrieben. UUIDs oder GUIDs sind genau für deinen Zweck gemacht. Nur musst du dafür auch die volle Länge des erzeugten GUIDs verwenden. GUIDs sind eindeutig und die Wahrscheinlichkeit, dass jemand den gleichen GUID erzeugt, ist unendlich gering.

Mit dem Python-Modul ``uuid.py`` kannst du solche global eindeutige IDs erstellen. Unter Windows könntest du über pywin32 direkt auf ``CreateGuid`` zugreifen. Aber besser du verwendest ``uuid.py`` dafür.

Code: Alles auswählen

>>> import pythoncom
>>> pythoncom.CreateGuid()
IID('{973778F6-CB65-421F-B5E6-96D95677657C}')
>>> 
Diese so erstellten UUIDs brauchst du nicht mehr auf Eindeutigkeit prüfen. So können z.B. Daten von vielen Computern in einer Datenbank gesammelt werden, ohne dass es ID-Kollissionen gibt.

Aber wie schon geschrieben. Du musst dafür die gesamte erzeugte UUID verwenden. --> "973778F6-CB65-421F-B5E6-96D95677657C"

mfg
Gerold
:-)

EDIT:

Wie ich soeben sehe, ist das Modul ``uuid`` seit Python 2.5 sogar ein mit Python ausgeliefertes Standardmodul.

--> http://docs.python.org/lib/module-uuid.html
[url]http://halvar.at[/url] | [url=http://halvar.at/elektronik/kleiner_bascom_avr_kurs/]Kleiner Bascom AVR Kurs[/url]
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Freitag 2. November 2007, 12:25

Y0Gi hat geschrieben:Leonidas: OK, das ist jetzt wirklich ein simpler Ansatz :) Der beinhaltet ja leider nicht die von Hashverfahren annehmbaren großen Unwahrscheinlichkeiten von Kollisionen, aber selbst da wäre eine Prüfung auf einen bereits vorhandenen Wert keine schlechte Idee. Dann werde ich es wohl so lösen und habe da den Baum vor lauter Wäldern nicht gesehen.
Stimmt, ob das "Passwort" verwendet wird, musst du natürlich selbst prüfen. Jede Lösung hat ihre Vor und Nachteile, diese eben die relative "Lesbarkeit", und Einfachkeit aber auch ihre geringe Sicherheit.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Freitag 2. November 2007, 12:35

Hallo!

Zu diesem Thema passend: PostgreSQL wird ab Version 8.3 den Datentyp UUID besitzen. Damit kann eine UUID endlich auch unter PostgreSQL platzsparend (16 Byte) und indiziiert gespeichert werden. Es soll auch eine Funktion zum automatischen Erstellen von UUIDs mit dazu kommen. So lässt sich eine UUID endlich auch unter PostgreSQL als Primärschlüssel einsetzen, ohne auf den TEXT-Datentyp ausweichen zu müssen.

lg
Gerold
:-)
[url]http://halvar.at[/url] | [url=http://halvar.at/elektronik/kleiner_bascom_avr_kurs/]Kleiner Bascom AVR Kurs[/url]
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Antworten