Suche…


Einführung

Python ist eine der beliebtesten Sprachen in der Computer- und Netzwerksicherheit und hat ein großes Potenzial in Sicherheit und Kryptographie. Dieses Thema behandelt die kryptografischen Funktionen und Implementierungen in Python von der Verwendung in der Computer- und Netzwerksicherheit bis hin zu Hash- und Verschlüsselungs- / Entschlüsselungsalgorithmen.

Syntax

  • hashlib.new (name)
  • hashlib.pbkdf2_hmac (Name, Passwort, Salt, Runden, Dklen = Keine)

Bemerkungen

Bei vielen der Methoden in hashlib müssen Sie Werte übergeben, die als Puffer von Bytes und nicht als Zeichenfolgen interpretierbar sind. Dies ist der Fall für hashlib.new().update() sowie hashlib.pbkdf2_hmac . Wenn Sie eine Zeichenfolge haben, können Sie sie in einen Bytepuffer konvertieren, indem Sie das Zeichen b vor den Anfang der Zeichenfolge setzen:

  "This is a string"
 b"This is a buffer of bytes"

Berechnen eines Message-Digest

Das hashlib Modul ermöglicht das Erstellen von Message Digest-Generatoren mit der new Methode. Diese Generatoren verwandeln einen beliebigen String in einen Digest mit fester Länge:

import hashlib

h = hashlib.new('sha256')
h.update(b'Nobody expects the Spanish Inquisition.')
h.digest()
# ==> b'.\xdf\xda\xdaVR[\x12\x90\xff\x16\xfb\x17D\xcf\xb4\x82\xdd)\x14\xff\xbc\xb6Iy\x0c\x0eX\x9eF-='

Beachten Sie, dass Sie eine beliebige Anzahl von update aufrufen können, bevor Sie digest aufrufen. digest ist nützlich, wenn Sie einen großen Datei-Chunk von Chunk durchgehen möchten. Sie können den Digest auch im Hexadezimalformat hexdigest indem Sie hexdigest :

h.hexdigest()
# ==> '2edfdada56525b1290ff16fb1744cfb482dd2914ffbcb649790c0e589e462d3d'

Verfügbare Hash-Algorithmen

hashlib.new erfordert den Namen eines Algorithmus, wenn Sie ihn zur Erzeugung eines Generators aufrufen. Um herauszufinden, welche Algorithmen im aktuellen Python-Interpreter verfügbar sind, verwenden Sie hashlib.algorithms_available :

import hashlib
hashlib.algorithms_available
# ==> {'sha256', 'DSA-SHA', 'SHA512', 'SHA224', 'dsaWithSHA', 'SHA', 'RIPEMD160', 'ecdsa-with-SHA1', 'sha1', 'SHA384', 'md5', 'SHA1', 'MD5', 'MD4', 'SHA256', 'sha384', 'md4', 'ripemd160', 'sha224', 'sha512', 'DSA', 'dsaEncryption', 'sha', 'whirlpool'}

Die zurückgegebene Liste variiert je nach Plattform und Interpret. Stellen Sie sicher, dass Ihr Algorithmus verfügbar ist.

Es gibt auch einige Algorithmen , die auf allen Plattformen und Dolmetscher zur Verfügung stehen sind garantiert, die unter Verwendung verfügbar sind hashlib.algorithms_guaranteed :

hashlib.algorithms_guaranteed
# ==> {'sha256', 'sha384', 'sha1', 'sha224', 'md5', 'sha512'}

Sicheres Passwort-Hashing

Der vom hashlib Modul hashlib PBKDF2-Algorithmus kann verwendet werden, um sicheres Passwort-Hashing durchzuführen. Dieser Algorithmus kann zwar keine Brute-Force-Angriffe verhindern, um das ursprüngliche Kennwort aus dem gespeicherten Hash wiederherzustellen, macht jedoch solche Angriffe sehr teuer.

import hashlib
import os

salt = os.urandom(16)
hash = hashlib.pbkdf2_hmac('sha256', b'password', salt, 100000)

PBKDF2 kann mit jedem Digest-Algorithmus arbeiten. Das obige Beispiel verwendet SHA256, was normalerweise empfohlen wird. Das zufällige Salt sollte zusammen mit dem Hash-Passwort gespeichert werden. Sie benötigen es erneut, um ein eingegebenes Passwort mit dem gespeicherten Hash zu vergleichen. Es ist wichtig, dass jedes Passwort mit einem anderen Salt gehashed wird. Es wird empfohlen, die Anzahl der Runden für Ihre Anwendung so hoch wie möglich einzustellen.

Wenn das Ergebnis hexadezimal sein soll, können Sie das binascii Modul verwenden:

import binascii
hexhash = binascii.hexlify(hash)

Hinweis : Während PBKDF2 nicht schlecht ist, gelten bcrypt und insbesondere scrypt als stärker gegen Brute-Force-Angriffe. Zur Zeit ist kein Teil der Python-Standardbibliothek.

Hashing von Dateien

Ein Hash ist eine Funktion, die eine Folge von Bytes mit variabler Länge in eine Folge mit fester Länge konvertiert. Das Hashing von Dateien kann aus vielen Gründen vorteilhaft sein. Mithilfe von Hashes können Sie überprüfen, ob zwei Dateien identisch sind, oder überprüfen, ob der Inhalt einer Datei nicht beschädigt oder geändert wurde.

Sie können hashlib , um einen Hash für eine Datei zu generieren:

import hashlib

hasher = hashlib.new('sha256')
with open('myfile', 'r') as f:
    contents = f.read()
    hasher.update(contents)

print hasher.hexdigest() 

Bei größeren Dateien kann ein Puffer mit fester Länge verwendet werden:

import hashlib
SIZE = 65536
hasher = hashlib.new('sha256')
with open('myfile', 'r') as f:
    buffer = f.read(SIZE)
    while len(buffer) > 0:
        hasher.update(buffer)
        buffer = f.read(SIZE)
print(hasher.hexdigest())

Symmetrische Verschlüsselung mit Pycrypto

Die in Python integrierte Kryptofunktionalität ist derzeit auf das Hashing beschränkt. Für die Verschlüsselung ist ein Drittanbieter-Modul wie pycrypto erforderlich . Beispielsweise bietet es den AES-Algorithmus, der als Stand der Technik für die symmetrische Verschlüsselung gilt. Der folgende Code verschlüsselt eine bestimmte Nachricht mit einer Passphrase:

import hashlib
import math
import os

from Crypto.Cipher import AES

IV_SIZE = 16    # 128 bit, fixed for the AES algorithm
KEY_SIZE = 32   # 256 bit meaning AES-256, can also be 128 or 192 bits
SALT_SIZE = 16  # This size is arbitrary

cleartext = b'Lorem ipsum'
password = b'highly secure encryption password'
salt = os.urandom(SALT_SIZE)
derived = hashlib.pbkdf2_hmac('sha256', password, salt, 100000,
                              dklen=IV_SIZE + KEY_SIZE)
iv = derived[0:IV_SIZE]
key = derived[IV_SIZE:]

encrypted = salt + AES.new(key, AES.MODE_CFB, iv).encrypt(cleartext)

Der AES-Algorithmus benötigt drei Parameter: Verschlüsselungsschlüssel, Initialisierungsvektor (IV) und die eigentliche zu verschlüsselnde Nachricht. Wenn Sie einen zufällig generierten AES-Schlüssel haben, können Sie diesen direkt verwenden und lediglich einen zufälligen Initialisierungsvektor generieren. Eine Passphrase hat jedoch nicht die richtige Größe, und es ist auch nicht empfehlenswert, sie direkt zu verwenden, da sie nicht wirklich zufällig ist und daher vergleichsweise wenig Entropie aufweist. Stattdessen verwenden wir die integrierte Implementierung des PBKDF2-Algorithmus , um einen 128-Bit-Initialisierungsvektor und einen 256-Bit-Verschlüsselungsschlüssel aus dem Kennwort zu generieren.

Beachten Sie den zufälligen Salt-Wert, der für jede verschlüsselte Nachricht einen anderen Initialisierungsvektor und einen anderen Schlüssel benötigt. Dies stellt insbesondere sicher, dass zwei gleiche Nachrichten nicht zu identischem verschlüsseltem Text führen, es verhindert jedoch auch, dass Angreifer die Arbeit für das Erraten einer Passphrase für mit einer anderen Passphrase verschlüsselte Nachrichten erneut verwenden. Dieses Salt muss zusammen mit der verschlüsselten Nachricht gespeichert werden, um denselben Initialisierungsvektor und denselben Schlüssel für die Entschlüsselung abzuleiten.

Der folgende Code entschlüsselt unsere Nachricht erneut:

salt = encrypted[0:SALT_SIZE]
derived = hashlib.pbkdf2_hmac('sha256', password, salt, 100000,
                              dklen=IV_SIZE + KEY_SIZE)
iv = derived[0:IV_SIZE]
key = derived[IV_SIZE:]
cleartext = AES.new(key, AES.MODE_CFB, iv).decrypt(encrypted[SALT_SIZE:])

Generierung von RSA-Signaturen mit pycrypto

RSA kann zum Erstellen einer Nachrichtensignatur verwendet werden. Eine gültige Signatur kann nur mit Zugriff auf den privaten RSA-Schlüssel generiert werden, die Validierung ist dagegen nur mit dem entsprechenden öffentlichen Schlüssel möglich. Solange die andere Seite Ihren öffentlichen Schlüssel kennt, kann sie die von Ihnen zu signierende und unveränderte Nachricht überprüfen - ein Ansatz, der zum Beispiel für E-Mails verwendet wird. Derzeit ist für diese Funktionalität ein Drittanbieter-Modul wie pycrypto erforderlich.

import errno

from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5

message = b'This message is from me, I promise.'

try:
    with open('privkey.pem', 'r') as f:
        key = RSA.importKey(f.read())
except IOError as e:
    if e.errno != errno.ENOENT:
        raise
    # No private key, generate a new one. This can take a few seconds.
    key = RSA.generate(4096)
    with open('privkey.pem', 'wb') as f:
        f.write(key.exportKey('PEM'))
    with open('pubkey.pem', 'wb') as f:
        f.write(key.publickey().exportKey('PEM'))

hasher = SHA256.new(message)
signer = PKCS1_v1_5.new(key)
signature = signer.sign(hasher)

Das Überprüfen der Signatur funktioniert ähnlich, verwendet jedoch den öffentlichen Schlüssel anstelle des privaten Schlüssels:

with open('pubkey.pem', 'rb') as f:
    key = RSA.importKey(f.read())
hasher = SHA256.new(message)
verifier = PKCS1_v1_5.new(key)
if verifier.verify(hasher, signature):
    print('Nice, the signature is valid!')
else:
    print('No, the message was signed with the wrong private key or modified')

Hinweis : Die obigen Beispiele verwenden den Signaturalgorithmus PKCS # 1 v1.5, der sehr häufig vorkommt. pycrypto implementiert auch den neueren PKCS # 1-PSS-Algorithmus. PKCS1_v1_5 durch PKCS1_PSS In den Beispielen sollte dies funktionieren, wenn Sie diesen verwenden möchten. Momentan scheint es jedoch wenig Grund zu geben, es zu benutzen .

Asymmetrische RSA-Verschlüsselung mit Pycrypto

Die asymmetrische Verschlüsselung hat den Vorteil, dass eine Nachricht verschlüsselt werden kann, ohne dass ein geheimer Schlüssel mit dem Empfänger der Nachricht ausgetauscht wird. Der Absender muss lediglich den öffentlichen Schlüssel des Empfängers kennen, wodurch die Nachricht so verschlüsselt werden kann, dass nur der angegebene Empfänger (der den entsprechenden privaten Schlüssel besitzt) die Nachricht entschlüsseln kann. Derzeit ist für diese Funktionalität ein Drittanbieter-Modul wie pycrypto erforderlich.

from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA

message = b'This is a very secret message.'

with open('pubkey.pem', 'rb') as f:
    key = RSA.importKey(f.read())
cipher = PKCS1_OAEP.new(key)
encrypted = cipher.encrypt(message)

Der Empfänger kann die Nachricht dann entschlüsseln, wenn er den richtigen privaten Schlüssel hat:

with open('privkey.pem', 'rb') as f:
    key = RSA.importKey(f.read())
cipher = PKCS1_OAEP.new(key)
decrypted = cipher.decrypt(encrypted)

Hinweis : Die obigen Beispiele verwenden das PKCS # 1-OAEP-Verschlüsselungsschema. pycrypto implementiert auch das Verschlüsselungsschema PKCS # 1 v1.5. Dieses Protokoll wird jedoch für neue Protokolle aufgrund bekannter Vorbehalte nicht empfohlen.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow