Das secrets Modul in Python

Einführung

Python verfügt über ein built-in Modul namens secrets, mit dem sich kryptografisch starke Passwörter, Token und andere verwandte „geheime Daten“ erzeugen lassen? Das secrets-Modul wurde erstmals in Python 3.6 (PEP 506) eingeführt. 

Vor der Einführung des secrets-Moduls in Python wurde das random-Modul von den meisten Entwicklern zur Erzeugung von Passwörtern, Token usw. verwendet. Bei den vom random-Modul erzeugten Zufallszahlen handelt es sich jedoch um Pseudo-Zufallszahlen, die kryptografisch nicht sicher sind. Daher wurde das secrets-Modul ab Python 3.6 eingeführt.

Auf der offiziellen Dokumentationsseite des random-Mmoduls findet man die folgende Warnung – „Die Pseudo-Zufallsgeneratoren dieses Moduls sollten nicht für Sicherheitszwecke verwendet werden. Für Sicherheits- oder kryptografische Zwecke siehe das secrets-Modul.“

Secrets

Die Funktionen des secrets-Moduls können in zwei Abschnitte unterteilt werden – Generierung von Zufallszahlen und Generierung von Token.

Generierung von Zufallszahlen

1) secrets.choice(sequence) – gibt ein Zufallselement aus einer nicht leeren Sequenz zurück. Die beiden folgenden Beispiele geben ein zufälliges Zeichen aus der Reihe A-Za-z und eine Zufallszahl aus dem Bereich 0-10 zurück.

>>> secrets.choice(seq=string.ascii_letters)
'B'
>>> secrets.choice(seq=range(10))
2

2) secrets.randbelow(n) – liefert eine zufällige ganze Zahl im Bereich 0-n (außer n). Das folgende Beispiel gibt eine zufällige ganze Zahl im Bereich 0-10 zurück.

>>> secrets.randbelow(exclusive_upper_bound=10)
5

3) secrets.randbits(k) – liefert eine zufällige Ganzzahl mit k Bits. Das folgende Beispiel gibt eine zufällige Ganzzahl mit 8 Bits zurück.

Wenn k=4, dann wird die Zufallszahl von 0 bis 15 sein.
Wenn k=8, dann ist die zufällige Ganzzahl von 0 bis 255.
Wenn k=16, dann ist die Zufallszahl von 0 bis 65.535, und so weiter.

>>> secrets.randbits(k=8)
46

4) secrets.SystemRandom() – Jedes Betriebssystem verfügt über eine Quelle zur Erzeugung sicherer und starker Zufallszahlen. SystemRandom ist eine Klasse, die im Modul random verfügbar ist und die wiederum die Funktion os.urandom() zur Erzeugung sicherer Zufallszahlen verwendet.

Wie bereits erwähnt, wurde vor der Einführung des secrets-Moduls die Klasse SystemRandom verwendet, um sichere und kryptografisch starke Zufallszahlen/Tokens zu erzeugen. Tatsächlich kann man auf alle Funktionen/Methoden des random-Moduls über das SystemRandom-Objekt zugreifen. 

Wie man aus dem unten stehenden Code ersehen kann, kann man mit der Klasse SystemRandom auf die Funktionen des random-Moduls zugreifen. Man kann auch andere im Modul verfügbare Funktionen/Methoden ausprobieren.

>>> import secrets
>>> sys_random = secrets.SystemRandom()
>>> sys_random.choice(seq=range(10))
6
>>> sys_random.getrandbits(k=8)
88
>>> sys_random.randrange(1, 100)
45
>>> sys_random.sample(range(100), 5)
[85, 73, 31, 88, 48]

Generierung von Token

Das secrets-Modul bietet auch Funktionen, die für Anwendungen wie das Zurücksetzen von Passwörtern, schwer zu erratende URLs usw. verwendet werden können, wie im Folgenden beschrieben.

1) secrets.token_bytes(nbytes) – gibt sichere zufällige Byte-Strings mit den im Parameter nbytes angegebenen Bytes zurück. Wenn nbytes „None“ ist oder nicht angegeben wird, wird ein vernünftiger Standardwert verwendet.

Die folgenden Beispiele geben 8 und 16 Token-Bytes wie im Parameter angegeben zurück.

>>> secrets.token_bytes(8)
b'>k\t\xbcO\x8dg\xd6'
>>> secrets.token_bytes(16)
b'\xe81\xedT\xfcOP\xe9\x9e\x87\xa4\xec\xa0\xffH9'

2) secrets.token_hex(nbytes) – liefert sichere zufällige Byte-Strings im Hexadezimalformat mit den im Parameter nbytes angegebenen Bytes. Ist nbytes gleich Null oder nicht angegeben, wird ein vernünftiger Standardwert verwendet.

Die folgenden Beispiele geben 8 und 16 Token-Bytes im Hexadezimalformat zurück, wie im Parameter angegeben.

>>> secrets.token_hex(8)
'796d446a4dcbe000'
>>> secrets.token_hex(16)
'6e8b324b58f0d94d5f6440b90c59d350'

3) secrets.token_urlsafe(nbytes) – gibt eine sichere zufällige URL-sichere Textzeichenfolge mit den im Parameter nbytes angegebenen Bytes zurück.

Die folgenden Beispiele geben 8 und 16 Bytes zurück, wie im Parameter angegeben.

>>> secrets.token_urlsafe(8)
'GLyhe4JD72g'
>>> secrets.token_urlsafe(16)
'kJkUOJIUZRAYkEgFR6X52w'

Beispiele

Mit dem Wissen, das wir aus den oben genannten Funktionen gewonnen haben, können wir nun kryptografisch starke Passwörter, OTP, Token usw. erstellen. Schauen wir uns ein paar Anwendungsfälle an.

(1) Erzeugen eines 8-stelligen alphanumerischen Passworts

>>> import string
>>> import secrets
>>> alphabet = string.ascii_letters + string.digits
>>> password = ''.join(secrets.choice(alphabet) for i in range(8))
>>> password
'ubHLOZY1'

(2) Erzeugen eines 6-stelligen numerischen OTP (OTP = one-time password / Passcode / PIN)

>>> import string
>>> import secrets
>>> numbers = string.digits
>>> OTP = ''.join(secrets.choice(numbers) for i in range(8))
>>> OTP
'904447'

(3) Erzeugen eines 10-stelliges Passwort mit mindestens einem Großbuchstaben, einem Kleinbuchstaben, einer Ziffer, einem Sonderzeichen und mindestens 5 Buchstaben.

>>> import string
>>> import secrets
>>> alphabet = string.ascii_letters + string.digits + string.punctuation
>>> while True:
... password = ''.join(secrets.choice(alphabet) for i in range(10))
... if (any(c.islower() for c in password)
... and any(c.isupper() for c in password)
... and any(c.islower() for c in password)
... and any(c.isdigit() for c in password)
... and any(c in string.punctuation for c in password)
... and sum(c.isalpha() for c in password) >= 5):
... break
>>> password
"hMyo>'A5<="

(4) Erzeugen eines temporären sicheren URL-Token zum Zurücksetzen des Passworts

Angenommen, man hat das Passwort für eine Website vergessen. Wenn man eine Passwortrücksetzung anfordert, erhält man nach der Authentifizierung mit der Benutzerkennung, der E-Mail-ID oder anderen Authentifizierungsmethoden eine sichere URL für die Passwortrücksetzung. Nachfolgend findet man einen Beispielcode für die Verwendung von token_urlsafe().

>>> print("Password Reset link:")
>>> SecureURL = "https://mysite.com/user/chetanambi/passwordreset="
>>> SecureURL += secrets.token_urlsafe(32)
>>> print(SecureURL)

Password Reset link:
https://mysite.com/user/chetanambi/passwordreset=urtFK4CeJvJ0f7nVbPAAZw

PRNG vs. CSPRNG

PRNG steht für Pseudo-Random Number Generator und CSPRNG bedeutet Cryptographically Strong Pseudo-Random Number Generator.

Die von einer Software erzeugten Zufallszahlen sind von Natur aus pseudozufällig, da sie aus einer bestimmten Verteilung stammen und vorhergesagt werden können, wenn der Seed bekannt ist. Echte Zufallszahlen hingegen verwenden eine externe Quelle, die nicht vorhersagbar ist, um Zufallszahlen zu erzeugen. Der CSPRNG in Python ist ein echter Zufallszahlengenerator, da er das Betriebssystem als Quelle für den Zufallszahlengenerator verwendet.

Schlussfolgerung

In diesem Artikel haben wir eine Einführung in das Python-Modul secrets erhalten. Das secrets-Modul wird verwendet, um kryptographisch starke und sichere Passwörter, OTPs, Token und andere verwandte „geheime Daten“ zu erzeugen. Das Modul random in Python kann ebenfalls zur Erzeugung von Zufallszahlen verwendet werden, ist aber nicht sicher!