Sei sulla pagina 1di 6

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 pseudo-
random 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.

Potrebbero piacerti anche