%% introsec.tex
%%
%% Copyright (C) 2005-2018 Simone Piccardi and Truelite Srl. 
%%
%% This work is licensed under the Creative Commons Attribution-ShareAlike 4.0
%% International License. To view a copy of this license, visit
%% \url{http://creativecommons.org/licenses/by-sa/4.0/} or send a letter to
%% Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
%%
%% Introduzione alla sicurezza: Dispense dei corsi GNU/Linux di Truelite
%%
%% S. Piccardi Jan. 2005
%% 
%% introsec.tex
%%
\chapter{Le basi della sicurezza informatica}
\label{cha:security}


\section{Introduzione ai concetti di base}
\label{sec:security_whatis}

In questa prima sezione faremo una breve introduzione teorica sulla sicurezza
informatica, illustrando i concetti di base su cui essa è fondata, descrivendo
gli attacchi e le fonti di insicurezza, ed i servizi e le funzionalità
necessari alla sua salvaguardia. Infine esamineremo alcuni criteri di base
necessari alla creazione di una politica di sicurezza.

\subsection{Gli obiettivi fondamentali della sicurezza informatica}
\label{sec:security_intro}

Per poter parlare di sicurezza di un sistema informatico occorre anzitutto
definire cosa si intende per sicurezza, perché è solo in base a questo che si
possono identificare le minacce ed i pericoli che possono metterla in
discussione e poi discutere delle politiche che si intendono applicare per
realizzarla.

Nel campo dell'informatica si sono spesso adottate le più varie definizioni
del termine sicurezza che ne caratterizzano il significato secondo vari
aspetti.  Nel nostro caso utilizzeremo una definizione operativa che si basa
sul soddisfacimento di tre obiettivi fondamentali, e che è ampiamente adottata
in buona parte della letteratura che tratta delle problematiche di sicurezza
informatica.\footnote{un ottimo testo che usa questa classificazione, il cui
  contenuto è però molto teorico, è \cite{CompSec}.}

Si dice allora che quando un sistema informatico è in grado di realizzare
questi obiettivi potremo considerarlo sicuro.  Questi obiettivi di base, che
costituiscono quelli che considereremo come criteri essenziali per la
sicurezza informatica, sono i seguenti:
\begin{basedescript}{\desclabelwidth{3cm}\desclabelstyle{\nextlinelabel}}
\item[\textsl{confidenzialità}] la garanzia che solo le persone autorizzate
  possono accedere al sistema ed ai dati, ed operare tramite di esso e su di
  essi. 
\item[\textsl{integrità}] la garanzia che solo le persone autorizzate possano
  modificare il sistema e i dati in esso mantenute, e possano farlo solo
  all'interno dei limiti e delle autorizzazioni loro assegnate. 
\item[\textsl{disponibilità}] la garanzia che il sistema è in grado di fornire
  i servizi previsti, e sia in grado di farlo in tempi e modalità
  ``\textsl{ragionevoli}''. 
\end{basedescript}

In realtà le definizioni appena riportate sono estremamente generiche ed
astratte, ed il loro significato viene spesso inteso in maniera diversa a
seconda degli ambienti in cui si opera, a seconda delle esigenze degli utenti,
(si pensi ad esempio al significato di \textsl{ragionevoli} nella
disponibilità dei servizi) o delle consuetudini locali.

La \textsl{confidenzialità} riguarda la necessità di mantenere segreti, o
meglio accessibili solo dalle persone autorizzate, informazioni, risorse e
dati presenti in un sistema informatico. A prima vista si potrebbe pensare che
questo è di interesse solo in casi particolari, come per l'uso in campi
particolarmente sensibili come quelli di applicazioni militari, amministrative
o industriali o per la protezione di dati ed informazioni particolarmente
sensibili.

In realtà benché questo sia un aspetto di cui è senz'altro necessario tenere
conto, anche le più semplici esigenze di privacy (come quelle imposte dal
Testo Unico del decreto legislativo 196/03) necessitano di meccanismi di
riservatezza. Inoltre le stesse credenziali di accesso che permettono di
definire gli utenti di un sistema devono essere adeguatamente protette. 

La confidenzialità in sostanza esprime la necessità che l'accesso alle
opportune risorse (dati ed informazioni) sia garantito solo a chi ha il
diritto di utilizzarle, nelle modalità stabilite dalla propria politica di
sicurezza. A livello di realizzazione tecnica questo comporta un supporto
diretto sia da parte del sistema operativo che delle applicazioni.

Infine una aspetto talvolta trascurato, ma che in certi casi è molto
importante, è quello della riservatezza riguardo l'esistenza stessa di certe
informazioni (ad esempio quanto potrebbe rivelare ad attaccanti contromisure
prese a difesa di una rete o per il rilevamento di attacchi), cioè quello che
usualmente viene classificato sotto il nome generico di \textit{information
  hiding}. 

In genere la modalità più utilizzata per garantire la confidenzialità dei dati
è quella di usare delle opportune tecnologie crittografiche (vedi
sez.~\ref{sec:cryptography}) in modo da renderli accessibili solo da coloro
che detengono le opportune chiavi di accesso. Nel caso però di
\textit{information hiding} si suole parlare invece di \index{steganografia}
\textsl{steganografia}, per indicare un insieme di tecniche con cui le
informazioni oltre che ad essere opportunamente cifrate, vengono pure nascoste
(in genere all'interno di altri dati apparentemente ``\textsl{innocui}'').

Si tenga presente comunque che non sempre è possibile cifrare tutte le
informazioni (ad esempio i dati mantenuti in un database, o da esso ricavati)
per esigenze di natura tecnica o realizzativa, nel qual caso si dovranno
prendere provvedimenti di altra natura per garantire i requisiti di
confidenzialità necessari.

L'\textsl{integrità} esprime la necessità che dati e risorse siano mantenuti
ed acceduti in maniera affidabile, così che ne sia sempre garantita la
validità. In particolare si deve poter essere certi sia del loro contenuto che
della loro origine. In genere si interpreta questo requisito in maniera
semplificata identificandolo con la capacità di prevenire operazioni di
scrittura non autorizzata,\footnote{come nel rapporto \cite{AIPAsec} dell'AIPA
  sulla sicurezza informatica.} o richiedendo che le informazioni siano non
modificabili, consistenti, o modificabili solo tramite i procedimenti
appropriati, o più genericamente \textsl{accurate}.

In questo caso cioè si intende per integrità che i dati sono nello stato in
cui sono stati ha lasciati dall'ultima operazione correttamente eseguita su
di essi, e che non hanno subito altre manipolazioni, modifiche o cancellazioni
non autorizzate. Normalmente quando si parla di integrità in un sistema sicuro
si fa riferimento solo al poter fare affidamento che dati e informazioni siano
mantenuti correttamente al riparo da distruzione o falsificazioni. 

Il termine \textsl{accuratezza} precedentemente citato però ha una valenza che
non è completamente esaurita dagli aspetti finora elencati, e sottintende
anche una ulteriore caratteristica, che spesso viene trascurata, e cioè che i
dati devono affidabili fin dall'inizio. L'integrità quindi deve anche
rispondere alla esigenza di garantire la correttezza dell'origine dei dati e
delle modalità con cui non solo vengono trattati, ma sono anche ottenuti. 

Per questo rispetto a quanto è necessario per la confidenzialità, l'integrità
richiede delle misure completamente diverse; nel primo caso l'obiettivo è
impedire l'accesso ai dati, in questo caso invece deve essere garantita anche
la correttezza e la loro validità ed in particolare quest'ultimo punto è
estremamente critico, in quanto si basa sull'assunzione di validità che si
pone all'origine dei dati stessi.

Questo rende spesso la valutazione dell'integrità dei dati estremamente
difficile, in quanto deve basarsi su delle assunzioni riguardanti la loro
origine e sulla fiducia che si può porre nella relativa fonte, due aspetti che
sono molto spesso sono erroneamente dati per acquisiti acriticamente nelle
politiche di sicurezza.

Anche per la gestione dell'integrità dei dati sono di fondamentale importanza
le tecnologie crittografiche, anche se in questo caso vengono applicate in
maniera sostanzialmente diversa dalla confidenzialità, e servono non tanto per
cifrare e decifrare dati, quanto per calcolare una \textsl{impronta} di un
certo file in un certo istante, memorizzando la quale è poi possibile eseguire
una verifica ad un tempo successivo.  Tratteremo gli aspetti generici di
queste tecniche in sez.~\ref{sec:crypto_hash}, mentre vedremo un esempio del
loro utilizzo in sez.~\ref{sec:ids_integrity_scan}.

Ovviamente tecniche come quella appena descritta sono efficaci solo per
informazioni che variano poco nel tempo; nel caso di basi di dati con
informazioni che variano continuamente questo approccio non è adeguato e si
può garantire un buon livello di integrità solo con una corretta politica di
identificazione ed autenticazione degli utenti, controllo degli accessi e
tracciabilità delle operazioni eseguite. 

La \textsl{disponibilità} esprime la necessità di poter utilizzare i dati, le
informazioni e le risorse messe a disposizione da un sistema informatico. 
Questo può apparire poco attinente alle questioni relative alla sicurezza, ma
è ovvio che un sistema senza backup è un sistema poco sicuro, in quanto
può essere messa a rischio l'esistenza stessa dei dati che gestisce. 

In genere comunque nel settore specifico della sicurezza si intende per
disponibilità di una risorsa o di un'applicazione la capacità di poter far si
che la stessa sia accessibile e utilizzabile a ogni richiesta inoltrata da un
utente autorizzato. 

In genere gli attacchi rivolti a questo aspetto della sicurezza vengono
chiamati \itindex{Denial~of~Service~(DoS)} \textit{Denial of Service}, (o più
brevemente DoS) e benché possano sembrare meno critici rispetto ad attacchi
che compromettano l'integrità o la confidenzialità dei dati, ciò non di meno
sono in grado di rendere inutilizzabili le risorse, e con questo bloccare
completamente il funzionamento del sistema.

Inoltre spesso questo tipo di attacco serve come ausilio per effettuare
attacchi più pericolosi, ad esempio se si è in grado di bloccare con un
attacco di \itindex{Denial~of~Service~(DoS)} \textit{Denial of Service} un
sistema chiave per la propria sicurezza (ad esempio quello che garantisce un
accesso cifrato) gli utenti finiranno probabilmente con l'usare un accesso non
cifrato non adeguatamente protetto, rendendo così possibile, all'attaccante
che lo ha predisposto, accedere a risorse critiche altrimenti non disponibili.


\subsection{I servizi per la sicurezza}
\label{sec:security_services}

Per poter assicurare la realizzazione di un adeguato livello di sicurezza
secondo i criteri illustrati in sez.~\ref{sec:security_intro} un sistema
informatico deve fornire una serie di servizi che gli permettano di assicurare
\textsl{confidenzialità}, \textsl{integrità} e \textit{disponibilità}.

In generale quando si parla di servizi di sicurezza la \textit{disponibilità}
non viene presa in considerazione esplicitamente, in quanto attiene più alla
robustezza infrastrutturale del sistema che a dei servizi specifici, anche se
ci possono essere eventuali indisponibilità dovute alle conseguenze di un
accesso abusivo.  Non tratteremo pertanto questi aspetti in questa sezione, ma
si tenga presente che anche i servizi di sicurezza più sofisticati non ci
salveranno dall'uso un sistema operativo o di programmi instabili o di scarsa
qualità, o dalla mancanza di una adeguata politica di backup.

Una prima classificazione elementare dei servizi di sicurezza può essere la
seguente, in cui essi sono stati suddivisi in tre classi funzionali diverse,
riportate in tab.~\ref{tab:security_services}. Queste prime tre classi sono
fondamentali e normalmente sono realizzate a livello di sistema operativo,
anche se molte applicazioni implementano a loro volta al loro interno questi
stessi meccanismi. In ogni caso questi servizi riguardano aspetti
infrastrutturali, che devono essere messi a disposizione dal sistema
informatico che si usa (applicazione o sistema operativo che sia).

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}{|l|l|}
    \hline
    \textbf{Classe}&\textbf{Descrizione}\\
    \hline
    \hline
    \textsl{identificazione}& Risponde alla domanda \textsl{chi sei?}\\
    \textsl{autenticazione} & Risponde alla domanda \textsl{come mi accerto che
      sei tu?}\\
    \textsl{autorizzazione} & Risponde alla domanda \textsl{cosa puoi fare?}\\ 
    \hline
  \end{tabular}
  \caption{Le tre classi funzionali dei servizi di sicurezza.}
  \label{tab:security_services}
\end{table}


La prima classe di servizi di sicurezza è quella
dell'\textsl{identificazione}; lo scopo di questi servizi è appunto quello di
identificare l'utente all'interno del sistema: questo da una parte è in genere
la condizione per l'accesso al sistema, dall'altra permette di associare
all'utente privilegi e capacità operative specifiche ad uso dei servizi di
controllo dell'accesso.

Questi servizi possono essere realizzati in diverse modalità, la più classica
è quella di associare un nome a ciascun utente (il classico \textit{username})
che lo identificherà,\footnote{nel caso di Unix questo è fatto associando ad
  un utente un numero identificativo detto \textit{User ID}, che a sua volta è
  associato all'\textit{username}; altri sistemi usano meccanismi più
  complessi, che prevedono identificativi comprendenti informazioni ulteriori,
  come la macchina su cui l'utente opera.} ma possono esistere anche sistemi
alternativi, come l'uso di smart-card o di dati biometrici,\footnote{in questi
  casi di spesso il servizio di identificazione viene unificato a quello di
  autenticazione.} che permettono di identificare l'utente in base al possesso
di un opportuno oggetto o alle sue caratteristiche fisiche.

La seconda classe di servizi è quella dell'\textsl{autenticazione}, il cui
scopo è quello di verificare l'identità di chi intende utilizzare il sistema e
che questa corrisponda ad un utente autorizzato. Si deve cioè determinare in
una qualche maniera la validità dell'identificazione, tanto che spesso si
tende ad considerare l'autenticazione come parte dei servizi di
identificazione.

Il meccanismo classico in questo caso è quello della password, dove
l'autenticazione è eseguita attraverso una parola chiave segreta, dimostrando
la conoscenza della quale si dimostra anche la correttezza della propria
identità. Anche in questo caso sono disponibili meccanismi alternativi, più o
meno sofisticati come le smart-card o i sistemi biometrici, o altre tecnologie
che consentano comunque di poter determinare con ragionevole certezza
l'identità di un utente; l'ambito del ``\textsl{ragionevole}'' definisce
appunto quella zona grigia sui contorni della quale si concentrano tanti
attacchi alla sicurezza.

In generale per i servizi di autenticazione si fa un uso significativo di
tecnologie crittografiche, le password ad esempio vengono controllate tramite
hash crittografici, mentre altri meccanismi come quelli usati da SSL e SSH
comportano l'uso di chiavi asimmetriche (vedi
sez.~\ref{sec:crypto_asymmetric}).

La terza classe di servizi è infine quella dell'\textsl{autorizzazione}, cioè
quella che mira a stabilire cosa l'utente può fare o non fare all'interno del
sistema, e ad cui si fa spesso riferimento anche come \textsl{controllo degli
  accessi}.  Questa è in genere la parte più corposa e complessa dei servizi
di sicurezza, in quanto ci sono diversi modelli di realizzazione che
riflettono anche diverse concezioni delle metodologie applicate.

Lo schema classico di controllo degli accessi è quello chiamato
\itindex{Discrectionary~Access~Control~(DAC)} \textit{Discrectionary Access
  Control} o DAC; in questo caso viene definito il proprietario di un dato ed
è lui a decidere quale tipo di accesso gli altri utenti possono avere dello
stesso.  In questo caso sono i singoli utenti che governano gli accessi ai
propri dati e decidono quali, in un elenco di operazioni definite possono
essere consentite agli altri utenti. 

Il caso classico di questa tipologia è quello dei dati mantenuti in
filesystem, e dei permessi usualmente associati ai file.  In genere in uno
schema DAC si articola in una serie di permessi che il proprietario può
assegnare ad altri utenti e gruppi, lo schema classico di Unix è limitato ad
una assegnazione generalizzata dei permessi a gruppi o a tutti gli utenti, ma
si possono creare anche schemi più complessi con l'uso delle \textit{Access
  List}, che permettono di assegnare permessi specifici ai singoli utenti e
gruppi. Anche in questo caso comunque è sempre il proprietario del file che
decide le modalità di accesso.

Il limite dello schema del \textit{Discrectionary Access Control} è che non si
possono imporre limiti alla disponibilità del dato al proprietario dello
stesso; esistono infatti situazioni in cui si vuole poter definire delle
politiche di accesso che limitino anche il proprietario di un dato nelle
operazioni consentite. Un esempio è quello in cui si vuole evitare che anche
in caso di compromissione del sistema in cui un attaccante ha avuto accesso
allo stesso, questo possa compiere delle operazioni che si sono stabilite
essere comunque illegittime.

Un caso classico in cui ci si scontra con questo problema è quello in cui si
vuole poter limitare le capacità dell'amministratore del sistema di compiere
certe operazioni. Questo comporta la necessità non solo di associare dei
permessi e dei controlli ai singoli dati, come nel DAC, ma anche alle varie
operazioni su di essi eseguibili.

Per rispondere a questi problemi è stato elaborato il cosiddetto
\itindex{Mandatory~Access~Control(MAC)} \textit{Mandatory Access Control} o
MAC, in cui si estende il concetto dei privilegi di accesso non solo al
contenuto dei singoli dati, ma alle varie operazioni che possono essere
eseguite nel sistema. Questo comporta ad esempio la possibilità di usare o
meno un certo programma per accedere a certi specifici dati o per compiere
certe specifiche operazioni.

Inoltre esiste il cosiddetto \itindex{Role-Based~Access~Control~(RBAC)}
\textit{Role-Based Access Control} o RBAC, che rappresenta un approccio nuovo
ed alternativo rispetto sia al \textit{Discrectionary Access Control} che al
\textit{Mandatory Access Control}. In questo caso l'idea è quella della
creazione di \textsl{ruoli} all'interno del sistema, a cui sono assegnate
certe capacità specifiche. Solo gli utenti inseriti all'interno di un ruolo
potranno eseguire le relative operazioni.

Questo approccio, eliminando la necessità di assegnare ad ogni utente permessi
e privilegi, semplifica notevolmente la gestione della sicurezza, in quanto
basterà definire gli opportuni ruoli e poi assegnare gli utenti ad uno di
essi. La semplificazione è però apparente, in quanto la difficoltà viene
comunque spostata nel compito di creare e definire adeguatamente le capacità
di accesso dei singoli ruoli.

Sia MAC che RBAC richiedono comunque, rispetto al caso tradizionale in cui i
permessi erano direttamente associati ai dati, un supporto molto più complesso
da parte del sistema operativo, che deve consentire di inserire controlli e
verifiche non solo a livello di accesso ai dati, ma anche all'interno delle
operazioni da eseguire su di essi. Questo permette in controllo molto più
raffinato, ma ovviamente aumenta anche la complessità di gestione e con questo
la probabilità di errori, ed in genere diminuisce anche le prestazioni.


\subsection{La classificazione dei rischi e delle minacce}
\label{sec:security_risk}

Rispetto ai tre obiettivi fondamentali della sicurezza illustrati in
sez.~\ref{sec:security_intro}, si tende a fornire una classificazione teorica
dei rischi e delle minacce ad essi portate suddividendo questi ultimi nelle
quattro classi generiche illustrate in tab.~\ref{tab:security_threat}.

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}{|l|p{8cm}|}
    \hline
    \textbf{Classe}&\textbf{Descrizione}\\
    \hline
    \hline
    \textit{disclosure}& la possibilità di un accesso non autorizzato ad
                         informazioni e dati riservati di un sistema.\\
    \textit{deception} & la possibilità di inserire o far accettare dati o
                         informazioni false o errate in un sistema. \\
    \textit{disruption}& la possibilità di interrompere o compromettere il
                         corretto funzionamento delle operazioni di un
                         sistema.\\ 
    \textit{usurpation}& la possibilità di prendere il controllo di un
                         sistema (o di una parte dello stesso) senza averne il
                         diritto.\\ 
    \hline
  \end{tabular}
  \caption{Le quattro classi astratte delle minacce alla sicurezza.}
  \label{tab:security_threat}
\end{table}

Come si può notare quella di tab.~\ref{tab:security_threat} è una
classificazione molto astratta, relativa a caratteristiche completamente
generiche, che si è ordinata per gravità crescente della minaccia. In generale
però quando si vanno a classificare le caratteristiche funzionali dei vari
tipi di attacco questi ricadono in più di una delle classi precedenti; per
questo c'è chi tende ad usare una categorizzazione delle minacce diversa,
secondo il seguente elenco:
\begin{basedescript}{\desclabelwidth{3.2cm}\desclabelstyle{\nextlinelabel}}
\item[\textsl{intercettazione}] detta in gergo \itindex{snooping}
  \textit{snooping}, questa categoria indica sia i rischi relativi
  all'intercettazione non autorizzata di informazioni che l'accesso non
  autorizzato a dati e documenti.

  Questo tipo di minacce ricade nella classe della \textit{disclosure}, e può
  essere implementato con varie metodologie: dalla intercettazione eseguita
  con mezzi fisici (il cosiddetto \itindex{wiretapping} \textit{wiretapping}),
  all'uso di software specifici come gli \itindex{sniffer} \textit{sniffer}
  sulla rete (vedi sez.~\ref{sec:ids_sniffer}), a sistemi di monitoraggio
  delle operazioni degli utenti: in generale ci si basa su tecniche di tipo
  passivo.

  Qualora si intercettino informazioni essenziali come le credenziali degli
  utenti (ad esempio le loro password) questo tipo di minaccia può anche
  portare a rischi ulteriori, fino alla \textit{usurpation}.  In generale si
  risponde a questo tipo di minacce con contromisure basate sulla crittografia
  che consentano di cifrare il traffico o i dati, vale a dire attraverso
  servizi dedicati al mantenimento della confidenzialità.

\item[\textsl{Alterazione}] si coprono in questa categoria le minacce relative
  un vasto insieme di attacchi miranti a modificare in maniera non autorizzata
  dati ed informazioni. Questo di nuovo porterebbe questa categoria nella
  classe della \textit{deception}, ma qualora si tratti di dati usati nel
  controllo del sistema di nuovo si potrebbero avere conseguenze in termini
  sia di \textit{disruption} che di \textit{usurpation}.

  Di norma gli attacchi usati in questa categoria di minacce si basano su
  tecniche attive, il caso esemplare è quello dell'intercettazione attiva, in
  cui si modifica il contenuto dei dati. I cosiddetti attacchi di
  \itindex{man-in-the-middle} ``\textit{man-in-the-middle}'', in cui
  l'attaccante si interpone fra due interlocutori per presentarsi come l'altro
  a ciascuno di essi, rientrano in questa tipologia.  In generale si risponde
  a questo tipo di minacce con contromisure volte a verificare l'integrità dei
  dati.

\item[\textsl{Mascheramento}] detto in gergo \itindex{spoofing}
  \textit{spoofing}, è la categoria di minacce basata sul presentarsi con una
  diversa identità, e pertanto attiene principalmente alla classe della
  \textit{deception}, ma qualora si riesca ad impersonare un amministratore o
  un utente privilegiato può sconfinare nella \textit{usurpation}. Appartiene
  a questa categoria il \itindex{phishing} \textit{phishing}, cioè il
  redirigere gli utenti su siti web che sembrano quelli di altre entità per
  ottenere informazioni di valore, mentre con \itindex{spoofing}
  \textit{spoofing} si tende ad indicare in maniera più specifica la
  falsificazione degli indirizzi dei pacchetti di rete.

  Sebbene in teoria possano essere passivi, attendendo semplicemente che
  l'utente si colleghi ad un servizio falsificato, per lo più gli attacchi in
  questa categoria sono di natura attiva, con scenari in cui l'attaccante si
  presenta sotto false credenziali o si spaccia per altri.  Di nuovo si
  risponde a questo tipo di minacce con contromisure volte a verificare
  l'integrità, che in questo contesto sono essenzialmente servizi di
  autenticazione che mirino a confermare l'identità degli attori in gioco.

\item[\textsl{Blocco o ritardo}] appartengono a questa categoria gli attacchi
  che mirano a ritardare l'uso dei servizi, a o bloccarli completamente.  La
  si può considerare una forma particolare di \textit{usurpation}, in quanto
  tende a manipolare le strutture informatiche per ottenere i suoi risultati,
  ma spesso gli attacchi di questa categoria vengono usati come supporto per
  attacchi di \textit{deception} in cui si tenta di sostituirsi al sistema che
  si è bloccato per ingannare l'utente.

  Gli attacchi in questa categoria sono sempre di natura attiva e sfruttano in
  generale delle debolezze dell'infrastruttura bersaglio; ma si tenga presente
  che in blocco dei servizi può derivare anche da debolezze intrinseche o
  difetti strutturali del sistema che ne causino il malfunzionamento. Si
  risponde a questa categoria di minacce con servizi mirati a garantire la
  disponibilità del sistema.
\end{basedescript}

In generale un sistema informatico deve essere in grado di garantire
protezioni da tutte queste minacce; per questo tutti i sistemi operativi
moderni e molte applicazioni forniscono degli opportuni servizi di sicurezza
(vedi sez.~\ref{sec:security_services}) il cui scopo è esattamente quello di
proteggersi contro questi rischi.

Se il mondo forse perfetto i servizi di sicurezza sarebbero infallibili, i
programmi non avrebbero errori e vulnerabilità e gli utenti si comporterebbero
sempre in maniera corretta e non malevola. Il mondo però non è perfetto, i
programmi hanno errori, i sistemi presentano malfunzionamenti e gli utenti
possono essere scorretti, per cui alle minacce illustrate in precedenza
corrispondono sempre una serie di attacchi possibili che possono realizzarle
concretamente.

Per capire meglio allora quali sono i rischi che si vanno a correre è
opportuno fornire una ulteriore classificazione, questa volta andando a
esaminare i vari tipi di attacchi che vengono usati nella pratica per violare
la sicurezza di un sistema informatico; un breve elenco dei principali è il
seguente, che ci servirà anche come glossario:
\begin{basedescript}{\desclabelwidth{3.2cm}\desclabelstyle{\nextlinelabel}}
\itindbeg{exploit} 

\item[\textit{Exploit}] è una espressione gergale che copre tutti quegli
  attacchi che sfruttano delle vulnerabilità presenti nei programmi dovute ad
  errori di programmazione, anche se talvolta la si usa per indicare
  semplicemente il successo nell'intrusione abusiva in un sistema attraverso
  una di queste vulnerabilità. In genere quello che succede è che inviando al
  programma dei dati in ingresso in una forma che non era stata presa in
  considerazione dal programmatore, si ha un errore.

  Questo può portare semplicemente al crash del programma, nel qual caso si ha
  un \itindex{Denial~of~Service~(DoS)} \textit{denial of service}, ma spesso è
  possibile, usando dei dati opportunamente forgiati, fare eseguire al
  programma del codice malevolo (il codice
  dell'\textit{exploit},\footnote{spesso questo è semplicemente un cosiddetto
    \textit{shellcode}, cioè un programma elementare il cui unico scopo è
    eseguire una shell per dare accesso al sistema compromesso.} appunto) con
  risultati che possono andare dalla sovrascrittura di un file al completo
  controllo di una macchina.

  Gli errori più comuni definiscono a loro volta ulteriori sottocategorie di
  attacchi. I più noti sono i cosiddetti \itindex{buffer~overflow}
  \textit{buffer overflow}, in cui inviando più dati di quanti previsti, in
  assenza degli opportuni controlli, si eccede la dimensione di un buffer
  precedentemente allocato consentendo l'esecuzione dell'\textit{exploit};
  questo attacco è descritto con estrema chiarezza in un articolo classico
  \cite{StS} di Phrack fin dal 1996, e nonostante ciò si continuano ad avere
  problemi di questo tipo. Altri tipi di \textit{exploit} sono gli
  \itindex{integer~overflow} \textit{integer overflow} dove lo stesso effetto
  è ottenuto per mancati controlli sulle dimensioni di un intero,\footnote{in
    questo caso si usa un intero che viene usato come indice per poter
    eseguire sovrascritture di dati in zone di memoria non previste.} gli
  \itindex{string~format} \textit{string format} in cui si abusa della
  formattazione in uscita di un dato.

  In generale si tende a dividere gli \textit{exploit} in locali e remoti, a
  seconda che per poterli realizzare sia necessario avere un accesso sulla
  macchina sul quale eseguire il programma vulnerabile o sia sufficiente
  eseguire l'attacco su una connessione via rete.  Ovviamente i rischi
  maggiori sono dovuti a questi ultimi. 

  In generale si tende ad inserire in questa categoria anche alcuni dei più
  comuni problemi della sicurezza informatica come i \textit{virus} ed i
  \itindex{worm} \textit{worm}. In sostanza si tratta della stessa tipologia
  di attacco per cui da una vulnerabilità di un programma si ottiene la
  possibilità di eseguire del codice il cui scopo in questo caso è quello di
  propagarsi verso altri computer. La differenza principale fra le due forme è
  che un \textit{virus} in genere cerca di inserirsi all'interno di altri
  programmi e si attiva con l'esecuzione di questi ed agisce localmente,
  mentre un \textit{worm} agisce principalmente via rete.

\itindend{exploit}

\itindex{backdoor}

\item[\textit{Backdoor}] si chiama così un attacco che consente di
  oltrepassare delle misure di protezione attraverso appunto una \textsl{porta
    sul retro}. In realtà non si tratta di un attacco, se per questo si
  intende una azione diretta volta a effettuare una violazione di sicurezza,
  quanto piuttosto di un meccanismo per mantenere insicuro un sistema. In
  genere ha due significati diversi a seconda del contesto. Quando riferito ad
  un algoritmo crittografico si intende la possibilità di decifrare i messaggi
  anche senza conoscere la chiave con cui sono stati cifrati;\footnote{è il
    caso del famoso \textit{clipper chip}, un processore crittografico che
    negli Stati Uniti era stato proposto per cifrare tutte le comunicazioni, e
    che prevedeva la possibilità di avere una chiave speciale che potesse
    decifrarle sempre, ad uso dell'FBI, che, anche per questo motivo, alla
    fine non è mai stato dispiegato.}  quando riferito ad un sistema
  informatico si intende del codice che viene inserito al suo interno per
  permettere un accesso scavalcando i normali criteri di autenticazione.

  Il secondo è il caso più comune, ed è il metodo che viene usato molto spesso
  da chi si introduce abusivamente in un sistema dopo un \textit{exploit} per
  garantirsi un accesso, in genere da remoto, anche quando la via originaria
  che ne aveva consentito l'ingresso non è più disponibile, ad esempio perché
  il programma vulnerabile ad un \textit{exploit} è stato aggiornato.

  Nel caso di sistemi Unix questi vengono in genere chiamati \itindex{rootkit}
  \textit{rootkit} perché servono a garantire un accesso da amministratore, ed
  oltre ad una \textit{backdoor} prevedono anche ulteriori meccanismi volti a
  mascherare la presenza di quest'ultima. Nel caso Windows esistono programmi
  analoghi; quando la \textit{backdoor} viene inserita all'interno di un altro
  programma, che si cerca di far eseguire all'utente, in genere si parla di
  \itindex{trojan} \textit{trojan}.\footnote{il nome deriva ovviamente
    dall'idea del cavallo di Troia.}

  Una \textit{backdoor} comunque non è detto debba derivare direttamente
  dall'installazione abusiva di un programma apposito da parte di un intruso.
  Molti programmi infatti contengono delle \textit{backdoor} inserite dagli
  stessi programmatori che li hanno realizzati, messe lì per consentire loro
  un accesso diretto. Nel caso di software libero sono stati scoperti
  tentativi di inserimento di \textit{backdoor} (in particolare ne è stata
  scoperta una all'interno di un database proprietario di cui sono stati
  rilasciati i sorgenti, presente presumibilmente da molti anni), ma nei vari
  casi in cui sono state trovate sono state anche immediatamente rimosse; per
  i programmi proprietari, per i quali non si ha l'accesso al codice, non si
  potrà mai essere certi della loro assenza, mentre sono noti molti esempi
  concreti di una loro presenza.
  
  Inoltre si tenga presente che è possibile creare delle \textit{backdoor}
  anche senza modificare direttamente il codice di un programma. L'esempio
  classico è quello creato da Ken Thompson, uno dei creatori di Unix,
  considerato fra i più grandi scienziati nel campo dell'informatica, che
  aveva inserito all'interno del compilatore del C\footnote{il C è il
    linguaggio con cui è stato creato Unix, e con cui sono realizzati la gran
    parte dei sistemi operativi e dei programmi di sistema.} un meccanismo per
  cui veniva inserita automaticamente una \textit{backdoor} tutte le volte che
  questo veniva usato per compilare il programma di accesso al sistema. Era
  anche stata creata una versione dello stesso compilatore in grado di
  replicare questo comportamento nei compilatori creati tramite il compilatore
  originale.

  In questo modo nel codice sorgente, a parte quello del compilatore originale
  da cui si era iniziato il processo, non vi sarebbe stata alcuna traccia
  della \textit{backdoor}, rilevabile solo ad una analisi, molto meno
  probabile e comunque molto più complessa da fare, del codice
  eseguibile. Questo esempio illustra in maniera molto chiara quanto accennato
  in sez.~\ref{sec:security_intro}, per cui è essenziale, per valutare
  l'integrità di un sistema, il grado di fiducia che si può riporre
  nell'origine di dati ed informazioni e negli strumenti per il loro utilizzo.

\itindend{backdoor}

\item[\textsl{Intercettazione}] corrispondono alla omonima categoria di
  minacce e sono gli attacchi che mirano a ottenere informazioni, in genere
  relative alle credenziali di accesso o a dati riservati, intercettando le
  comunicazioni.  Benché usualmente in questo caso si tenda a pensare a
  problematiche non strettamente attinenti all'ambito informatico e più vicine
  al mondo dello spionaggio, come microfoni, microspie, intercettazioni
  telefoniche, telecamere nascoste, ecc. occorre comunque valutare questo tipo
  di attacchi; le più accurate misure di sicurezza informatica servono a poco
  infatti se è possibile ad esempio intercettare il segnale di una telecamera
  che riprende la tastiera di chi inserisce una password.

  Inoltre esistono tecnologie specifiche, realizzate proprio per intercettare
  i dati all'interno di sistemi informatici, come le reti e gli stessi
  computer.  Un esempio sono i \itindex{keylogger} \textit{keylogger},
  apparecchi\footnote{per analogia si chiamano così anche i programmi che
    forniscono la stessa funzionalità via software, spesso presenti nei
    \textit{rootkit}.}  in grado di registrare tutte le pressioni dei tasti
  eseguite su una tastiera, o il sistema \textit{Tempest} che è in grado di
  intercettare le emissioni elettromagnetiche dei monitor e replicare a
  distanza quello che appare sullo schermo.

  Non è inoltre detto che si debba arrivare all'utilizzo di apparecchiature di
  intercettazione specializzate, esistono infatti anche programmi dedicati
  all'intercettazione che possono essere eseguiti su un qualunque computer,
  come gli \itindex{sniffer} \textit{sniffer} (di cui parleremo in
  sez.~\ref{sec:ids_sniffer}) che permettono di intercettare il traffico che
  passa su di una rete locale,\footnote{il rischio è ancora più forte se la
    rete è wireless e per inserirsi non è neanche necessaria la presenza
    fisica all'interno dei locali.} o i \textit{keylogger} o altri programmi
  dedicati che possono intercettare tutte le operazioni compiute su un
  desktop.\footnote{ad esempio il programma VNC, spesso usato per
    l'amministrazione remota, può essere usato anche a questo scopo.}

  Benché molti dei problemi relative all'intercettazione possano essere
  risolti con l'uso della crittografia per rendere inutilizzabili le
  informazioni intercettate, occorre comunque essere consapevoli che questa è
  una soluzione parziale. Per quanto sia sicuro un algoritmo crittografico
  esso è normalmente soggetto ai cosiddetti attacchi di
  \itindex{man-in-the-middle} \textit{man-in-the-middle} in cui si
  intercettano tutte le informazioni scambiate fra due capi di una
  comunicazione presentandosi a ciascuno dei due come l'altro. Esistono
  modalità per ridurre questo rischio, ma in generale non è possibile
  cancellarlo completamente.


\item[\textsl{Ingegneria sociale}] per quanto raffinato possa essere un
  sistema di controllo, per quanto accuratamente possa essere stato scritto il
  software, gli essere umani possono sempre sbagliare, ma soprattutto essere
  ingannati, usando quella che in gergo viene chiamata \textit{social
    engineering}.  Per cui si può utilizzare la più stretta delle politiche di
  accesso ed il controllo più stretto sui firewall e l'antivirus più potente,
  ma se si convince la segretaria del capo a far girare un programma
  spacciandosi per il nuovo sistemista della sede secondaria che manda un
  aggiornamento, e questo in realtà è un programma che permette di accedere
  alla rete interna, tutte le precauzioni prese saranno inutili.

  Gli attacchi di \itindex{social~engineering} \textit{social engineering}
  sono senz'altro quelli più difficili da contrastare, proprio perché non sono
  categorizzabili e non hanno a che fare con l'organizzazione di un sistema
  informatico, ma con quella delle persone. Le uniche contromisure possibili
  pertanto sono l'educazione e la formazione, ma anche queste non possono
  coprire tutte le possibilità. Inoltre rendere estremamente rigide le
  politiche di sicurezza rischia anche di essere controproducente, in quanto
  diventa molto più facile che queste, per la loro scomodità, vengano ignorate
  dalle persone, lasciando così più spazi di quanto non ci sarebbero con
  politiche più \textsl{sostenibili}.
\end{basedescript}


\subsection{I criteri per una politica di sicurezza}
\label{sec:security_policy}

Probabilmente il criterio fondamentale che deve essere compreso per poter
affrontare il tema della sicurezza è quello che Bruce Schneier, crittografo e
matematico, architetto dell'algoritmo Blowfish, uno dei maggiori esperti
mondiali in ambito di crittografia e sicurezza informatica, ha espresso con la
frase: ``\textsl{la sicurezza è un processo, non un prodotto}''. Non esiste
cioè un prodotto che possa risolvere una volta per tutte le problematiche di
sicurezza, ma queste devono essere affrontate all'interno di un processo che
preveda una loro valutazione, la valutazione dei relativi rischi, dei costi
delle contromisure, ed una continua verifica e ridispiegamento e affinamento
delle misure adottate.

Si tratta cioè di realizzare che il primo passo da fare per affrontare il tema
è quello di definire una \textsl{politica di sicurezza}, cioè definire le
proprie priorità, le linee guida per realizzarle e le modalità per verificarne
l'effettività.  Un elenco di concetti da tenere ben presenti quando si vuole
impostare una politica di sicurezza è il seguente:
\begin{itemize}
\item \textsl{la sicurezza assoluta non esiste}; se un attaccante è
  sufficientemente determinato e ha risorse sufficienti potrà superare
  qualunque misura di sicurezza abbiate realizzato, ad esempio puntandovi una
  pistola alla testa... Pertanto chiunque propagandi la nuova rivoluzionaria
  soluzione a tutti i problemi della sicurezza vi sta vendendo ``\textsl{olio
    di serpente}''.\footnote{traduzione improvvisata dell'espressione gergale
    ``\textit{snake oil}'', che origina dalle medicine miracolose dei
    \textit{western} che guarivano qualunque cosa.}

\item \textsl{il miglioramento della sicurezza è asintotico}; questo significa
  che si possono ottenere buoni risultati di sicurezza anche con investimenti
  modesti, ma più si vuole elevare il livello di sicurezza più i costi
  aumentano. Per questo una valutazione da fare prima di realizzare una
  qualunque misura di sicurezza è quella dell'analisi dei rischi che si
  vogliono coprire e dei costi che si intendono affrontare. Spesso per
  ottenere un piccolo miglioramento della sicurezza si devono affrontare dei
  costi maggiori, sia in termini di infrastrutture che di organizzazione, di
  quelli sostenuti per creare l'infrastruttura esistente.

\item \textsl{la sicurezza e la facilità d'uso sono esigenze contrastanti};
  poter lasciare la porta aperta è molto più comodo che portare tre mazzi di
  chiavi e ricordarsi dieci combinazioni diverse. Perché una politica di
  sicurezza sia efficace occorre che le sue misure siano praticabili e
  ragionevoli. Potete imporre password composte di lettere casuali lunghe 20
  caratteri da cambiare ogni mese, ma rischiate che la gente per ricordarsele
  se le scriva su un foglietto sotto la tastiera.
\end{itemize}

Per poter avere una indicazione dei passi da fare nell'implementazione di una
politica di sicurezza faremo riferimento allo standard ISO/BS-17799 relativo
all'adozione di un sistema di gestione della sicurezza delle informazioni. Il
processo previsto dallo standard è piuttosto complesso dal punto di vista
organizzativo e burocratico, simile come concetti a quelli della
certificazione di qualità ISO-9000. Quello che interessa però non sono tanto i
dettagli specifici quanto i concetti generali che possono servire come linee
guida per la creazione di una politica di sicurezza.

Il punto fondamentale chiarito dallo standard è che la gestione della
sicurezza deve essere vista come parte integrante del funzionamento dei propri
processi interni; ci deve cioè essere una decisione strategica in cui si
sceglie di occuparsi delle problematiche relative alla sicurezza e si fa sì
che queste vengano considerate all'interno di tutte le procedure
organizzative.

Un secondo punto significativo è che lo standard adotta il modello di
sicurezza come processo, formalizzato un modello ciclico detto PDCA
(dall'inglese \textit{Plan-Do-Check-Act}), i cui concetti fondamentali sono
riassumibili nei quattro punti:
\begin{basedescript}{\desclabelwidth{2.0cm}\desclabelstyle{\nextlinelabel}}
\item[\textsl{Pianifica}] è fondamentale capire quali sono i requisiti di
  sicurezza sulla base delle proprie attività, e deve essere chiara la
  necessità di stabilire politiche e obiettivi; occorre cioè una analisi dei
  rischi ed una pianificazione della gestione della sicurezza.
\item[\textsl{Fai}] occorre implementare le opportune misure di sicurezza nel
  contesto delle normali procedure operative; devono cioè essere integrate nei
  propri processi organizzativi e funzionali.
\item[\textsl{Controlla}] occorre tenere sotto controllo la congruità delle
  politiche di sicurezza, il funzionamento sul campo delle misure adottate ed
  infine verificarne continuamente l'efficacia e le prestazioni.
\item[\textsl{Agisci}] sulla base dei controlli effettuati occorre migliorare
  continuamente processi e misure di sicurezza, ripetendo da capo il ciclo di
  pianificazione, implementazione, verifica, aggiornamento.
\end{basedescript}

Il concetto fondamentale sottolineato in questo schema è che non basta
pianificare ed implementare una politica di sicurezza; questi sono solo i
primi due passi, dopo i quali essa deve anche essere tenuta sotto controllo,
valutata e continuamente aggiornata.

In genere il primo passo nella pianificazione di una politica di sicurezza è
quello di eseguire una analisi dei rischi. La valutazione del rischio è
probabilmente una delle parti più complesse dell'operazione: devono essere
identificati i beni che si vogliono proteggere, in questo caso dati ed
informazioni gestiti attraverso i sistemi informatici ed essere identificate e
valutate le minacce. 

Alla fine la valutazione consiste nel prodotto fra il valore dei beni soggetti
a rischio e la probabilità che esso possa concretizzarsi, e per rischi e
minacce occorre anche considerare non solo gli attacchi deliberati ma anche i
possibili incidenti e le eventuali catastrofi naturali. La difficoltà della
procedura sta appunto nell'identificare tutte queste variabili. Non trattando
qui delle metodologie per l'analisi del rischio, non entreremo ulteriormente
in detto argomento.

Una volta individuati i beni ed i rischi, occorrerà valutare le misure,
organizzative e funzionali, che si possono porre in atto per eliminare o
ridurre gli stessi ad un valore ritenuto ragionevole. Non è detto che per un
qualunque rischio si debba prevedere una misura di sicurezza, fra le decisioni
possibili infatti c'è sempre quella di accettare il rischio (ad esempio quando
le misure dovessero avere un costo superiore al bene da proteggere), così come
quella di trasferire ad altri il rischio (ad esempio facendo una
assicurazione).

Il secondo passo della pianificazione è quello della individuazione delle
procedure funzionali relative alle misure di sicurezza che si vogliono mettere
in atto; queste in genere vengono suddivise in tre categorie generali:
\begin{basedescript}{\desclabelwidth{2.5cm}\desclabelstyle{\nextlinelabel}}
\item[\textsl{Prevenzione}] spesso ci si limita a pensare a questo aspetto,
  quello che cioè mira a prevenire una violazione di sicurezza come
  procedimenti di autorizzazione, firewall, antivirus, ecc. Ovviamente questa
  è la parte principale di un qualunque insieme di misure di sicurezza, ma
  dato che la sicurezza assoluta non esiste, per una politica di sicurezza
  sostenibile sono necessarie anche misure nelle due categorie successive.
\item[\textsl{Rilevamento}] per ridurre al minimo i danni causati da una
  eventuale violazione di sicurezza è cruciale intervenire il più
  tempestivamente possibile; per questo uno degli aspetti cruciali di una
  qualunque politica di sicurezza resta quello delle misure prese per rilevare
  eventuali violazioni (IDS, analisi dei log, scanner) in modo da minimizzare
  i tempi di intervento.
\item[\textsl{Recupero}] infine una volta che si è subita una violazione di
  sicurezza è indispensabile poter disporre di una strategia che permetta di
  recuperare l'integrità e l'affidabilità dei sistemi e delle informazioni; un
  aspetto che spesso non viene adeguatamente pianificato. Rientrano in questa
  categoria le procedure per il backup e il \textit{disaster recovery}.
\end{basedescript}

Infine nella creazione di una politica di sicurezza occorrerà anche definire
le modalità con cui si gestiscono di dati ed informazioni ed i relativi
criteri di accesso, cioè la parte che attiene alla identificazione dei
processi di gestione e dei ruoli di coloro che sono incaricati di eseguirli.
In questo caso si fa riferimento ad alcuni criteri generici che sono chiamati
i \textsl{pilastri} della sicurezza, intesa dal punto di vista organizzativo:
\begin{basedescript}{\desclabelwidth{3.9cm}\desclabelstyle{\nextlinelabel}}
\item[\textit{Classification}] risponde alla necessità di identificare dove è
  richiesta una maggiore sicurezza. Si applica in genere ai requisiti di
  confidenzialità e prevede una classificazione verticale di informazioni e
  sistemi a seconda della loro criticità e di utenti e processi in base al
  loro livello di affidabilità. Un incaricato o un processo deve poter
  accedere ad un dato di un certo livello di sensibilità solo se ha un
  corrispondente livello di affidabilità.

\item[\textit{Need to know}] risponde alla necessità di definire quali sono i
  dati e le informazioni a cui un utente o un processo deve poter accedere per
  potere eseguire i suoi compiti. In questo caso la classificazione è di tipo
  orizzontale e attiene alle divisioni operative (comparti, funzioni, ecc).
  In questo caso si tratta di identificare quale è lo stretto necessario allo
  svolgimento dei compiti assegnati e fornire accesso solo a quello, evitando
  così possibili abusi di privilegi non necessari.

\item[\textit{Separation of duties}] risponde alla necessità di suddividere
  organizzativamente alcuni compiti, in modo da minimizzare gli effetti di
  possibili errori o frodi. In sostanza si tratta di separare alcuni compiti
  (il caso classico è chi sta alla cassa e chi conta i soldi a fine giornata)
  in modo che la suddivisione di responsabilità renda molto più difficile un
  atto fraudolento.
\end{basedescript}


\section{Crittografia e sicurezza}
\label{sec:cryptography}

Daremo in questa sezione una introduzione molto generica alle basi della
crittografia, descrivendone i concetti generali e illustrando le funzionalità
e le caratteristiche dei vari algoritmi e delle varie tecniche crittografiche
che vengono utilizzate per applicazioni relative alla sicurezza.


\subsection{Introduzione}
\label{sec:crypto_info}

La crittografia\footnote{la parola deriva dal greco e significa
  ``\textsl{scrittura segreta}''.} è una disciplina antichissima, e riguarda
l'arte di trasmettere messaggi il cui contenuto sia stato opportunamente
``\textsl{cifrato}'' in modo che a chi esegue una eventuale intercettazione
essi risultino inintelligibili, mentre restino comprensibili per il legittimo
destinatario che sia in grado di \textsl{decifrarne} il contenuto.

Uno degli esempi più antichi è quello usato dai condottieri cretesi nelle
campagne militari, che prevedeva messaggi scritti su strisce di stoffa
avvolte su un cilindro di legno di un diametro fissato, il cui contenuto
diveniva leggibile solo quando riavvolte sul cilindro del destinatario.

In generale si pensa alla crittografia come ad una tecnica che attiene al
mantenimento della confidenzialità delle informazioni, oggi però si tende a
richiedere anche qualcosa in più; per questo una definizione utilizzata
comunemente per la crittografia moderna è quella data da Bruce Schneier in
\cite{ApplCrypt}:

\begin{quote}
  la crittografia è ``\textsl{la disciplina che studia la trasformazione di
    dati allo scopo di nascondere il loro contenuto semantico, impedire il
    loro utilizzo non autorizzato, o impedire qualsiasi loro modifica non
    rilevabile}''
\end{quote}

In generale qualunque tecnica crittografica si avvale di un \textsl{algoritmo
  crittografico} che attraverso una serie di trasformazioni consente il
passaggio (la \textsl{cifratura}) da un \textsl{testo in chiaro}, contenente
il messaggio che si vuole spedire, ad un \textsl{testo cifrato} da trasmettere
effettivamente su un canale su cui può essere intercettato.  Chi riceverà il
testo cifrato dovrà poi fare il passaggio inverso (cioè \textsl{decifrare})
per ricavare il testo in chiaro.

Tradizionalmente la crittografia si basava sulla segretezza del metodo
utilizzato per cifrare e decifrare i messaggi, secondo lo schema illustrato in
fig.~\ref{fig:crypto_traditional}; uno degli esempi classici è quello del
\index{cifrario~di~Cesare}\textsl{cifrario di Cesare} che consiste nello
scrivere un messaggio sostituendo a ciascuna lettera quella che la segue di
tre posti nell'ordine alfabetico.\footnote{che è ancora in uso, come semplice
  tecnica per oscurare un testo, nel cosiddetto \textit{ROT-13} in cui la
  rotazione è fatta su tredici posti invece che su tre.} Una volta noto
l'algoritmo decifrare un messaggio è banale.

\begin{figure}[htb]
  \centering
  \includegraphics[width=8cm]{images/crypto_old}
  \caption{Schema di funzionamento di un algoritmo crittografico tradizionale.}
  \label{fig:crypto_traditional}
\end{figure}

Al giorno d'oggi nessuno si basa più su un sistema crittografico fondato sulla
segretezza di un algoritmo; questo perché ci sono degli evidenti svantaggi dal
punto di vista pratico nel sostituire un algoritmo in caso di scoperta, o
nell'usarne uno diverso per ogni canale di comunicazione che si vuole
mantenere separato.  Inoltre la verifica della effettiva validità
dell'algoritmo, cioè della sua capacità di rendere davvero inintelligibile il
testo cifrato, non può che essere fatta in ambiti molto ristretti, visto che
non ne può essere divulgato il funzionamento senza comprometterlo.

Per questo fin dal secolo scorso è incominciato a diventare chiaro che era
necessario puntare su una diversa concezione che prevedesse algoritmi di
cifratura pubblici le cui capacità di rendere illeggibile un messaggio si
basassero solo sulla segretezza di una \textsl{chiave} di cifratura.  In
questo caso il testo cifrato viene prodotto dal testo in chiaro attraverso
delle manipolazioni che prevedono la presenza di una
``\textsl{chiave}'',\footnote{esistevano già algoritmi di cifratura di questo
  tipo, in fondo anche nel caso dell'antico metodo dei condottieri cretesi
  c'era una chiave, che era il bastone cilindrico.} nota la quale è possibile
riottenere il testo in chiaro. Senza la chiave anche con la conoscenza
dell'algoritmo di cifratura deve essere praticamente impossibile riottenere il
testo in chiaro (vedremo più avanti cosa si intende per praticamente).

Un'analisi dettagliata degli algoritmi di crittografia va ben al di là degli
scopi di queste dispense, ma una breve introduzione generica è necessaria per
approfondire la comprensione delle varie applicazioni che di essa si fanno nel
campo della sicurezza.  In particolare è utile comprendere quali sono i
criteri generali che permettono di stabilire la validità di un algoritmo
crittografico.

Fra questi, come appena accennato, ce n'è uno da scartare in partenza: la
segretezza. Periodicamente c'è chi proclama di disporre di un nuovo
segretissimo algoritmo crittografico super-sicuro. Dato che è segretissimo
però nessun crittografo esperto potrà mai dirvi se è sicuro davvero. I veri
algoritmi sicuri sono quelli che sono risultati tali dopo essere stati
analizzati in tutti i loro dettagli, e lo sono per la loro robustezza
intrinseca e non per il non sapere come sono realizzati.

La disciplina che studia la robustezza degli algoritmi crittografici si chiama
\index{crittanalisi} \textsl{crittanalisi}; i criteri di base per cui si
considera un algoritmo sicuro sono quelli che gli permettono di resistere alle
diverse tipologie di attacco da parte dei \textsl{crittanalisti}. Questi
attacchi vengono classificati nelle quattro categorie seguenti:
\begin{itemize}
\item \textsl{attacchi a testo in cifra noto}: è l'attacco più semplice, in cui
  si analizzano un certo numero di messaggi cifrati per ricavarne le
  informazioni necessarie a realizzare una delle violazioni che illustreremo a
  breve. In genere si tratta di attacchi su basi statistiche, che cercano di
  rivelare informazioni sul testo o sulla chiave utilizzando il fatto che nel
  testo in chiaro non tutti i caratteri compaiono con la stessa frequenza. In
  questo caso basta intercettare i messaggi cifrati, ed in genere più se ne
  intercetta più è facile eseguire questo tipo di attacco.

\item \textsl{attacchi a testo in chiaro noto}: in questo caso oltre ai
  messaggi cifrati si ha a disposizione anche il testo in chiaro che li ha
  generati. Ovviamente questo tipo di attacco comporta nella pratica una
  esecuzione più complessa, dovendosi ottenere, oltre ai messaggi cifrati
  anche la relativa conoscenza del testo in chiaro.

\item \textsl{attacchi a scelta di testo in chiaro}: rispetto al caso
  precedente in questo tipo di attacchi si è in grado non solo di conoscere
  alcuni messaggi passati sul canale, ma di scegliere anche il loro contenuto.
  Sebbene questo tipo di attacco possa sembrare impossibile da realizzare in
  pratica sono noti molti casi in cui lo si è eseguito con relativa facilità,
  ad esempio fornendo informazioni note che si sapeva sarebbero passate sul
  canale cifrato.

\item \textsl{attacchi a scelta adattativa di testo in chiaro}: oltre a quanto
  previsto nel caso precedente qui si richiede anche che sia possibile
  scegliere il testo dei messaggi da cifrare in base ai messaggi cifrati
  ottenuti per quelli scelti in precedenza. È ovviamente il più complesso da
  realizzare in quanto suppone la capacità di poter inserire arbitrariamente
  del testo sul canale cifrato.
\end{itemize}

A fronte di ciascuno di questi attacchi sono possibili vari livelli di
successo, quello che in gergo si chiama una \textsl{rottura} dell'algoritmo.
Anche questi casi sono classificati, e vengono utilizzate le seguenti quattro
categorie generiche:
\begin{itemize}
\item \textsl{rottura totale}: si riesce a determinare la chiave di cifratura,
  e si ha così l'accesso completo a tutto quanto viene cifrato e la capacità
  di creare messaggi cifrati a nostra volta.

\item \textsl{deduzione globale}: si riesce a individuare un algoritmo
  alternativo che decodifica tutti i messaggi anche senza conoscere la chiave.

\item \textsl{deduzione locale}: si riesce a decifrare alcuni messaggi.

\item \textsl{deduzione di informazione}: si riesce ad avere una qualche
  informazione sul testo in chiaro o sulla chiave.
\end{itemize}

Oltre a quelli citati esiste un ulteriore attacco che è sempre possibile e che
porta sempre ad un successo totale, l'attacco detto
\index{attacco~a~forza~bruta} \textsl{a forza bruta}.  Questo consiste
semplicemente nel provare tutte le chiavi possibili fintanto che dal testo
cifrato non si riottiene un testo in chiaro. Ovviamente benché questo attacco
sia sempre possibile, la scelta di una chiave sufficientemente complessa
permette di renderlo inutile sul piano pratico.

Un algoritmo crittografico robusto deve essere allora in grado di resistere a
tutti gli attacchi delle categorie precedentemente esposte per tutti i livelli
di successo appena illustrati.  In pratica questo significa che un buon
algoritmo di crittografia è un algoritmo che rende il tentativo di decifrare
il messaggio senza la chiave dello stesso ordine di difficoltà di un attacco a
forza bruta.

Si tenga presente però che in molti casi, quando la chiave è una
\textsl{parola chiave}, si può utilizzare una versione molto efficace
dell'attacco a forza bruta, detta \index{attacco~a~dizionario} \textsl{attacco
  a dizionario}, in cui invece di provare tutte le chiavi possibili, se ne
prova un numero molto più limitato, fra quelle presenti in un dizionario; se
la chiave scelta non è sufficientemente \textsl{complessa} il compito si
semplifica notevolmente e spesso è un gioco da ragazzi trovarla. In questo
caso non è l'algoritmo ad essere debole, quanto la chiave stessa, e questo è
un problema che c'è sempre con qualunque algoritmo.

Un esempio elementare di algoritmo debole è quello dell'enigma cifrato della
settimana enigmistica, in questo caso la chiave è la tabella delle
corrispondenze fra lettere e numeri. Come narrato da Edgar Allan Poe nel
racconto \textsl{Lo Scarabeo d'oro}, e come chiunque si diletti di enigmistica
avrà notato, basta fare una semplice analisi statistica dei numeri che
ricorrono di più per individuare le lettere principali del testo, e con un po'
di tentativi diventa semplice decifrare completamente il messaggio.

Un algoritmo che apparentemente sembrerebbe forte, tanto che a lungo è stato
ritenuto indistruttibile, è il cosiddetto \index{cifrario~di~Vigenère}
cifrario di Vigenère\footnote{questa è una attribuzione tardiva fatta nel
  1700, in realtà il meccanismo è stato ideato nel 1553 da Giovan Batista
  Belaso.}  in cui si usa una parola chiave per cifrare un testo. Il
meccanismo prevede che si affianchino il testo e la parola chiave, ripetuta
ciclicamente per tutta la lunghezza del testo, prendendo come risultato della
cifratura di ciascuna lettera del testo la lettera che lo segue nell'alfabeto
di tante posizioni quante sono quelle della lettera corrispondente della
parola chiave.\footnote{se cioè la lettera del testo è \texttt{C} e quella
  della chiave \texttt{B} il risultato sarà \texttt{E}.}

Per quanto possa sembrare difficile da decifrare, con una sufficiente quantità
di messaggi questo cifrario è suscettibile di analisi statistiche non
particolarmente complesse.\footnote{anche questo cifrario ha una sua notorietà
  letteraria, essendo stato usato da Jules Verne in vari suoi racconti.} Non
può comunque essere considerato robusto essendo completamente vulnerabile ad
attacchi con testo in chiaro, nel qual caso diventa immediato trovare la
chiave.

Nella crittografia moderna sono stati ideati vari algoritmi di cifratura;
tutti si basano su elaborazioni attinenti ad una certa classe di problemi
matematici. Alcuni algoritmi hanno mostrato, in seguito a successive analisi,
diversi gradi di debolezza, ma quelli di uso più comune non ne hanno finora
dimostrata alcuna. Dal punto di vista teorico però non esiste nessuna
dimostrazione che detti algoritmi siano effettivamente robusti. Tutto quello
che si può dire è che allo stato attuale delle conoscenze non esiste alcun
modo, né si ritiene che possa esistere, per romperli, non si ha però la
certezza matematica di tutto ciò, con una eccezione.

Esiste infatti, ed è noto da molto tempo, un algoritmo matematicamente
indistruttibile, chiamato OTP \itindex{One~Time~Pad~(OTP)} (\textit{One Time
  Pad}).  Questo consiste semplicemente nell'avere una chiave completamente
casuale più lunga del messaggio stesso, con la quale questo viene cifrato.
Fintanto che la chiave è più lunga del messaggio, è completamente casuale e
viene usata \textsl{una sola volta} non esiste modo, se non la conoscenza
della chiave stessa, di decifrare il messaggio.

Benché sia stato usato in varie occasioni, il problema di base di questo
algoritmo è che sul piano del suo utilizzo pratico ci sono delle difficoltà
enormi consistenti nel doversi scambiare precedentemente quantità di chiavi
sufficienti a coprire tutto quello che si cifrerà in seguito, per cui, per
banali esigenze di natura gestionale, quando si parla di crittografia si fa
sempre riferimento ad uno degli algoritmi che tratteremo nelle sezioni
seguenti.


\subsection{La crittografia a chiave simmetrica}
\label{sec:crypto_symmetric}

La crittografia moderna nasce in sostanza nel dopoguerra con il lavoro di
Claude Shannon,\footnote{che in un articolo del 1949 (vedi
  \cite{ShannonCrypt}) ha posto le basi teoriche della crittografia moderna.}
uno dei più grandi geni matematici del ventesimo secolo, i cui lavori han
posto i fondamenti della teoria delle comunicazioni. Ma a lungo lo studio di
questa materia è stato mantenuto segreto dai governi, in particolare nel caso
degli Stati Uniti era appannaggio della NSA.\footnote{acronimo di
  \textit{National Security Agency}, che per la sua segretezza è stata
  sarcasticamente chiamata anche \textit{No Such Agency}.}

Una classificazione molto grossolana degli algoritmi di crittografia moderni è
quella che li divide in due categorie principali, gli algoritmi a
\textsl{chiave simmetrica}, che vedremo in questa sezione, e quelli a
\textsl{chiave asimmetrica}, che vedremo nella prossima.

Il primo algoritmo crittografico moderno distribuito pubblicamente è il
\itindex{Data~Encryption~Standard~(DES)} DES (\textit{Data Encryption
  Standard}), proposto dalla IBM in risposta ad un bando dell'allora
\textit{National Bureau of Standards} statunitense per la creazione di un
sistema di comunicazione sicura ad uso di banche e grandi organizzazioni
finanziarie.\footnote{l'algoritmo ha una storia curiosa, in quanto una prima
  versione era stata considerata troppo ``forte'' per cui ne fu ridotta la
  dimensione della chiave; inoltre esso fu rivisto dalla NSA e a lungo c'è
  stato il sospetto, dimostratosi infondato ad analisi successive, che vi
  fosse stata inserita una qualche \textit{backdoor}.}

Il DES è l'esempio classico di quello che viene chiamato un \textsl{algoritmo
  a chiave simmetrica}, e funziona secondo lo schema illustrato in
fig.~\ref{fig:crypto_symmetric}.  Questa è la tipologia di algoritmo
crittografico più nota, quella a cui si pensa naturalmente quando si parla di
crittografia. La \textsl{crittografia a chiave simmetrica} si basa sull'uso di
una chiave unica condivisa fra mittente e destinatario, che per questo la si
dice simmetrica, da mantenere segreta.  La conoscenza della chiave permette
sia di cifrare che di decifrare il messaggio, senza di essa il messaggio è
incomprensibile.

\begin{figure}[htb]
  \centering
  \includegraphics[width=10cm]{images/crypto_symm}
  \caption{Schema di funzionamento di un algoritmo crittografico a chiave
    simmetrica.}
  \label{fig:crypto_symmetric}
\end{figure}


\itindbeg{block cipher}

Il DES appartiene ad una classe di algoritmi detti \textit{block cipher}
(\textsl{cifrari a blocchi}); questi prevedono che la cifratura avvenga per
blocchi di dati di dimensione fissa (la dimensione tipica è di 64 bit) che
vengono cifrati con l'applicazione dell'algoritmo di cifratura. Questo
comporta che il testo in chiaro deve essere di dimensione multipla del blocco
di dati elementare. Spesso non è così e deve essere per questo completato con
degli opportuni bit di riempimento, detti \textit{padding}.

I \textit{block cipher} hanno il vantaggio di poter essere facilmente
parallelizzati, ma presentano, se usati senza accortezza, il notevole
svantaggio di essere facilmente soggetti ad attacchi di crittanalisi basati
sul fatto che due blocchi uguali di testo in chiaro producono lo stesso testo
cifrato.\footnote{questa classe di attacchi vanno sotto il nome di
  \textit{reply block}.}  Per ovviare a questo tipo di attacchi si possono
però usare meccanismi di \textit{feedback}, il più comune è il cosiddetto
\itindex{Cipher~Block~Chaining~(CBC)} CBC (\textit{Cipher Block Chaining}),
prevede che ciascun blocco in chiaro, prima di essere cifrato, venga
opportunamente ``\textsl{sommato}''\footnote{l'operazione matematica usata è
  lo XOR aritmetico, che prevede che per ciascun bit dei due operandi la
  ``\textsl{somma}'' dia 1 se questi sono diversi e 0 se sono uguali.} con il
blocco in cifra calcolato al passo precedente.\footnote{inoltre per il primo
  blocco viene usato un valore casuale, detto \textsl{vettore di
    inizializzazione} che viene trasmesso insieme al messaggio.} In questo
modo allo stesso testo in chiaro corrisponderanno sempre testi cifrati diversi
e scorrelati fra di loro.

\itindend{block cipher}

\itindbeg{stream cipher}

Una seconda classe di algoritmi a chiave simmetrica sono i cosiddetti
\textit{stream cipher} (\textsl{cifrari a flusso}), che in contrapposizione ai
precedenti \textit{block cipher}\footnote{in realtà esistono procedimenti di
  \textit{feedback} (CFB e OB) che permettono di trasformare un qualunque
  \textit{block cipher} in uno \textit{stream cipher}.} possono operare su un
flusso indistinto di dati. In genere il meccanismo di funzionamento di uno
\textit{stream cipher} è quello della generazione di una sequenza
\textsl{pseudocasuale}\footnote{si chiama così un numero apparentemente
  casuale ottenuto però attraverso un preciso algoritmo matematico attraverso
  il valore di un numero iniziale, detto \textsl{seme}; nel caso di uno
  \textit{stream cipher} il seme corrisponde alla chiave, e la sequenza
  generata deve essere crittograficamente robusta secondo i criteri illustrati
  in sez.~\ref{sec:crypto_info}.} di bit, che vengono usati per cifrare il
testo in chiaro con una opportuna operazione matematica (in genere uno XOR
aritmetico).

\itindend{stream cipher}

Il più noto degli algoritmi a chiave simmetrica resta il DES, che si è
dimostrato robusto; esso però soffre di un grave problema dovuto alla
dimensione troppo ridotta della chiave. Questo al giorno d'oggi rende insicuro
questo algoritmo, non tanto per la presenza di vulnerabilità nello stesso,
quanto per il fatto che con la potenza di calcolo attualmente disponibile è
relativamente facile eseguire un attacco a forza bruta in tempi ragionevoli.

Essendo nota questa debolezza del DES negli anni sono stati introdotti altri
algoritmi di crittografia, che prevedessero delle dimensioni delle chiavi di
cifratura di lunghezza adeguata a rendere totalmente impraticabili attacchi a
forza bruta. Un elenco degli algoritmi più noti è il seguente:\footnote{sono
  tutti \textit{block cipher}, lo \textit{stream cipher} più noto è RC4, che
  però presenta forti debolezze crittografiche ed il suo uso è pertanto
  sconsigliato.}
\begin{basedescript}{\desclabelwidth{2cm}\desclabelstyle{\nextlinelabel}}
\item[IDEA] \itindex{International~Data~Encryption~Algorithm~(IDEA)}
  sviluppato nel 1991 all'Istituto Federale Svizzero di Tecnologia nasce come
  rimpiazzo del DES. Prevede una chiave di 128 bit ed è considerato molto
  sicuro anche se piuttosto lento. Inoltre è brevettato e questo porta ad
  ulteriori problemi (legali) di implementazione.

\item[3DES] il \textit{Triple DES} è un tentativo di estendere il DES
  ampliando la lunghezza delle chiavi. Il meccanismo prevede l'utilizzo del
  DES con tre chiavi diverse (ciascuna di 56 bit, per un totale di 168),
  applicate con una opportuna sequenza sul testo.

\item[blowfish] algoritmo progettato da Bruce Schneier e considerato robusto,
  il suo unico problema è la dimensione della chiave di 64 bit, considerata un
  po' troppo breve. I suoi vantaggi sono la velocità nelle operazioni di
  cifratura e decifratura e la semplicità realizzativa.

\item[AES] \itindex{Advanced~Encription~Standard~(AES)} è l'algoritmo,
  precedentemente noto come \textit{Rijndael} dal nome dei suoi autori, scelto
  dal governo USA come sostituto del DES dopo un procedimento di ricerca e
  standardizzazione durato 5 anni. Prevede diverse possibili lunghezze di
  chiavi, le più comuni sono 128, 192 e 256 bit. È considerato molto sicuro,
  tanto che le versioni con chiavi più lunghe sono state dichiarate valide
  anche per informazioni classificate come ``\textit{TOP SECRET}''.
\end{basedescript}

Gli algoritmi a chiave simmetrica sono ben conosciuti, e quelli citati sono,
allo stato delle conoscenze attuali, affidabili dal punto di vista della
robustezza crittografica, essi però hanno in comune un difetto di base:
occorre che il mittente ed il destinatario siano in possesso della stessa
chiave.

Si pone pertanto il problema di come questi possano scambiarsela in modalità
sicura: se infatti si dispone di un canale di comunicazione che è già sicuro
non ha senso usare la crittografia.  Pertanto, in tutte le situazioni in cui
non è possibile essersi scambiati la chiave in maniera sicura prima di
iniziare a comunicare, la crittografia a chiave simmetrica non assicura
nessuna sicurezza aggiuntiva rispetto a quella del canale su cui ci si scambia
la chiave.

Un secondo grave problema è la gestione stessa delle chiavi quando la
comunicazione non è più fra due soli estremi, ma fra molti attori
indipendenti. Se si usa la stessa chiave per tutti gli attori il rischio di
scoperta della stessa viene moltiplicato per il numero degli attori, e basta
che una sola comunicazione sia compromessa, o che uno degli attori non sia
fidato, perché si compromettano tutte le comunicazioni fra tutti gli attori. 

Viceversa se si decide di usare chiavi diverse si pone il problema pratico che
ciascun attore deve possedere le chiavi per comunicare con tutti gli altri, ed
il numero delle chiavi da gestire cresce in maniera esponenziale,\footnote{in
  effetti si è esagerato un po', per pignoleria si deve dire che il numero di
  chiavi diverse necessarie per $n$ attori cresce con $n(n-1)/2$, che non è un
  andamento esponenziale, ma quadratico; questo comunque non lo rende meno
  ingestibile.}  rendendone ingestibile il procedimento di distribuzione.

Inoltre più si usa una chiave (simmetrica), più materiale si fornisce ad un
attaccante per cercare di decifrarla, rendendo più facile il compito e più
esteso il danno in caso di scoperta. Per questo una chiave dovrebbe essere
cambiata spesso, ed il problema della gestione delle chiavi non può essere
considerato secondario.



\subsection{Crittografia a chiave asimmetrica}
\label{sec:crypto_asymmetric}

La soluzione ai problemi della crittografia a chiave simmetrica illustrati
alla fine della precedente sezione è venuta nel 1976 con l'invenzione da parte
di Whitfield Diffie e Martin Hellman (e di Ralph Merkle sul cui lavoro essi si
erano basati) della crittografia a \textsl{chiave asimmetrica}, che ha
modificato radicalmente i criteri di funzionamento degli algoritmi
crittografici rispetto a come erano stati fino ad allora concepiti.

Il concetto alla base della crittografia a chiave asimmetrica,
illustrato in fig.~\ref{fig:crypto_asymmetric}, è che si usano sempre delle
coppie di chiavi. Una chiave viene usata per cifrare, e l'altra per decifrare,
come un forziere con una serratura con due chiavi, di cui una può solo
chiudere e l'altra può solo aprire. Il meccanismo viene detto asimmetrico
proprio perché un capo della comunicazione può solo trasmettere e l'altro solo
ricevere.

\begin{figure}[htb]
  \centering
  \includegraphics[width=8cm]{images/crypto_asym}
  \caption{Schema di funzionamento di un algoritmo crittografico a chiave
    asimmetrica.}
  \label{fig:crypto_asymmetric}
\end{figure}

Per questo quando si parla di crittografia a chiave asimmetrica si parla
sempre di \textsl{chiave pubblica}, quella che viene usata per cifrare, che
viene pubblicata, che chiunque può usare, e la cui scoperta non comporta alcun
rischio, e di \textsl{chiave privata}, quella che serve per decifrare, da
tenere gelosamente custodita e da proteggere con la massima sicurezza, la cui
scoperta compromette completamente la segretezza della comunicazione.

In realtà l'algoritmo originale di Diffie ed Hellman non è propriamente un
cifrario a crittografia asimmetrica, quanto un algoritmo (denominato
\itindex{Diffie-Hellman} \textsl{procedura di
  \textit{Diffie-Hellman}}),\footnote{la trattazione dettagliata di questa
  procedura va al di là dello scopo di questo testo, ma banalizzando
  brutalmente si può dire che il concetto è che i due capi della comunicazione
  estraggono un numero a caso che spediscono al corrispondente opportunamente
  ``\textsl{moltiplicato}'' con la propria chiave privata e la sua chiave
  pubblica; rimettendo insieme il tutto e ``\textsl{fattorizzando}''
  opportunamente le chiavi, entrambi ottengono un valore identico combinazione
  dei due numeri a caso, che diventa la chiave di sessione (per una
  spiegazione meno vaga si consulti ad esempio
  \url{http://it.wikipedia.org/wiki/Diffie-Hellman}).}  che consente di
stabilire in maniera sicura fra i due capi di una comunicazione un segreto
crittografico condiviso (la cosiddetta \textsl{chiave di sessione}, da usare
con crittografia a chiave simmetrica) senza che questo venga mai trasmesso sul
canale di comunicazione e senza che sia possibile ottenerlo ad un terzo che
intercetti la comunicazione stessa.\footnote{e a questo scopo viene a
  tutt'oggi utilizzato da praticamente tutti i protocolli di comunicazione che
  prevedono la cifratura del traffico di rete.} Il primo algoritmo di vera e
propria cifratura a chiave asimmetrica venne realizzato, sempre nel 1976 da
Rivest, Shamir ed Aldeman e venne chiamato RSA, dalle loro iniziali.

Benché concettualmente il metodo di funzionamento sia completamente diverso,
anche per gli algoritmi a chiave asimmetrica valgono i criteri di sicurezza di
robustezza rispetto agli attacchi illustrati in sez.~\ref{sec:crypto_info}; in
questo caso la chiave che si cerca di determinare è ovviamente la chiave
privata, e fra le informazioni disponibili si avrà ovviamente la chiave
pubblica. Un elenco dei principali algoritmi è il seguente:
\begin{basedescript}{\desclabelwidth{2cm}\desclabelstyle{\nextlinelabel}}
\item[RSA] \itindex{Rivest-Shamir-Aldeman~(RSA)} è il primo algoritmo a chiave
  asimmetrico creato, la sua sicurezza è ritenuta equivalente alla difficoltà
  della fattorizzazione di numeri interi di grande dimensione, problema
  matematico per il quale al momento non è nota nessuna soluzione
  semplice\footnote{nel caso semplice vuol dire computazionalmente più
    semplice dell'attacco a forza bruta.} per cui l'algoritmo è considerato
  robusto. Non è però neanche stato dimostrato che tale soluzione non esista,
  per cui non si può avere la certezza della robustezza.
\item[El-Gamal] è basato sul calcolo di esponenziali di numeri interi, e la
  sua sicurezza si basa sulla difficoltà matematica del problema dei logaritmi
  discreti. La versione originale presenta una debolezza nei confronti di
  attacchi a testo in chiaro scelto, ma esistono versioni modificate che non
  lo sono.
\item[DSA] \itindex{Digital~Signature~Algorithm~(DSA)} il \textit{Digital
    Signature Algorithm} è un algoritmo proposto dal NIST (\textit{National
    Institute of Standards and Technology}) come standard per le firme
  digitali dal governo statunitense. La versione originale usa una matematica
  analoga a quella di \textit{El-Gamal}, ma ne esiste una versione basata
  sulle proprietà delle curve ellittiche, un'altra classe di altri problemi
  matematici ritenuta più difficile di quella dei logaritmi discreti. L'uso
  delle curve ellittiche consente in genere l'uso di chiavi più piccole, ma
  comporta tempi più lunghi nella cifratura.
\end{basedescript}

Il grande vantaggio della crittografia a chiave asimmetrica, che costituisce
una vera e propria rivoluzione rispetto alla crittografia a chiave simmetrica,
è che è possibile distribuire senza problemi la chiave pubblica, mettendo a
disposizione di chiunque la capacità di spedire un messaggio cifrato che solo
il destinatario, quello che possiede la chiave privata, può decifrare.

La forza dei meccanismi di crittografia a chiave asimmetrica sta nel fatto che
pur conoscendo la chiave pubblica non è possibile risalire alla chiave
privata, né decifrare quanto con essa è stato cifrato. Solo la conoscenza
della chiave privata consente la decifrazione. Ovviamente per poter ottenere
una comunicazione bidirezionale occorre usare una coppia di chiavi ciascuno. 

Lo svantaggio principale degli algoritmi a chiave asimmetrica è che le chiavi
devono avere dimensioni nettamente superiori a quelle di chiavi simmetriche di
forza equivalente, e che il procedimento di cifratura è nettamente più
esigente in termini di risorse e molto più lento nell'esecuzione.

Per questo motivo oggi tutti i sistemi di comunicazione cifrata sono sistemi
ibridi, in cui si usa la crittografia a chiave asimmetrica per creare un
canale sicuro su cui scambiare la chiave simmetrica che serve poi per cifrare
il grosso del traffico, anzi in genere si usa direttamente la procedura di
\itindex{Diffie-Hellman} \textit{Diffie-Hellman} per creare una chiave
simmetrica condivisa in maniera sicura.  In questo modo si risolve il problema
della trasmissione delle chiavi simmetriche usate per la comunicazione,
inoltre il meccanismo permette di cambiare le chiavi di cifratura con grande
frequenza, rinegoziandole attraverso il canale sicuro creato con le chiavi
asimmetriche.

In sostanza il grande vantaggio degli algoritmi a chiave asimmetrica è che non
soffrono del problema relativo alle modalità in cui realizzare la
distribuzione sicura delle chiavi, dato che non esiste più il problema di
comunicare in maniera sicura la propria chiave (quella pubblica ovviamente),
in quanto renderla nota è quanto serve al funzionamento stesso del meccanismo.

Inoltre basta che ciascuno curi la conservazione della sua chiave privata per
mantenere la sicurezza di quanto viene comunicato a lui, senza riflessi, in
caso di compromissione, sulle comunicazioni destinate ad altri. Questo
significa che quando è necessario mantenere diversi canali di comunicazione
fra un numero arbitrario di persone basterà che ciascuna di esse abbia la sua
coppia di chiavi; il problema cioè cresce linearmente con il numero delle
persone ed è pertanto gestibile con relativa semplicità.

La crittografia a chiave asimmetrica sembra pertanto essere in grado di
fornire la soluzione al problema teorico che sta alla base della crittografia
contemporanea, quello di mettere in grado due persone\footnote{in generale il
  problema riguarda i due capi di un canale di comunicazione, anche se la
  formulazione più comune è proprio questa.}  (convenzionalmente indicate dai
nomi \textit{Alice} e \textit{Bob}) che non si sono mai incontrate né si
conoscono di comunicare in maniera sicura, senza che un terzo (indicato
convenzionalmente con il nome \textit{Charlie}) possa intercettarne la
comunicazione.\footnote{si, le iniziali dei nomi hanno un significato, neanche
  tanto velato, (per una lista più completa si consulti
  \href{http://en.wikipedia.org/wiki/Alice_and_Bob}
  {\texttt{http://en.wikipedia.org/wiki/Alice\_and\_Bob}}) quello che ancora non
  si riesce a capire è perché diamine Alice e Bob abbiano tutta questa voglia
  di chiacchierare in segreto senza neanche conoscersi, e cosa importi a
  Charlie di spiarli.} La crittografia a chiave asimmetrica sembra una
soluzione, in quanto basta che Alice e Bob si scambino la chiave pubblica ed
il gioco è fatto.

In realtà questo non risolve il problema, perché restano sempre possibili gli
attacchi \itindex{man-in-the-middle} \textit{man-in-the-middle}, in cui
Charlie si spaccia per Bob con Alice e per Alice con Bob, ed essendo in mezzo
può decifrare quanto Alice manda a lui credendo che sia Bob (e che invierà a
Bob fingendosi Alice) e viceversa. Resta dunque aperto il problema
dell'identificazione, perché niente consente di dire che la chiave pubblica
che io ricevo sia davvero di Alice, a meno di non fare una verifica diretta,
metodo che però fuoriesce dall'ambito della crittografia.

È comunque possibile, utilizzando le PKI (\textsl{infrastrutture di chiave
  pubblica}, che vedremo in sez.~\ref{sec:PKI}) fornire una soluzione, anche
se solo parziale, al problema degli attacchi \itindex{man-in-the-middle}
\textit{man-in-the-middle}. Infatti una delle caratteristiche più interessanti
della crittografia a chiave asimmetrica è quella che consente anche di
realizzare la cosiddetta \index{firma~digitale} \textsl{firma digitale}, che
vedremo in sez.~\ref{sec:crypto_hash}. La direzione di cifratura illustrata in
fig.~\ref{fig:crypto_asymmetric} infatti può essere invertita; si può cioè
cifrare con la chiave privata e generare un messaggio che potrà essere
decifrato solo con la chiave pubblica. In questo caso chiaramente non si avrà
un messaggio confidenziale, dato che chiunque potrà decifrarlo con la chiave
pubblica, ma si potrà dimostrare di essere in possesso della corrispondente
chiave privata, essendo questo l'unico modo con cui si può creare tale
messaggio.


\subsection{Le funzioni di hash crittografico}
\label{sec:crypto_hash}

Finora abbiamo trattato delle tecniche crittografiche applicandole
esclusivamente ad una classe di problemi; quelli della
\textsl{confidenzialità} dei dati. In realtà le tecniche crittografiche
vengono usate in tutti gli ambiti della sicurezza delle comunicazioni, in
particolare esse possono essere utilizzate anche per verificare
l'\textsl{integrità} delle informazioni e che i dati non siano stati
modificati, per realizzare meccanismi di \textsl{autenticazione} che
identifichino gli utenti e di \textsl{non ripudiabilità} che consentano di
impedire che il mittente di un messaggio possa negare di averlo spedito.

\index{hash~crittografico|(} 

Per realizzare queste ulteriori funzionalità le tecniche crittografiche
prevedono una ulteriore classe di algoritmi, relativi ai cosiddetti
\textsl{hash crittografici}, o \textsl{funzioni ad una via}. Una funzione di
\textit{hash} è in generale una funzione che dato un ingresso qualunque (in
genere un testo di dimensione arbitraria) genera un valore in uscita, detto
appunto \textsl{valore di hash}, di dimensione fissa (ed in genere ridotta)
che viene usato come indice per identificare il testo in ingresso.

In genere per una funzione di \textit{hash} la caratteristica più importante è
quella di non generare \textsl{collisioni}, vale a dire di dare valori in
uscita completamente diversi in corrispondenza di testi in ingresso diversi
(anche se questi differiscono poco). Spesso le si chiamano anche
\textit{checksum} in quanto vengono utilizzate per un controllo elementare di
integrità.

Rispetto ad una \textit{checksum} o ad una normale funzione di \textit{hash}
una funzione di \textsl{hash crittografico} richiede alcune ulteriori
proprietà che ne consentano l'uso a scopi crittografici. Se si indica con $m$
il testo iniziale e con $h$ il valore dell'hash, e con $f$ la funzione di
\textit{hash} tale che $h=f(m)$, queste proprietà sono:
\begin{itemize}
\item la funzione deve essere \textsl{ad una via} (o a \textsl{senso unico}),
  una volta cioè che sia noto soltanto il valore di hash $h=f(m)$ deve essere
  difficile risalire da esso al valore di $m$. Questa proprietà è chiamata
  \textit{preimage resistence}.

\item noto un certo testo iniziale $m_1$ ed il suo valore di hash $h=f(m_1)$
  deve essere difficile trovare un $m_2$ (con $m_2 \ne m_1$) che dia lo stesso
  hash (cioè tale che $f(m_2)=h$). Questa proprietà è chiamata \textit{second
    preimage resistence}.

\item infine deve essere molto difficile trovare due testi
  qualsiasi\footnote{si tenga presente che questa, anche se apparentemente
    simile, in realtà esprime una condizione molto più stringente della
    precedente.} $m_2$ e $m_1$ diversi, ma tali da avere lo stesso valore di
  hash (cioè con $f(m_2)=f(m_1)$). Questa proprietà è chiamata
  \textit{collision resistence}.\footnote{questo requisito è diverso rispetto
    a quanto serve per una funzione di hash normale, in cui le collisioni
    devono essere solo poco probabili, ma può anche essere relativamente
    facile trovare testi diversi che le generano.}
\end{itemize}

\index{hash~crittografico|)}

Le prima proprietà è necessaria ad esempio per far sì che una funzione di hash
crittografico possa essere utilizzata per realizzare meccanismi di
\textsl{autenticazione} (il caso classico è quello delle password di un
sistema Unix).  In tal caso in genere si calcola il valore di hash della
password confrontandolo con uno precedentemente memorizzato; se corrisponde si
ha l'autenticazione. Ovviamente in questo caso anche potendo leggere il
valore di hash deve essere molto difficile poter ottenere da questo la
password originaria.

Il secondo impiego delle funzioni di hash è quello della verifica di
\textsl{integrità}; in questo caso la seconda proprietà ci assicura che una
volta associato ad un testo il suo valore di hash non sarà possibile mettere
al suo posto un testo diverso che generi lo stesso valore. Rispetto alle
classiche funzioni \itindex{checksum} \textit{checksum} si vuole avere la
certezza che non sia possibile, non solo in caso di errore, ma anche in caso di
costruzione deliberata, ottenere lo stesso valore di hash per un testo
diverso.

Un passo ulteriore è quello in cui usando una funzione di hash ed una chiave
secreta è possibile creare un \itindex{Message~Authentication~Code~(MAC)}
\textit{Message Authentication Code} (MAC).  L'algoritmo usato più
comunemente, ad esempio nei vari protocolli di comunicazione sicura come SSL e
IPSEC, si chiama \itindex{Hash-based~Message~Authentication~Code~(HMAC)} HMAC;
in questo caso si utilizza una opportuna combinazione del testo e della chiave
per la generazione di un hash crittografico che consente di ottenere il valore
di un codice che non solo dimostra l'integrità del messaggio, ma anche il
possesso della chiave segreta, e pertanto ne autentica il contenuto.

Infine un ultimo impiego delle funzioni di hash crittografico è, quando
vengono unite all'uso della crittografia a chiave asimmetrica, quello della
\index{firma~digitale} \textsl{firma digitale}, grazie alla quale non solo si
ha la verifica dell'integrità di un messaggio e della identità del mittente,
ma anche la \textsl{non ripudiabilità}.\footnote{è quello che fanno, con la
  posta elettronica, programmi come GPG (\textit{Gnu Privacy Guard}, vedi
  sez.~\ref{sec:gpg_intro}), una reimplementazione libera e aderente allo
  standard del più noto PGP (\textit{Pretty Good Privacy}), un programma che
  consentiva appunto di cifrare e firmare i messaggi di posta elettronica.}

In questo caso dato un testo si genera un valore di hash che poi viene cifrato
con la propria chiave privata, distribuendo quanto ottenuto (la
\index{firma~digitale} firma digitale appunto) insieme al documento si
dimostra che quel documento è stato scritto da noi (in quanto possessori della
chiave privata che ha generato la cifratura) e che esso è integro.  Inoltre
dato che non è possibile negare che sia stata usata la nostra chiave privata,
né che il valore di hash possa essere relativo ad un documento diverso, si
avrà anche la non ripudiabilità dello stesso.

Come per gli algoritmi di crittografia a chiave simmetrica e asimmetrica,
esistono anche varie funzioni di hash crittografico; le più usate al momento
sono le seguenti:
\begin{basedescript}{\desclabelwidth{2.7cm}\desclabelstyle{\nextlinelabel}}
\item[MD5] è una funzione molto utilizzata (ad esempio per le password su
  GNU/Linux) creata nel 1991 da Rivest (lo stesso di RSA). Deriva da una serie
  di altre funzioni di \textit{Message Digest} precedentemente create da
  Rivest (in particolare MD4) che avevano dimostrato seri problemi.  La
  funzione produce un valore di hash di 128 bit. Nel 2004 sono stati trovati
  seri problemi anche per questa funzione, ed è pertanto opportuno programmare
  un passaggio ad altre funzioni, visto che i problemi si sono ulteriormente
  aggravati negli anni seguenti e ad oggi\footnote{nota riferita all'aprile
    2010.} questo algoritmo non è più considerato sicuro.

\item[SHA-1] \itindex{Secure~Hash~Algoritm~(SHA)} la sigla sta per
  \textit{Secure Hash Algoritm}, pensato come sostituto più sicuro del
  precedente MD5, è stato progettato dalla NSA ed è pubblicato come standard
  per il governo statunitense e produce un valore di hash di 160 bit. Viene
  usato da molti protocolli ed applicazioni come GPG, SSH, SSL, IPSEC.  La
  versione originale (SHA-0) non è considerata sicura ed è stata ampiamente
  sostituita da SHA-1; anche per quest'ultima però sono stati recentemente
  (Febbraio 2005) rilevati problemi che potrebbero ridurne
  l'efficacia. Esistono comunque altre versioni che producono valori di hash
  più ampi (SHA-256, SHA-512) che possono fare da sostituti.

\item[RIPMED-160] la sigla sta per \textit{RACE Integrity Primitives
    Evaluation Message Digest} ed è stato sviluppato in Europa da un gruppo di
  crittografi e pubblicato nel 1996. Nasce come sostituzione del precedente
  RIPMED-128, che risultava debole, e prevede un valore di hash di 160 bit. La
  sua caratteristica è quella di essere stato progettato in maniera aperta in
  ambito accademico. È meno usato e per questo meno studiato.
\end{basedescript}

% LocalWords:  connect scan tab default SYN flag connect list OB Charlie guard
% LocalWords:  stealth ping PGP pretty good secure Ralph Merkle Jules Verne
% LocalWords:  protocol idle ACK window RPC FTP bounce Security Agency Such
% LocalWords:  attack socket stack RST
% LocalWords:  half
% LocalWords:  synlogger iptables zombie
% LocalWords:  fragmentation Solaris OpenBSD
% LocalWords:  router ICMP port unreachable destination
% LocalWords:  call portmapper echo
% LocalWords:  request timestamp netmask
% LocalWords:  timeout IPv
% LocalWords:  DNS netfilter crash SSH
% LocalWords:  denial localhost fingerprint sniffer
% LocalWords:  incremental ethernet MAC address
% LocalWords:  firmware broadcast promiscuous BNC hub information
% LocalWords:  hiding sez denial of service username
% LocalWords:  smart hash SSL discrectionary access
% LocalWords:  control DAC filesystem mandatory role based RBAC disclosure the
% LocalWords:  deception disruption usurpation snooping wiretapping middle worm
% LocalWords:  spoofing phishing shellcode shell overflow Phrack integer string
% LocalWords:  format backdoor clipper rootkit Windows back orifice
% LocalWords:  trojan Ken Thompson keylogger wireless VNC social firewall Bruce
% LocalWords:  Schneier snake oil PDCA plan act antivirus
% LocalWords:  IDS log disaster recovery classification need to separation fig
% LocalWords:  duties ROT Edgar Allan Vigenère Belaso OTP One Pad Claude NSA
% LocalWords:  Shannon DES encryption IBM National Standards block CBC
% LocalWords:  cipher padding reply Chaining XOR stream CFB RC blowfish AES RSA
% LocalWords:  Rijndael Whitfield Diffie Hellman Rivest Shamir Aldeman Gamal
% LocalWords:  DSA digital signature algorithm NIST institute and technology
% LocalWords:  checksum preimage resistence second collision message IPSEC HMAC
% LocalWords:  authentication digest SHA decure algoritm GPG RIPMED RACE DoS
% LocalWords:  integrity primitives evaluation Carl PKI


%%% Local Variables: 
%%% mode: latex
%%% TeX-master: "sicurezza"
%%% End: 
