Seriennummern generieren

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
Ostfrees80
User
Beiträge: 3
Registriert: Donnerstag 4. Juni 2020, 14:28

Hallo zusammen,
ich bin neu hier und ich versuche mich mal mit meinem Problemchen an euch zu wenden:
Es sollen Kundenkarten erstellt werden, welche eine 12 stellige Buchstaben Zahlen Kombination haben. Ich habe mal versucht was zu finden, was dem nahe kommt und bin auf diese Lösung zur Erstellung eines Passwortes von der Seite https://trainyourprogrammer.de gestoßen.

Code: Alles auswählen

import random, string
random.seed()
inhalt = ''
 
z = input("Laenge: ")
laenge = int(z)
klein = input("Kleinbuchstabe (j/n): ")
gross = input("Grossbuchstaben (j/n): ")
zahl = input("Zahlen (j/n): ")
zeichen = input("Sonderzeichen (j/n): ")
 
if klein == 'j':
    inhalt += string.ascii_lowercase
if gross == 'j':
    inhalt += string.ascii_uppercase
if zahl == 'j':
    inhalt += '0123456789'
if zeichen == 'j':
    inhalt += '''`~!@#$%^&*()_+-=][';}{":/.,<>?"}'''
 
pw = ''.join(random.choice(inhalt) for i in range(laenge))
print("Passwort:", pw)
Da ich aber nur ein Kombination aus Großbuchstaben und Zahlen benötige und der Code auch immer 12 Stellen haben soll, habe ich den Code schon auf 7 Zeilen runtergekürzt:

Code: Alles auswählen

import random, string
random.seed()
inhalt = ''
inhalt += string.ascii_uppercase
inhalt += '0123456789'
pw = ''.join(random.choice(inhalt) for i in range(12))
print("Passwort:", pw)
Nun generiert mir das Programm eine Kombination. Jetzt brauche ich aber Tausend Nummern und die dürfen auch keine Duplikate enthalten.
Ist meine Herangehensweise so richtig, oder gibt es eine elegantere Lösung?
Freue mich über euer Feedback
nezzcarth
User
Beiträge: 1634
Registriert: Samstag 16. April 2011, 12:47

Weshalb müssen die Zahlen denn zufällig sein? Einfacher wäre es doch nur hoch zu zählen. Entweder, indem du bei 10^11 anfängst, oder bei Eins und mit Nullen auffüllst. Wenn dir die Buchstaben A-F genügen, kannst du enfch Hexadezimalzahlen nehmen. Das sieht dann zum Beispiel so aus:

Code: Alles auswählen

In [1]: for i in range(16**11): 
   ...:     print('{:0>12x}'.format(i))                                                                                                                                                       
Daraus kann man dann auch recht einfach eine wiederverwendbare Funktion machen.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@nezzcarth: die Nummern von Kundenkarten sollten nicht einfach erratbar sein.

@Ostfrees80: das `random.seed` ist unnötig und bestenfalls verringert es den Zufall.
Für Zahlen gibt es string.digits, und mit einem leeren String hier zu starten ist unnötig.
`inhalt` ist ein komischer Name für eine Menge an Zeichen.
Wenn man mehrere Zufallszeichen, gibt es random.choices.
Bleibt also

Code: Alles auswählen

import random
import string

zeichen = string.ascii_uppercase + string.digits
kundennummer = ''.join(random.choices(zeichen, k=12))
Wenn man etwas mehrfach machen will, schreibt man eine Schleife. Wenn man keine Duplicate will, dann benutzt man ein Set:

Code: Alles auswählen

zeichen = string.ascii_uppercase + string.digits
kundennummern = set()
while len(kundennummern) < 1000:
    kundennummern.add(''.join(random.choices(zeichen, k=12)))
nezzcarth
User
Beiträge: 1634
Registriert: Samstag 16. April 2011, 12:47

Sirius3 hat geschrieben: Donnerstag 4. Juni 2020, 19:42 @nezzcarth: die Nummern von Kundenkarten sollten nicht einfach erratbar sein.
Ist das wirklich entscheindend? Man weiß ja nicht, wem die Karte zugeordnet wurde und kennt weitere sekundäre Merkmale wie Passwörter nicht. Das erscheint mir für viele Anwendungszwecke ausreichend. Aber ich sehe ein, dass Zufälligkeit das Brutforcen erschwert. :)
Benutzeravatar
__blackjack__
User
Beiträge: 13103
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Also ich würde da ja einen Zähler und Zufall kombinieren um a) das raten zu erschweren, aber b) auch einfach Kollisionen auszuschliessen ohne das man alle bisher erzeugten Nummern kennen muss.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

Code: Alles auswählen

zeichen = string.ascii_uppercase + string.digits
for nummer in range(1000):
    kundennummer = random.randrange(4738381338321)*10**6 + nummer
    print(''.join(zeichen[kundennummer//36**n % 36] for n in range(12)))
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

Besser ist es ganz ohne Zufall zufällig aussehende Kennungen zu generieren und zu verifizieren:

Code: Alles auswählen

import hashlib
import string

DIGITS = string.digits + string.ascii_uppercase
SECRET = b"GEHEIM%12d"
CODE_LENGTH = 12
MAX_CUSTOMERS = 10**6

def generate_customer_code(number):
    modulo = len(DIGITS) ** CODE_LENGTH // MAX_CUSTOMERS
    code = int.from_bytes(hashlib.sha256(SECRET % number).digest(), 'little') % modulo
    code = code * MAX_CUSTOMERS + number
    return ''.join(DIGITS[code//len(DIGITS)**n % len(DIGITS)] for n in range(CODE_LENGTH))

def get_customer_number(code):
    number = int(code[::-1], len(DIGITS)) % MAX_CUSTOMERS
    if generate_customer_code(number) != code:
        raise ValueError("invalid code")
    return number

for number in range(1000):
    print(generate_customer_code(number))
Ostfrees80
User
Beiträge: 3
Registriert: Donnerstag 4. Juni 2020, 14:28

Hallo zusammen,
vielen Dank für die Unterstützung. Auch wenn das genau das ist, was ich gesucht habe, komme ich leider nicht wirklich dahinter, was da jetzt genau gemacht wird. Ich will Dich @Sirius3 aber auch nicht mit noob Fragen belästigen. Ich werde dann mal versuchen den einzelnen Zeilen auf den Grund zu gehen und zu verstehen. :)
Die erste Funktion erstellt Codes mithilfe der Hashlib. Die zweite Funktion überprüft die erstellten Codes auf Duplikate. Nur Einzigartige Codes werden dann übergeben, bis 1000 erreicht sind. Soweit so gut.

Grüße
Ostfrees80
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Einzigartigkeit wird bei generate_customer_code schon durch die Kundennummer garantiert.
Aus der Nummer wird ein Hash gebildet, der zufällig aussieht, damit man Kundencodes nicht erraten kann.
Der Hash ist wiederum eine Zahl, dessen unteren 6 Ziffern die Kundennummer ist, damit der Code eindeutig wird.
Zum Schluß wird nur noch die Zahl in die Basis 36 (also Ziffern + Buchstaben) umgewandelt.

Die Funktion get_customer_number wandelt wiederum einen Code zurück in die Kundennummer.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1020
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Realität vs. Theorie

Wir generieren die Kundenummern fortlaufend und ERP-Systeme machen das auch so.
Hashwerte als Kundennummern sind mir auf Rechnungen noch nie untergekommen.
Das kann man theoretisch machen, in der Praxis habe ich das noch nirgendwo gesehen (bezogen auf Kundennummern).

Was kann denn jemand außenstehendes anhand einer Kundennummer erraten?
Wie viele Kunden hat ein Unternehmen und die Reihenfolge der Registrierung.
Was noch?
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Benutzeravatar
__blackjack__
User
Beiträge: 13103
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@DeaD_EyE: Es geht um Kunden*karten*. Und wenn man den Namen von demjenigen kennt der sich kurz vor- oder nach einem registriert hat, dann kann man so eine Karte fälschen. Karten werden ja üblicherweise dazu benutzt um sich ”auszuweisen”, beispielsweise um bestimmte Dienstleistungen in Anspruch zu nehmen. Oder man sagt man hat die Karte vergessen, weiss aber den Namen und die Nummer, und kann dann vielleicht trotzdem etwas auf Rechnung von jemand anderem machen. Blöd ist auch wenn man sich mit der Kundennummer irgendwo online anmelden kann wenn die leicht erratbar ist, weil sie dann dafür nicht mehr taugt.

Und auch bei Rechnungen kann das für das Unternehmen das die Rechnung ausstellt interessant sein, dass niemand (so leicht) aus der Nummer abschätzen kann wie lange ein Kunde schon Kunde ist oder eine Schätzung vornehmen kann wie viele Kunden das Unternehmen ungefähr hat.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

Bei Kundenkarten leuchtet die Kryptik ein, bei Kunden und Rechnungsnummern hilft in der Praxis oft ein einfacher Trick, der bereits zu Schreibmaschinenzeiten funktionierte: man läßt die Nummern einfach irgendwo im fünfstelligen Bereich beginnen, z.B. Kundenummer 11473 und zählt dann hoch. Das ist dann der Kunde Nr. 1, weiß aber keiner.
Ostfrees80
User
Beiträge: 3
Registriert: Donnerstag 4. Juni 2020, 14:28

Vielen Dank nochmal an alle. Es geht tatsächlich um Kundenkarten. Bei Kundennummern würde ich mir den Aufwand dann auch nicht machen.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@Ostfrees80: versteh ich nicht. Deine Anforderung war doch, eine 12-Stellige "Zufallsfolge" zu erstellen.
Antworten