Per proteggere i dati in modo sicuro in Python, è essenziale utilizzare una crittografia efficace. In questo articolo, esploreremo come utilizzare la potente libreria di crittografia di Python, cryptography, passando dai metodi di crittografia di base a esempi avanzati. Ogni passo è spiegato in modo semplice e accessibile anche ai principianti, con esempi pratici e esercizi che aiuteranno a comprendere meglio le tecniche e le modalità di applicazione nei progetti reali. Alla fine dell’articolo, avrai acquisito le competenze fondamentali in sicurezza dei dati e sarai pronto per applicarle in modo pratico.
Come installare la libreria cryptography
Il primo passo per lavorare con la crittografia in Python è installare la libreria cryptography. Ecco come puoi farlo facilmente.
Preparazione dell’ambiente
Assicurati di avere Python installato e di avere accesso allo strumento di gestione dei pacchetti necessario (pip).
Verifica dell’installazione di Python
Per verificare se Python è installato, esegui il seguente comando nel terminale o nel prompt dei comandi.
python --version
Verifica dell’installazione di pip
Per verificare se pip è installato, esegui il seguente comando.
pip --version
Installazione della libreria cryptography
Usa pip per installare la libreria cryptography. Esegui il seguente comando nel terminale o nel prompt dei comandi.
pip install cryptography
Verifica dell’installazione
Per verificare se l’installazione è avvenuta con successo, apri l’interprete Python e esegui il seguente comando.
import cryptography
print(cryptography.__version__)
Se l’installazione è andata a buon fine, verrà visualizzato il numero di versione. Ora la libreria cryptography è installata correttamente.
Fondamenti della crittografia simmetrica
La crittografia simmetrica utilizza la stessa chiave per crittografare e decrittografare i dati. In questa sezione, esploreremo come utilizzare la libreria cryptography per implementare la crittografia simmetrica di base.
Cos’è la crittografia simmetrica
La crittografia simmetrica usa una sola chiave per criptare i dati e la stessa chiave per decriptarli. La gestione della chiave è quindi fondamentale. Un esempio di crittografia simmetrica è l’AES (Advanced Encryption Standard).
Crittografia e decrittografia con AES
Vediamo i passaggi fondamentali per crittografare e decrittografare i dati utilizzando AES.
Importazione dei moduli necessari
Per prima cosa, importiamo i moduli necessari dalla libreria cryptography.
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.backends import default_backend
import os
Generazione della chiave e del vettore di inizializzazione
Per AES, è necessario generare una chiave e un vettore di inizializzazione (IV).
key = os.urandom(32) # Chiave a 256 bit
iv = os.urandom(16) # Vettore di inizializzazione a 128 bit
Padding dei dati
Poiché la crittografia a blocchi richiede che i dati siano un multiplo della dimensione del blocco, aggiungeremo il padding ai dati.
def pad(data):
padder = padding.PKCS7(algorithms.AES.block_size).padder()
return padder.update(data) + padder.finalize()
Crittografia
Adesso crittografiamo i dati.
def encrypt(data, key, iv):
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
encryptor = cipher.encryptor()
padded_data = pad(data)
return encryptor.update(padded_data) + encryptor.finalize()
Decrittografia
Ora decrittografiamo i dati crittografati.
def decrypt(encrypted_data, key, iv):
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
decryptor = cipher.decryptor()
padded_data = decryptor.update(encrypted_data) + decryptor.finalize()
unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()
return unpadder.update(padded_data) + unpadder.finalize()
Esempio pratico
Vediamo un esempio in cui crittografiamo e decrittografiamo i dati.
data = b"Questo è un messaggio segreto"
encrypted_data = encrypt(data, key, iv)
print("Dati crittografati:", encrypted_data)
decrypted_data = decrypt(encrypted_data, key, iv)
print("Dati decrittografati:", decrypted_data.decode())
Così, con la libreria cryptography, possiamo implementare la crittografia simmetrica per proteggere i dati.
Fondamenti della crittografia asimmetrica
La crittografia asimmetrica utilizza chiavi diverse per la crittografia e la decrittografia. In questa sezione, esploreremo come utilizzare la libreria cryptography per implementare la crittografia asimmetrica di base.
Cos’è la crittografia asimmetrica
La crittografia asimmetrica utilizza una coppia di chiavi: una pubblica e una privata. I dati crittografati con la chiave pubblica possono essere decrittografati solo con la chiave privata corrispondente. Un esempio di crittografia asimmetrica è RSA (Rivest-Shamir-Adleman).
Crittografia e decrittografia con RSA
Vediamo i passaggi fondamentali per crittografare e decrittografare i dati utilizzando RSA.
Importazione dei moduli necessari
Importiamo i moduli necessari dalla libreria cryptography per RSA.
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import padding
Generazione della coppia di chiavi
Generiamo una coppia di chiavi pubblica e privata per la crittografia RSA.
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
)
public_key = private_key.public_key()
Salvataggio e caricamento delle chiavi
Vediamo come salvare le chiavi e caricarle in seguito.
# Salvataggio della chiave privata
private_pem = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption()
)
# Salvataggio della chiave pubblica
public_pem = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
# Caricamento delle chiavi
loaded_private_key = serialization.load_pem_private_key(private_pem, password=None)
loaded_public_key = serialization.load_pem_public_key(public_pem)
Crittografia
Usiamo la chiave pubblica per crittografare i dati.
def encrypt(data, public_key):
return public_key.encrypt(
data,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
Decrittografia
Usiamo la chiave privata per decrittografare i dati.
def decrypt(encrypted_data, private_key):
return private_key.decrypt(
encrypted_data,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
Esempio pratico
Vediamo un esempio in cui crittografiamo e decrittografiamo i dati.
data = b"Questo è un messaggio segreto"
encrypted_data = encrypt(data, public_key)
print("Dati crittografati:", encrypted_data)
decrypted_data = decrypt(encrypted_data, private_key)
print("Dati decrittografati:", decrypted_data.decode())
Così, con la libreria cryptography, possiamo implementare la crittografia asimmetrica per la protezione dei dati.
Fondamenti dell’hash
L’hash è un metodo per trasformare i dati in un valore di lunghezza fissa. Il valore hash è unidirezionale e non può essere riportato ai dati originali. In questa sezione, esploreremo come usare la libreria cryptography per applicare l’hash ai dati.
Cos’è l’hash
L’hash viene utilizzato per verificare l’integrità dei dati o per memorizzare le password. Un esempio di algoritmo di hash è SHA-256 (Secure Hash Algorithm 256-bit).
Hash con SHA-256
Vediamo i passaggi per applicare l’hash ai dati usando SHA-256.
Importazione dei moduli necessari
Importiamo i moduli necessari dalla libreria cryptography.
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend
Hash dei dati
Usiamo SHA-256 per fare l’hash dei dati.
def hash_data(data):
digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
digest.update(data)
return digest.finalize()
Esempio pratico
Vediamo un esempio in cui effettuiamo l’hash dei dati e visualizziamo il risultato.
data = b"Questi sono i dati da hashare"
hashed_data = hash_data(data)
print("Dati hashati:", hashed_data.hex())
Uso dell’hash
L’hash può essere utilizzato per verificare l’integrità dei dati. Ad esempio, dopo aver scaricato un file, puoi confrontare l’hash per assicurarti che non sia stato manomesso.
# Calcolare l'hash di un file
def hash_file(file_path):
digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
with open(file_path, 'rb') as f:
while chunk := f.read(8192):
digest.update(chunk)
return digest.finalize()
# Calcolare e visualizzare l'hash del file
file_path = 'path/to/your/file'
file_hash = hash_file(file_path)
print("Hash del file:", file_hash.hex())
Con la libreria cryptography, possiamo eseguire l’hash dei dati e verificarne l’integrità. L’hash è fondamentale per la gestione delle password e per il controllo dell’integrità dei dati.
Generazione di chiavi private e pubbliche
Generare una coppia di chiavi private e pubbliche è un passo cruciale nella crittografia asimmetrica. In questa sezione, vedremo come generare e gestire le chiavi usando la libreria cryptography.
Generazione di una coppia di chiavi RSA
Generiamo una coppia di chiavi usando l’algoritmo RSA.
Importazione dei moduli necessari
Importiamo i moduli necessari dalla libreria cryptography.
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
Generazione della coppia di chiavi
Generiamo la coppia di chiavi RSA.
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
)
public_key = private_key.public_key()
Salvataggio delle chiavi
Salviamo le chiavi in file separati, uno per la chiave privata e uno per la chiave pubblica.
# Salvataggio della chiave privata
with open("private_key.pem", "wb") as private_file:
private_file.write(private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption()
))
# Salvataggio della chiave pubblica
with open("public_key.pem", "wb") as public_file:
public_file.write(public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
))
Caricamento delle chiavi
Carichiamo le chiavi salvate dai file.
# Caricamento della chiave privata
with open("private_key.pem", "rb") as private_file:
loaded_private_key = serialization.load_pem_private_key(
private_file.read(),
password=None,
)
# Caricamento della chiave pubblica
with open("public_key.pem", "rb") as public_file:
loaded_public_key = serialization.load_pem_public_key(
public_file.read()
)
Esempio pratico
Usiamo la coppia di chiavi per crittografare e decrittografare i dati.
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
# Crittografia dei dati
def encrypt(data, public_key):
return public_key.encrypt(
data,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# Decrittografia dei dati
def decrypt(encrypted_data, private_key):
return private_key.decrypt(
encrypted_data,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# Esempio di crittografia e decrittografia
data = b"Questo è un messaggio segreto"
encrypted_data = encrypt(data, loaded_public_key)
print("Dati crittografati:", encrypted_data)
decrypted_data = decrypt(encrypted_data, loaded_private_key)
print("Dati decrittografati:", decrypted_data.decode())
Così, con la libreria cryptography, possiamo generare e gestire coppie di chiavi pubbliche e private per la crittografia sicura dei dati.
Crittografia e decrittografia in pratica
Utilizzando la libreria cryptography, esploreremo i passaggi pratici per crittografare e decrittografare i dati. Mostreremo esempi di crittografia simmetrica (AES) e asimmetrica (RSA) in progetti reali.
Crittografia simmetrica con AES
Importazione dei moduli necessari
Iniziamo importando i moduli necessari per la crittografia simmetrica.
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.backends import default_backend
import os
Generazione della chiave e del vettore di inizializzazione
Per AES, generiamo una chiave e un vettore di inizializzazione.
key = os.urandom(32) # Chiave a 256 bit
iv = os.urandom(16) # Vettore di inizializzazione a 128 bit
Padding dei dati
Aggiungiamo padding ai dati per farli diventare un multiplo della dimensione del blocco.
def pad(data):
padder = padding.PKCS7(algorithms.AES.block_size).padder()
return padder.update(data) + padder.finalize()
Crittografia dei dati
Crittografiamo i dati con AES.
def encrypt(data, key, iv):
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
encryptor = cipher.encryptor()
padded_data = pad(data)
return encryptor.update(padded_data) + encryptor.finalize()
Decrittografia dei dati
Decrittografiamo i dati crittografati e rimuoviamo il padding.
def decrypt(encrypted_data, key, iv):
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
decryptor = cipher.decryptor()
padded_data = decryptor.update(encrypted_data) + decryptor.finalize()
unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()
return unpadder.update(padded_data) + unpadder.finalize()
Esempio pratico
Critto e decripto i dati per vedere come funziona il processo completo.
data = b"Questo è un messaggio segreto"
encrypted_data = encrypt(data, key, iv)
print("Dati crittografati:", encrypted_data)
decrypted_data = decrypt(encrypted_data, key, iv)
print("Dati decrittografati:", decrypted_data.decode())
Crittografia asimmetrica con RSA
Importazione dei moduli necessari
Importiamo i moduli necessari per RSA.
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import padding
Generazione della coppia di chiavi
Generiamo la coppia di chiavi RSA.
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
)
public_key = private_key.public_key()
Crittografia dei dati
Usiamo la chiave pubblica per crittografare i dati.
def encrypt(data, public_key):
return public_key.encrypt(
data,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
Decrittografia dei dati
Usiamo la chiave privata per decrittografare i dati.
def decrypt(encrypted_data, private_key):
return private_key.decrypt(
encrypted_data,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
Esempio pratico
Vediamo un esempio in cui crittografiamo e decrittografiamo i dati usando RSA.
data = b"Questo è un messaggio segreto"
encrypted_data = encrypt(data, public_key)
print("Dati crittografati:", encrypted_data)
decrypted_data = decrypt(encrypted_data, private_key)
print("Dati decrittografati:", decrypted_data.decode())
Con la libreria cryptography, possiamo implementare sia la crittografia simmetrica che asimmetrica in progetti reali.
Applicazioni pratiche nei progetti
Esploreremo ora come utilizzare la libreria cryptography in scenari reali, come la crittografia delle comunicazioni API, la crittografia delle basi di dati e dei file.
Crittografia delle comunicazioni API
Esploreremo come proteggere le comunicazioni API con la crittografia.
Uso di HTTPS
Iniziamo utilizzando HTTPS per proteggere la comunicazione. Questo garantisce che i dati siano criptati durante il trasferimento, impedendo l’intercettazione.
Crittografia dei dati
Possiamo anche crittografare i dati prima di inviarli tramite l’API per aggiungere un ulteriore livello di sicurezza.
import requests
# Crittografia dei dati con la chiave pubblica
data = b"Dati sensibili dell'API"
encrypted_data = encrypt(data, public_key)
# Invio dei dati crittografati all'API
response = requests.post('https://api.example.com/data', data=encrypted_data)
Crittografia delle basi di dati
Vediamo come crittografare le informazioni importanti memorizzate nelle basi di dati.
Crittografia dei dati prima della memorizzazione
Crittografiamo i dati prima di memorizzarli nel database e li decrittografiamo quando ne abbiamo bisogno.
import sqlite3
# Connessione al database
conn = sqlite3.connect('example.db')
cursor = conn.cursor()
# Crittografia dei dati
data = b"Dati sensibili da salvare"
encrypted_data = encrypt(data, key, iv)
# Salvataggio dei dati crittografati
cursor.execute("INSERT INTO secrets (data) VALUES (?)", (encrypted_data,))
conn.commit()
# Decrittografia dei dati
cursor.execute("SELECT data FROM secrets")
encrypted_data = cursor.fetchone()[0]
decrypted_data = decrypt(encrypted_data, key, iv)
print("Dati decrittografati:", decrypted_data.decode())
Crittografia dei file
Vediamo come crittografare i file per proteggerli e come decrittografarli quando necessario.
Crittografia del file
Crittografiamo il contenuto di un file e lo salviamo in modo sicuro.
# Lettura e crittografia del file
with open('example.txt', 'rb') as file:
file_data = file.read()
encrypted_data = encrypt(file_data, key, iv)
# Salvataggio dei dati crittografati
with open('example_encrypted.txt', 'wb') as file:
file.write(encrypted_data)
# Decrittografia del file
with open('example_encrypted.txt', 'rb') as file:
encrypted_data = file.read()
decrypted_data = decrypt(encrypted_data, key, iv)
# Scrittura dei dati decrittografati
with open('example_decrypted.txt', 'wb') as file:
file.write(decrypted_data)
Gestione sicura delle chiavi
La gestione sicura delle chiavi è cruciale per mantenere i dati protetti. In questa sezione, esploreremo come gestire le chiavi in modo sicuro.
Salvataggio sicuro delle chiavi
Per garantire la sicurezza delle chiavi, è possibile utilizzare HSM (Hardware Security Module) o servizi di archiviazione sicura delle chiavi, o gestirle tramite variabili d’ambiente.
import os
# Ottieni la chiave dalle variabili d'ambiente
key = os.environ.get('SECRET_KEY').encode()
iv = os.environ.get('SECRET_IV').encode()
Conclusioni
In questo articolo, abbiamo esplorato i fondamenti della crittografia con la libreria cryptography di Python, imparando a implementare la crittografia simmetrica e asimmetrica, nonché a gestire le chiavi e le operazioni di hash. Attraverso esempi pratici e applicazioni reali, hai acquisito le competenze per proteggere i tuoi dati in modo sicuro nei progetti reali. La sicurezza dei dati è sempre più importante, e padroneggiare queste tecniche ti aiuterà a mantenere i tuoi progetti sicuri.