Zoeken…


Invoering

Python, een van de meest populaire talen op het gebied van computer- en netwerkbeveiliging, heeft een groot potentieel op het gebied van beveiliging en cryptografie. Dit onderwerp behandelt de cryptografische functies en implementaties in Python, van het gebruik ervan in computer- en netwerkbeveiliging tot hashing- en encryptie / decryptie-algoritmen.

Syntaxis

  • hashlib.new (naam)
  • hashlib.pbkdf2_hmac (naam, wachtwoord, zout, rondes, dklen = Geen)

Opmerkingen

Voor veel van de methoden in hashlib moet u waarden doorgeven die kunnen worden geïnterpreteerd als buffers van bytes in plaats van tekenreeksen. Dit is het geval voor hashlib.new().update() en hashlib.pbkdf2_hmac . Als je een string hebt, kun je deze converteren naar een bytebuffer door het teken b aan het begin van de string:

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

Een berichtensamenvatting berekenen

Met de hashlib module kunnen generators van berichten worden hashlib via de new methode. Deze generatoren veranderen een willekeurige string in een digest met een vaste lengte:

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-='

Merk op dat je een willekeurig aantal keer een update kunt oproepen voordat je digest wat handig is om een groot bestand stuk voor stuk te hashen. Je kunt de samenvatting ook in hexadecimaal formaat krijgen door hexdigest :

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

Beschikbare hash-algoritmen

hashlib.new vereist de naam van een algoritme wanneer u dit hashlib.new om een generator te produceren. Gebruik hashlib.algorithms_available om te weten te komen welke algoritmen beschikbaar zijn in de huidige Python-interpreter:

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'}

De geretourneerde lijst is afhankelijk van het platform en de tolk; zorg ervoor dat u controleert of uw algoritme beschikbaar is.

Er zijn ook enkele algoritmen die gegarandeerd beschikbaar zijn op alle platforms en tolken, die beschikbaar zijn met hashlib.algorithms_guaranteed :

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

Veilig wachtwoord hashing

Het PBKDF2-algoritme dat wordt blootgesteld door de hashlib module kan worden gebruikt om veilige wachtwoordhashing uit te voeren. Hoewel dit algoritme brute-force-aanvallen niet kan voorkomen om het oorspronkelijke wachtwoord van de opgeslagen hash te herstellen, maakt het dergelijke aanvallen erg duur.

import hashlib
import os

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

PBKDF2 kan met elk digest-algoritme werken, het bovenstaande voorbeeld gebruikt SHA256, dat meestal wordt aanbevolen. Het willekeurige zout moet samen met het gehashte wachtwoord worden opgeslagen, u hebt het opnieuw nodig om een ingevoerd wachtwoord te vergelijken met de opgeslagen hash. Het is essentieel dat elk wachtwoord wordt gehasht met een ander zout. Wat het aantal rondes betreft, is het raadzaam om deze zo hoog mogelijk in te stellen voor uw toepassing .

Als u het resultaat in hexadecimaal wilt, kunt u de binascii module gebruiken:

import binascii
hexhash = binascii.hexlify(hash)

Opmerking : Hoewel PBKDF2 niet slecht is, worden bcrypt en vooral scrypt als sterker beschouwd tegen brute-force-aanvallen. Momenteel maakt geen van beide deel uit van de standaardbibliotheek van Python.

Bestand Hashing

Een hash is een functie die een reeks bytes met variabele lengte omzet in een reeks met vaste lengte. Hashing-bestanden kunnen om vele redenen voordelig zijn. Hashes kan worden gebruikt om te controleren of twee bestanden identiek zijn of om te controleren of de inhoud van een bestand niet is beschadigd of gewijzigd.

Je kunt hashlib gebruiken om een hash voor een bestand te genereren:

import hashlib

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

print hasher.hexdigest() 

Voor grotere bestanden kan een buffer met een vaste lengte worden gebruikt:

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 codering met behulp van pycrypto

De ingebouwde cryptofunctionaliteit van Python is momenteel beperkt tot hashing. Versleuteling vereist een externe module zoals pycrypto . Het biedt bijvoorbeeld het AES-algoritme dat wordt beschouwd als state of the art voor symmetrische codering. De volgende code codeert een bepaald bericht met een wachtwoordzin:

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)

Het AES-algoritme heeft drie parameters: coderingssleutel, initialisatievector (IV) en het daadwerkelijke te coderen bericht. Als u een willekeurig gegenereerde AES-sleutel hebt, kunt u die direct gebruiken en alleen een willekeurige initialisatievector genereren. Een wachtwoordzin heeft echter niet de juiste maat, en het is ook niet aan te bevelen om het direct te gebruiken, aangezien het niet echt willekeurig is en dus relatief weinig entropie heeft. In plaats daarvan gebruiken we de ingebouwde implementatie van het PBKDF2-algoritme om een 128-bits initialisatievector en een 256-bits coderingssleutel van het wachtwoord te genereren.

Let op het willekeurige zout dat belangrijk is om een verschillende initialisatievector en -sleutel voor elk gecodeerd bericht te hebben. Dit zorgt er in het bijzonder voor dat twee gelijke berichten niet resulteren in identieke gecodeerde tekst, maar het voorkomt ook dat aanvallers werk hergebruiken dat is besteed aan het raden van één wachtwoordzin op berichten die zijn gecodeerd met een andere wachtwoordzin. Dit zout moet samen met het gecodeerde bericht worden opgeslagen om dezelfde initialisatievector en sleutel voor het decoderen af te leiden.

De volgende code decodeert ons bericht opnieuw:

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:])

RSA-handtekeningen genereren met behulp van pycrypto

RSA kan worden gebruikt om een berichthandtekening te maken. Een geldige handtekening kan alleen worden gegenereerd met toegang tot de private RSA-sleutel. Validatie is daarentegen mogelijk met alleen de bijbehorende openbare sleutel. Dus zolang de andere partij uw openbare sleutel kent, kan deze het bericht verifiëren dat door u moet worden ondertekend en ongewijzigd - een benadering die bijvoorbeeld voor e-mail wordt gebruikt. Momenteel is voor deze functionaliteit een externe module zoals pycrypto vereist.

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)

Het verifiëren van de handtekening werkt op dezelfde manier, maar gebruikt de openbare sleutel in plaats van de persoonlijke sleutel:

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')

Opmerking : de bovenstaande voorbeelden gebruiken PKCS # 1 v1.5-ondertekeningsalgoritme, wat heel gebruikelijk is. pycrypto implementeert ook het nieuwere PKCS # 1 PSS-algoritme, het vervangen van PKCS1_v1_5 door PKCS1_PSS in de voorbeelden zou moeten werken als u dat wilt gebruiken. Momenteel lijkt er echter weinig reden om het te gebruiken .

Asymmetrische RSA-codering met behulp van pycrypto

Asymmetrische codering heeft het voordeel dat een bericht kan worden gecodeerd zonder een geheime sleutel uit te wisselen met de ontvanger van het bericht. De afzender hoeft alleen de openbare sleutel van de ontvanger te kennen, hierdoor kan het bericht zodanig worden gecodeerd dat alleen de aangewezen ontvanger (die de bijbehorende persoonlijke sleutel heeft) het kan ontsleutelen. Momenteel is voor deze functionaliteit een externe module zoals pycrypto vereist.

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)

De ontvanger kan het bericht vervolgens ontsleutelen als hij de juiste persoonlijke sleutel heeft:

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

Opmerking : de bovenstaande voorbeelden gebruiken PKCS # 1 OAEP-coderingsschema. pycrypto implementeert ook PKCS # 1 v1.5 coderingsschema, dit wordt echter niet aanbevolen voor nieuwe protocollen vanwege bekende kanttekeningen .



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow