Appunti Cyber-Security 3 [PDF]

  • 0 0 0
  • Gefällt Ihnen dieses papier und der download? Sie können Ihre eigene PDF-Datei in wenigen Minuten kostenlos online veröffentlichen! Anmelden
Datei wird geladen, bitte warten...
Zitiervorschau

CYBER-PHYSICAL SECURITY 01/10/2020 Nella crittografia moderna, ci sono 3 principi nominati da Kerckhoffs: - Qualsiasi schema o cifrario utilizzato, quando viene creato, è pubblico. Sicurezza non è data dall’ignoranza e dal non sapere. - L’unica cosa segreta è la chiave - Un cifrario deve poter essere rotto in tempi non realistici e con risorse non accessibili (es. uno schema si può rompere in 20.000 anni). Non bisogna creare un cifrario indecifrabile. Requisiti degli schemi: - Lo spazio delle chiavi deve essere abbastanza grande per resistere ad attacchi brute force - Il testo cifrato deve essere indistinguibile da dati random per un attaccante, a prescindere dal tipo di dati - Nessuna informazione deve essere ricavabile dal testo cifrato

Gli schemi che a prescindere da qualsiasi quantità di risorse di attacco a disposizione sono indistruttibili sono identificati dal termine perfect secrecy. Sono schemi che però comportano dei costi talmente elevati che chi me lo fa fare di usare sta robaccia… molto meglio gli schemi identificati da computational security, come gli stream ciphers e i block ciphers.

Fin dai tempi di Cesare, anche se non si conosceva la somma modulare (lo XOR), questa era già usata in maniera inconsapevole. Il problema di Vigenère è che nel momento in cui hai una chiave segreta, devi metterla in parallelo con il testo in chiaro e fare una somma modulare lettera per lettera. La chiave va ripetuta quando termina. Il ripetere più volte la stessa parola segreta crea una vulnerabilità perché basta sottocampionare il testo cifrato.

Nel one-time-pad, la chiave deve essere completamente random e lunga tanto quanto il messaggio in chiaro. Questo schema è completamente sicuro, perché non esiste una soluzione. La chiave è random, i bit hanno la stessa probabilità di essere giusti o sbagliati. Questo schema però non è utilizzabile nel mondo reale per il fatto della lunghezza della chiave. Non è un sistema pratico per il mondo moderno (es. per comprare articoli online). Questo schema, nonostante sia perfetto per la confidenzialità, è completamente vulnerabile per l’integrità: manipolare del testo cifrato con questo sistema, non permette di capire quali parti siano cifrate e quali no. Essendo la cifratura basata sullo XOR, ed essendo lo XOR commutativo, se un attaccante modifica alcuni bit (da 0 a 1 o viceversa), il destinatario non si accorgerà della modifica. Si parla quindi di malleabilità dello schema (capire quali porzioni di testo sto criptando e quali no).

COMPUTATIONAL SECURITY Quello che cerchiamo di avere è avere uno schema di cifratura che offre due funzioni efficienti e una inefficiente. - Le due funzioni efficienti sono di cifratura e di decifratura. Chi cifra e chi decifra i dati con conoscenza della chiave esegue quell’operazione con poche risorse. La funzione efficiente è un algoritmo con un costo polinomiale: il numero di operazioni per decifrare o cifrare è esprimibile con un polinomio - La funzione inefficiente (negligible) è quella della rottura dello schema. L’algoritmo che rompe lo schema deve richiedere molto tempo e risorse tali per cui la probabilità di rompere lo schema senza chiave è bassissima. Il livello di sicurezza di uno schema individua il numero medio di operazioni necessarie a rompere uno schema. Se ho uno schema di sicurezza con n bit, ci vogliono 2^n bit per rompere lo schema. Con gli schemi simmetrici, se ho una chiave da 128 bit mi serviranno 2^128 operazioni per trovare la chiave col bruteforce (miglior metodo). Negli schemi asimmetrici il discorso è diverso, perché si basano su relazioni matematiche.

La prima famiglia di schemi che consideriamo è quella dei cifrari a flusso. Al posto di avere una chiave completamente random, abbiamo una chiave a flusso (chiave pseudo-random). Un dato pseudo-random è un dato generato da una funzione che prende come input una piccola quantità di dati random e genera una sequenza più grande di bit indistinguibile da dati random. È molto simile al one-time-pad, ma la chiave che va conosciuta non è quella lunga quanto il testo, ma la chiave piccolina dello stream cypher. Questa funzione è deterministica: eseguendo questa funzione con gli stessi input, otteniamo sempre la stessa stream key. Stesso input, stesso output. Al suo interno ci sono operazioni di shift e di varia natura che possono avere vulnerabilità. Il modello a cui tutti gli stream cypher rispondono è: messaggio XOR StreamCypher (key, nonce) I dati random sono generati da un processo fisico nativo (tasti tastiera, dati webcam, corrente passiva generata tra semiconduttori…). I dati pseudorandom sono generati da un generatore pseudorandom, e sono indistinguibili dai dati random. Quando usiamo gli schemi di cifratura bisogna garantire che i dati siano cifrati in modo differente. La funzione deve generare sempre dati cifrati diversi. Se mando gli stessi dati due volte, e l’attaccante se ne accorge, viene violata la confidenzialità. È necessario che gli stessi dati siano cifrati in maniera diversa.

IL NONCE Il nonce è una sequenza di bit potenzialmente non random (es. un contatore) e viene utilizzato 1 volta sola. In caso di più utilizzi dello stesso nonce si incorre in una vulnerabilità enorme. Chi spedisce i dati genera il nonce, cifra il messaggio e invia il testo insieme al nonce. L’attaccante può leggere il nonce in chiaro, ma non serve a nulla perché da solo non dà informazioni. Dati una stessa chiave e uno stesso nonce, uno stream cipher produce la stessa stream key. Questo distrugge completamente il cifrario, cripto dati diversi con la stessa chiave. La natura del calcolo di questi schemi permette all’attaccante di ottenere informazioni nel caso il nonce sia lo stesso.

BLOCK CIPHERS Lavorando con i block cipher si ha a che fare con AES, lo standard universale. AES non è uno schema di cifratura, né un block cipher, è una famiglia di cifrari che identifica 3 particolari istanze: può esistere come 128, 192 e 256. Questi numeri si riferiscono alla lunghezza in bit della chiave. Bisogna specificare anche la modalità di cifratura con cui usare il cifrario a blocchi. È un oggetto matematico definito come una famiglia di permutazioni pseudorandom che dipendono da una chiave. Un block cipher altro non è che un cifrario a sostituzione (assumendo un certo alfabeto, sostituisco una lettera con un’altra lettera dello stesso alfabeto). Un block cipher ideale (tabella) è troppo grosso per essere utilizzato e memorizzato in una macchina. Vogliamo costruire un oggetto che si comporta come un cifrario a sostituzione ideale ma non vogliamo memorizzare tutte le combinazioni. Ci serve però una chiave. La chiave del block cipher concettualmente agisce come indice: va a dire “utilizza la sostituzione numero x”. Qual è il valore di n? Il numero di bit che sostituiamo ogni volta per fare in modo che lo schema sia resistente/non vulnerabile ad attacchi di frequenza? Dipende: ad esempio AES ha una block size di 128 bit. A prescindere dalla dimensione della chiave, la block size resta quella, vengono sostituiti 128 bit alla volta. Ma che succede se cifro dei dati più corti di 128 bit? Il predecessore di AES è DES. Aveva una block size di 64 bit, rischioso per l’epoca moderna. Aumentare la dimensione del blocco è un modo per rafforzare lo schema dal punto di vista degli attacchi di frequenza. Il block cipher non sostituisce direttamente i dati: utilizziamo delle modalità apposite, aggiungendo operazioni. Ad esempio, utilizzando il CBC, creiamo un effetto cascata tra tutti i blocchi cifrati: viene fatto lo XOR tra il blocco cifrato e il testo in chiaro (Cipher Block Chaining). In questo caso entra in gioco l’initialization vector: è un oggetto simile al nonce, e garantisce la sicurezza di tanti messaggi da cifrare. La concatenazione rompe i pattern all’interno di uno stesso messaggio, ma cifrando più testi uguali si ottiene lo stesso ciphertext. IV è un input che deve essere fornito dall’utente, come il nonce, e deve essere random e diverso ogni volta.

IV e nonce sono due cose diverse: - Il nonce serve nei casi in cui l’unicità è critica - IV serve nei casi in cui la randomicità è critica: se l’attaccante riesce a predire gli initialization vector che utilizzeremo può effettuare attacchi gravi, per questo il fattore random è importante

CTR MODE ENCRYPTION Il block cipher è formato da due oggetti: il nonce e il counter. Non viene più dato in ingresso il testo in chiaro. In questo modo ogni blocco riceve sempre un input diverso. La stream key (l’output del block cypher) viene xorata con il testo in chiaro per generare il testo cifrato. Le dimensioni di nonce e counter variano in base all’implementazione. Dipende dalle situazioni, ad esempio più è grande il counter, più è piccolo il nonce, minore è il numero di messaggi criptabili. Se ho tanti messaggi ma di piccole dimensioni potrei avere un nonce di dimensioni maggiori, se ho messaggi di dimensioni grandi avrò un counter più grande.

Nonce + counter = block cipher size Il counter pone un limite alla quantità di dati cifrabile con una singola invocazione della funzione, mentre il nonce pone un limite al numero di invocazioni della funzione. In caso la lunghezza del testo in chiaro non fosse multipla della lunghezza della stream key, prendo solo una parte della stream key, il resto lo scarto. Alla fine io ho bisogno di fare uno xor tra testo e chiave, quindi non importa se uso tutta la chiave o solo una parte. Questo però non vale in modalità CBC (quella con l’initialization vector). I block cipher non lavorano con lunghezze variabili, hanno bisogno di lunghezze definite, e se in input ho il plaintext non posso avere una lunghezza che non sia un multiplo della dimensione del blocco (es. tutti i blocchi devono essere di 128 bit).

Se voglio criptare dei messaggi utilizzando delle tecniche che prevedono una dimensione multipla della block size entra in gioco il padding, cioè l’inserimento di dati fittizi che aggiustano la dimensione. Ovviamente questi dati devono essere distinguibili dai dati reali. Storicamente venivano aggiunte frasi e parole a caso che non c’entravano niente con il testo. In epoca moderna c’è uno standard, PKCS7. Lo standard prevede di aggiungere N volte il numero N di byte mancanti (es: se mancano 6 byte, aggiungi 6 volte il numero 6). In caso i dati siano già della dimensione corretta, si aggiunge block-size volte il valore della block size (es: nel caso in cui avessi a disposizione 16 byte e li avessi già occupati tutti, bisogna aggiungere 16 volte il numero 16).

Concetto importante: la cifratura non ha lo scopo di nascondere la dimensione dei dati. Nel caso in cui la dimensione vada protetta, bisogna manipolare appositamente il messaggio per camuffare la dimensione.