lunedì 6 dicembre 2010

Anticipo lezione del 6 dicembre

In seguito all'indispozione della prof. Venuleo, la lezione di oggi è anticipata alle 15.30 .

venerdì 3 dicembre 2010

Programmi da scaricare per il resto del corso

www.openoffice.org

Per Windows: http://download.services.openoffice.org/files/localized/it/3.2.1/OOo_3.2.1_Win_x86_install-wJRE_it.exe

Per Mac: http://download.services.openoffice.org/files/localized/it/3.2.1/OOo_3.2.1_MacOS_x86_install_it.dmg

Lezione del 3 dicembre 2010 /2

Nella seconda lezione si sono descritti i programmi e i formati più comunemente utilizzati nell'uso quotidiano.

Le prime considerazioni riguardano i file di dati, i file cioè che contengono le informazioni che ci interessa mantenere (la tabella di excel con i voti, l'archivio delle email, le lettere d'amore scritte con Word). Come è in grado il sistema operativo di "riconoscerne" il contenuto in modo da rappresentarli con un'icona che li ricollega al programma con cui sono stati creati o con cui è possibile aprirli? (per esempio i file di word vengono riconosciuti come tali: ma se i file sono solo una sfilza di numeri come è possibile che vengano "riconosciuti" dal sistema?)

Il "segreto" è che i nomi dei file, in windows, possiedono una "estensione" di tre caratteri che li rende riconsudibili al programma appropriato per aprirli. Windows nasconde questa estensione per... semplificare la vita agli utenti (introducendo anche rischi per la sicurezza), ma comuque la mantiene e la usa per avere un'informazione sul contenuto del file. Ogni programma è libero di "scegliere" l'estensione da applicare ai propri file, ma alcune di queste sono diventate ormai consolidate e caratteristiche. Vediamo ne alcune con le diverse caratteristiche.

Formati compressi: ZIP e RAR (o 7z per il 7zip)
Sono le estensioni classiche che rappresentano file che contengono dati compressi. I dati compressi sono dati di qualsiasi genere che vengono ricodificati in modo da fargli occupare uno spazio minore, ma senza perdere nessuna informazione. Per fare un semplice esempio, se il file originale fosse AAABBBCCCCCCC, sarebbe possibile ricodificarlo (in questo esempio in modo molto ingenuo e poco realistico) come 3A3B7C (codifica "run length", di fatto quella usata nei fax). Questa nuova codifica mantiene tutta l'informazione originale (infatti permette di ricostruire il file di partenza) ma è in grado di esprimerla in modo molto più compatto (meno della metà). Ovviamente per poter utilizzare nuovamente i dati è necessario operare il processo inverso per ricostruire il file originario.
Un esempio più realistico è il seguente. Mettiamo di voler comprimere il seguente testo:
CARO AMICO TI SCRIVO PERCHÉ SEI UN AMICO CARO. È immediatamente evidente che c'è una certa ridondanza di informazioni, infatti le parole AMICO e CARO sono ripetute. Cerchiamo un modo per ricodificare questi dati in modo più compatto, in particolare cercando un modo di richiamare dentro al testo pezzi di testo già comparsi. Usiamo la convenzione di scrivere [pos iniz, num car] per indicare che in quel punto si deve sostituire il testo che si trova a partire dalla posizione pos iniz per un certo umero di caratteri. Il testo di esempio diventa quindi: CARO AMICO TI SCRIVO PERCHÉ SEI UN [6,5] [1,4]. In questo esempio particolare il guadagno non è evidente, ma la procedura permette in generale di risparmiare molto spazio nella codifica. Inoltre la procedura potrebbe essere nidificata, mettiamo che nel seguito della lettera si ripetessero le parole AMICO CARO, le si potrebbe sostituire con [35,11] cioè facendo riferimento a una sezione già codificata, e iniziare a "risparmiare" un bel po' di caratteri.
Questo è in generale il funzionamento di programmi tipo winzip (che implementano l'algoritmo Lempel-Ziv) e anche winRAR. Esistono altri algoritmi di compressione (come il metodo di Huffman) ma sono in linea di massima meno efficienti.

Formati immagine: JPG e GIF
Come già spiegato le immagini a livello di base vengono ottenute suddividendo la fotografia in piccoli riquadri, e ogni riquadro (detto pixel) possiede un colore. Registrare tutte quelle informazioni richiede molta memoria, per esempio una foto 800x600 pixel, dove ogni pixel può rappresentare 64000 colori richiede 960 kilobyte. Ci chiediamo quindi se non sia possibile usare una codifica simile a quella illustrata sopra per rendere più efficiente. Data la caratteristica delle immagini, dove molte aree spesso hanno colori uniformi o molto vicini, già una codifica tipo quella run-length è un guadagno.
Con il formato JPG si aggiunge un ulteriore fatto: le compressioni "lossless" (cioè quelle che non perdono informazioni) possono non esere le migliori per le immagini di tipo fotografico, dato che spesso la qualità effettiva richiesta è molto inferiore alla qualità massima: insomma, una foto per quasi tutti gli usi può non essere superdefinita. Il formato JPG mette in pratica questo principio introducendo un formato di compresione di tipo "Lossy" (cioè con perdita).

Formato PDF e PS:
Portable Document Format e PostScript (strettamente imparentati, sviluppati entrambi da Adobe)
Contrariamente ai formati di immagine dove l'immagine viene divisa in puntini, il formato PDF è vettoriale. Questo significa che le aree vengono definite da una serie di piccoli segmenti, e anche le lettere sono costruite in questo modo. Il vantaggio di essere un formato vettoriale è che è possibile ingrandirlo a piacere e mantiene i margini sempre perfettamente definiti.

Formati testuali: TXT e DOC
Normalmente i file con estensione TXT sono quelli che contengono testo semplice, senza formattazioni né altri arricchimenti. Una "a" è una "a" e basta.
Invece i formati di file tipo Word permettono non solo di avere le informazioni delle lettere scritte nel testo, ma anche della particolare formattazione di ogni carattere o parti di testo, oltre alle altre informazioni che si possono inserire come le note o dei grafici o delle immagini. Possiamo immaginare il formato di word descritto con un sistema simile all'xml discusso in una lezione precedente. Dato che abbiamo un testo e delle informazioni "a proposito" del testo, possiamo esprimerle in questo modo:
Il testo Caro amico potremmo pensare di descriverlo come:
<text font="Courier"><italic>Caro</italic></text> <text size="small"><underline>amico</underline></ext>

Lezioni del 3 dicembre 2010 /1

Approfondimento del concetto di sistema operativo. Dato che il computer può eseguire solo un programma alla volta, è necessario immaginare un sistema che ci permetta di utilizzare il computer in un modo più versatile. Il vincolo rimane, ma è possibile strutturare le cose in modo più intelligente per aumentare le possibilità di funzionamento.

Quando accendiamo il computer la memoria è completamente vuota. Per potervi inserire qualcosa è nevessario che le istruzioni del programma siano scritte in un luogo che le possa mantenere nel tempo: questo lugo, come sappiamo, è l'hard disk (ma alcuni vecchi computer avevamo dei piccoli programmi scritti in delle memorie non modificabili inserite direttamente sulla ciruciteria, le note ROM: read only memory). Grazie a un sistema di gestione elementare delle periferiche (che fornisce un funzionamento di base per tastiera, schermo e accesso a memorie di massa come gli hard disk), che si chiama BIOS (Basic Input Output System), il copmuter autonomamente trova sul disco il programma "di avvio" del sistema operativo, lo copia nella memoria e lo esegue. Niente di sostanzialmente diverso da quello che abbiamo visto finora.

Il sistema operativo si occupa di gestire l'interazione tra l'utente e i programmi, e di amministrare l'"ecosistema" dove i programmi "vivono". Dato che i programmi, come abbiamo visto, devono avere (e poter disporre liberamente) di una memoria, il primo "potere speciale" che deve avere un sistema operativo è quello di poter creare delle sotto-aree di memoria "ritagliandole" dalla memoria globale del computer. Da un punto di vista del programma che si trova a funzionare in questa sotto-area, quella è la sua memoria, che comincia da 1 ed è di sua esclusiva competenza. Con questa memoria ci può fare quello che vuole. (ma non può uscirne e invadere la memoria globale o altre aree di memoria: se serve un'aggiunta è il sistema operativo che provvede, automaticamente, a ingrandire lo spazio del programma che ne necessita)

Dentro queste aree di memoria è possibile inserire dei programmi (normalmente estratti dall'hard disk, che rispondono a nomi esotici e strani come "Word", "Outlook Express", "Internet Explorer", "Excel"). Questi programmi si comporteranno né più né meno come quelli "astratti" che abbiamo visto a lezione, lavorando sulla propria memoria privata e facendo cose molto diverse da quelle che facevano i "nostri" programmi, ma facendole usando esattamente le stesse modalità.

Ma dato che in ogni momento solo un programma (anzi: una sola istruzione di un solo programma) può essere in esecuzione, bisogna escogitare una struttra che renda possibile la convivenza contemporanea di più programmi. La soluzione è ingegneristica e non logica: si usa un sistema detto di scheduling. Lo scheduling permette il multitasking, cioè permette di eseguire più compiti contemporaneamente. Per dare l'idea che più programmi possano essere eseguiti allo stesso momento (un programma in esecuzione è detto processo) il sistema operativo reindirizza il flusso delle istruzioni a turno verso uno dei processi in esecuzione, permettendogli di avanzare per alcune frazioni di secondo e quindi fermandolo per poi passare il controllo nuovamente a un altro processo. Quando tutti i processi hanno avuto il loro "pezzettino" di tempo, il ciclo si ripete. In questo modo, a turno, tutti i programmi possono procedere in modo apparentemente parallelo. Il passaggio tra un processo e l'altro è talmente veloce che è impercettibile all'utente che "vede" tutti i processi andare avanti in parallelo e contemporaneamente.


Noi comunichiamo col sistema operativo attraverso l'interfaccia. Fondamentalmente quando facciamo "doppio click" sull'icona di Word, stiamo dando istruzione al sistema operativo di cercare il file che contiene le istruzioni del programma Word sull' hard disk, di creargli una sua area di memoria, di copiare le istruzioni dal disco alla memoria e di farne partire l'esecuzione. A quel punto il processo Word andrà avanti per conto suo, a turno con gli altri processi in funzione. (questo è il motivo per cui più programmi sono "aperti", più è lenta l'esecuzione di ognuno)

Il sistema operativo gestisce e coordina anche le risorse comuni alla macchina sulla quale viene eseguito, per esempio l'accesso al disco, alla stampante e così via.

A questo punto però bisogna rendersi conto che al computer si possono collegare periferiche che hanno modelli, funzionalità, marche, caratteristiche anche molto diverse tra loro. Alcune di queste periferiche potrebbeno non essere nemmeno state previste dai creatori del sistema operativo. Anche per limitarsi solo alle stampanti, ne esistono migliaia di marche e modelli, ognuno con modalità di funzionamento e di gestione del tutto diverse. Come può il sistema operativo gestire delle risorse con caratteristiche così varie? Per fare ciò si utilizzano speciali programmi detti driver. Un driver è un tipo speciale di programma che deve essere scritto secondo una struttura rigida e predefinita. Il programma driver deve possedere alcune funzioni standard (sono le sottoprocedure che abbiamo visto in altre lezioni) con dei parametri standard. Per esempio u driver di stampa dovrà avere funzioni come STAMPA, SALTA_PAGINA, INTERROMPI_STAMPA e così via: sono le funzioni che genericamente ci aspettiamo di poter eseguire con quel particolare hardware. Tutti i driver di stampa devono possedere quelle funzioni. (si dice in gergo che devono possedere una "interfaccia standard": interfaccia in questo caso non è quella visuale di windows, ma una particolare strutura fatta i modo da "incastrarsi" con le aspettative del sistema operativo, una inter-faccia appunto, fatta come il pezzo di un puzzle che si deve adattare alle specifiche del sistema). Le istruzioni contenute in queste funzioni sono invece strettamente dipendenti dall'apparecchio che deve essere pilotato (infatti "driver" significa "pilota"!). Se per esempio una stampante richiede il codice A per saltare pagina, il driver all'interno della procedura SALTA_PAGINA dovrà inviare alla stampante il codice "A". Se una stampante richiede il codice B, il suo driver dovrà sempre avere la procedura SALTA_PAGINA ma all'interno di quest'ultima il codice da inviare sarà "B", e così via. Ogni apparecchio collegato al computer (ma anche quelli all'interno del computer, come la scheda video che permette di mostrare le immagini sullo schermo, o la sched aaudio che permette di riprodurre i suoni) richiede un driver specifico. Molto spesso i sistemi operativi possiedono già una certa collezione di driver per i dispositivi più diffusi, ma nel caso questo driver non sia presente è necessario installarlo col CD fornito con l'apparecchio o scaricarlo dal sito del produttore. Ci si può accorgere di questo fatto quando si inserisce una chiavetta di memoria in una porta USB e compare un messaggio "installazione della periferica in corso": il sistema operativo sta cercando se possiede già il driver di quell'apparecchio e in caso positivo fa in modo di utilizzarlo per interagire con quella periferica.

I driver quindi sono programmi molto speciali, perché diversamente dagli altri che "vivono" una vita propria nella memoria e che in caso di errore possono essere interrotti (col task manager che si apre premendo contemporaneamente ctrl-alt-canc), i driver diventano pezzi del sistema operativo, vengono incorporati in esso. Se nei programmi driver ci sono errori o si verificano malfunzionamenti è l'intero sistema a trovarsi a rischio di instabilità, perché il problema viene a manifestarsi nel cuore stesso del sistema pregiudicandone il buon funzionamento. Questo spiega per quale ragione i driver sono gli elementi dell'ecosistema "computer" a introdurre i maggiori problemi di funzionamento.

giovedì 2 dicembre 2010

Lezione del 2 dicembre 2010 /2

... Dalla teoria alla pratica.

Questa lezione inaugura la rotta di avvicinamento al computer come oggetto reale, cercando di comprendere come applicare gli algoritmi visti a lezione al mondo reale del computer.

In primo luogo bisogna riconoscere che anche i semplici programmi che abbiamo scritto possono essere (precisamente come le lettere e i caratteri) codificati con dei numeri. I programmi stessi quindi diventano dei dati e trovano una loro collocazione fisica nella memoria, nella stessa memoria che abbiamo finora considerato dedicata solo ai dati. (i programmi SONO dati, in fin dei conti. Dati che vengono interpretati in un certo modo dal computer, che vengono interpretati come istruzioni ed eseguite sugli altri dati presenti in memoria)

Per ragioni di tipo tecnologico, le prime memorie erano molto contenute ed estremamente costose, quindi se da una parte la teorizzazione di una memoria infinita è un comodo concetto, dall'altra è decisamente irrealistica, almeno per quello che erano i computer ai loro primordi. Ma sono queli che hanno dato il modello di quelli attuali quindi, anche se la tecnologia cambia rapidamente, lo schema base di funzionamento è ancora quello degli anni '50.

Programmi e dati devono essere in memoria per poter operare insieme, ma non tutti i dati devono necesariamente stare in memoria nello stesso tempo. Per esempio, se i nostri dati fosero i nomi degli iscritti all'università, non sarebbe sempre necessario averli interamente in memoria. Potremmo pensare di scriverli da qualche parte con un apparecchio esterno, e richiamarli ogni volta che diventano necessari, e magari solo quei dati che ci sono necessari. Questo "apparecchio esterno" è quello che oggi si chiama Hard Disk. Quando vogliamo che un dato resista all'"azzeramento" della memoria che avviene ogni volta che si toglie la corrente al computer, bisogna registrarlo su un qualche supporto che abbia la caratteristica di poterlo mantenere per un tempo indeterminato, e di poterlo recuperare quando è necessario. Questa modalità di gestione della memoria è utile anche per ragioni di efficienza, e permette di non sprecare una risorsa preziosa come la memoria operativa (la RAM, Random Access Memory). I programmi quindi, attraverso specifiche istruzioni, sono in grado di scrivere da qualche parte il contenuto di alcune aree della propria memoria, e di scrivere nella memoria valori letti dal disco. Questa serie di operazioni però è molto impegnativa, e non vorremmo dover scrivere in ogni programma delle istruzioni dettagliate su come fare. Sarebbe utile che ci fosse una specie di "servizio" cui noi chiediamo di salvare una certa area di memoria sul disco, e questo lo fa a nostro nome.

Inoltre nei nostri esempi è semrpe stato dato per implicito che un computer potesse eseguire solo un programma. Nella nostra espeirnza quotidiana sappiamo che così non è, che in un computer più programmi possono essere eseguiti contemporaneamente. Come è possibile ottenere questo risultato? La soluzione consiste nel creare un mega-programma il cui funzionamento sia quello fondamentale, e che si occupi di gestire tutte le risorse connesse al computer, come le periferiche, ma anche gestire il funzionamento dei programmi veri e propri del genere che noi abbiamo visto negli esempi. Questo programma deve essere il primo che viene eseguito e deve rimanere sempre in esecuzione. Deve permettere di recuperare dati dall'hard disk e anche programmi (che, per quanto detto all'inizio SONO dati anche loro). Il nome di questo programma speciale è sistema operativo.

Il sistema operativo permette l'esecuzione (apparentemente) contemporanea di diversi programmi, compreso se stesso. La simulazione della contemporaneità di esecuzione avviene perché il sistema operativo effettua fondamentalmente le seguenti operazioni:
1) gestisce la memoria RAM disponibile del sistema, creando delle sotto-aree che vengono assegnate ai programmi (i programmi vedono questo assegnamento come se cominciasse dalla cella 1 quindi il funzionamento dei programmi dentro un sistema operativo è identico al funzionamento dei programmi che abbiamo visto finora negli esempi).
2) gestisce tutti i programmi in esecuzione, e li porta avanti "in parallelo" concedendo a ognuno di loro un tempo di esecuzione (di frazioni di secondo) per poi bloccarlo e dare il controllo al programma successivo. In questo modo è possibile far funzionare "contemporaneamente" più programmi, anche se in ogni momento solo uno è in effetiva esecuzione (il processore può eseguire solo una istruzione alla volta!)
Quindi ogni programma in funzione nel sistema operativo, dal "proprio" punto di vista è l'unico: ha una sua memoria e vene eseguito seguendo il proprio programma.

Il sistema operativo si prende in carico la gestione di tutti quegli aspetti estranei (o non strettamente inerenti) al programma vero e proprio: la lettura della pressione dei tasti nella tastiera (e la trasmissione al programma opportuno di quei tasti), il movimento del mouse (con il clic, anche in questo caso da applicare al programma "giusto"), l'accesso al disco e alle altre periferiche, la visualizzazione, la stampa e così via.

Parlando di ambienti dove è possibile eseguire più di un programma, si può pensare di estendere una delle caratteristiche che sono state elencate sopra: la possibilità di registrare parti della memoria su un disco. Come si è ripetuto più e più volte, i dati in sé non sono che numeri. La memoria non è altro che una lunghissima sequenza di numeri privi di senso intrinseco. La semantica di quei numeri è data dal programma che li crea e gestisce, in base a come li manipola e organizza. Quindi quei dati, perché creati e gestiti unicamente da un programma, sarebbero in un certo senso di sua esclusiva proprietà visto che il loro significato è definito solo mediante l'uso che ne fa il programma corrispondente. Sarebbe però interessatne cercare il modo di memorizzare questi dati secondo un formato che contenesse già in sé almeno alcune delle informazioni riguardo i dati. Per esempio, se il programma in esecuzione fosse una rubrica, nella memoria potremmo leggere MARCO/TONTI/MARCO.TONTI@UNISALENTO.IT dove per nostra convenzione decidiamo che la barra separa i diversi campi. Senza avere l'informazione della barra però un programma, o una persona, non avrebbe nessuna informazione diretta sul significato di quella sequenza di simboli (se ci fossero stati nomi strani come SMEDSLUND o DIJKSTRA non sarebbe stato tanto chiaro che si trattava di un nome! oppure se fosse stato SERGIO/SALVATORE non avremmo avuto modo di sapere, senza guardare nel programma, qual è il nome e qual è il cognome). Cerchiamo quindi un modo per arricchire di semantica i nostri dati grezzi, anche allo scopo di renderli fruibili da programmi o da persone diverse dal nostro programma o da noi stessi.

La proposta che adottiamo è quella dello standard XML. Secondo questo standard (tralasciando alcuni dettagli tecnici) ogni valore deve essere circondato da tag che lo circostanziano. L'obiettivo è quello di arricchire con informazioni semantiche i dati "grezzi", in modo da renderli intelligibili e portabili su piattaforme, sistemi operativi e programmi diversi. Nel caso del nostro esempio, l'XML corrispondente potrebbe essere:
<persona>
   <nome>Marco</nome>
   <cognome>Tonti</cognome>
   <email>marco.tonti@unisalento.it</email>
</persona>
<persona>
...
</persona>
ecc.
Dentro le parentesi angolari (coppie di maggiore  e minore) ci sono i nomi dei valori contenuti da il tag di apertura e quello di chiusura (contrassegnato da una barra all'inizio: </nome> per esempio indica che lì finisce il nome). Notate come sia possibile non solo includere singoli valori, ma anche altri tag. Questo particolare è utilissimo e ci permette di creare strutture anche molto complesse.

Lezione del 2 dicembre 2010 /1

Lezione conclusiva sulla crittazione. Concetto di crittazione Asimmetrica.
Riferimenti:
http://it.wikipedia.org/wiki/Infrastruttura_a_chiave_pubblica
http://it.wikipedia.org/wiki/Differenza_fra_cifratura_simmetrica_e_asimmetrica

L'idea di fondo della crittazinoe asimmetrica è che, divesamente dal sistema simmetrico che prevede un unica chiave per entrambi i partecipanti, in questo caso le chiavi sono due: K1 e K2. Se crittiamo con la chiave K1 possiamo decrittare solo con la chiave K2, e se crittiamo con la chiave K2 possiamo decrittare solo con la chiave K1.

Le caratteristiche di un sistema PKI sono riassunte nell'acronimo PAIN: Privatezza, Autenticità, Integrità, Non ripudiazione.

Solitamente una delle due chiavi viene tenuta segreta (Ks) e l'altra viene resa pubblica (Kp). L'obiettivo è permettere a tutti coloro che vogliono comunicare in modo sicuro con la persona di poter crittare i messaggi con la chiave pubblica del ricevente, in modo che solo lui possa decrittare il messaggio. In questo modo si assicura la privatezza della comunicazione, perché una volta crittato dal mittente con la chiave pubblica del destinatario, il messaggio diventa decrittabile solo dal destinatario con la propria chiave privata.

Questo risolve il problema della Privacy, ma non ci dà nesuna garanzia sull'identità di chi manda il mesaggio (proprio per il fatto che la chiave che viene usata è pubblica).

Se al contrario non siamo interessati alla privatezza dei dati ma solo alla autenticazione, per le caratteristiche del sistema, è possibile che il mittente critti il messaggio con la propria chiave privata (che solo lui/lei possiede) in modo che chiunque possa riconoscerlo come mittente, dato che quel messaggio può esere decifrato solo con la chiave pubblica della persona. In altre parole SOLO quella persona può crittare usando la propria chiave segreta, e tutti possono decrittare il messaggio usando la chiave pubblica di quella persona (compreso il destinatario che così è certo di parlare con la persona giusta). Questo sistema però garantisce solo l'autenticità, non la privatezza della comunicazione.

Per risolvere il problema si possono comporre le due modalità: il messaggio per prima cosa viene crittato con la propria chiave privata, e successivamente di nuovo crittato con la chiave pubblica del destinatario. In questo modo si uniscono i due sistemi: viene garantita sia l'autenticità che la privatezza della comunicazione, infatti solo il destinatario può decifrare il messaggio del mittente (privatezza), e nuovamente decrittarlo usando la chiave pubblica del mittente (perché il mittente è l'unico che può crittarlo in modo che venga decrittato con la propria chiave pubblica, quindi autenticità).

Quest'ultimo aspetto dell'autenticazione dà luogo anche alla caratteristica che si chiama "non ripudiazione". Quando il mittente certifica di essere chi dice di essere crittando il messaggio con la propria chiave privata, visto che lui/lei è l'unico che può farlo, contemporaneamente sta facendo un gesto che gli impedirà di ripudiare il messaggio. Visto che la crittazione è con la propria chiave privata un'operazione deliberata che solo lui/lei può fare, quella persona non potrà in seguito affermare di non averlo fatto: non potrà ripudiare di essere il mittente di quel messaggio.

Questo è anche il meccanismo di base della firma digitale. Un documento che viene crittato con la propria chiave privata è implicitamente firmato, dato che nessun altro può effettuare quell'operazione. In realtà quello che viene crittato con la propria chiave privata (per firmare) è il codice hash del documento, che in questo modo rimane in chiaro. Il fatto che si usi il codice hash garantisce che sia PROPIO quel documento che viene firmato, e quindi si possono escludere modifiche successive. E anche chi ha firmato, per la non ripudiazione, non può negare di averlo fatto. Questo tipo di firma in Italia ha valore anche in tribunale (e per certi versi è persino più sicuro della firma autografa).

Per la diffusione e l'accertamento dell'effettivo proprietario di una chiave pubblica esistono società dette Certification Authorities che mantengono elenchi aggiornati delle chiavi pubbliche delle persone, in modo che quete chiavi possano essere sostituire in caso di smarrimento della corrispondente chiave privata, o per semplice prudenza.

mercoledì 1 dicembre 2010

Lezione del 1 dicembre 2010

  Oggi si è introdotto il concetto alla base della crittografia classica moderna (per una storia della crittografia pre-moderna vedere qui). (A posteriori, in base all'evoluzione teorica recente, viene definita "simmetrica" per il fatto che la chiave di cifratura deve esere condivisa da entrambe le parti: dall'emittente per crittare un messaggio e dal ricevente per decrittarlo).

Il primo elemento che riguarda crittografia e sicurezza è stato l'introduzione del concetto di codice HASH. Una funzione di hash è una procedura che, dato in ingresso una serie di dati, produce un codice (in linea di massima) diverso per ogni diversa serie di dati, ma identico per la stessa serie. Da questo codice deve essere impossibile risalire ai dati originali. Un esempio molto semplice che illustra il principio di base è quello basato sulla somma: se noi abbiamo una sequenza di numeri, sommandoli otteniamo un valore unico. Questo valore è sempre lo stesso per la stessa sequenza di numeri, ma da quel valore è impossibile risalire alla esatta sequenza che lo ha generato.
Questo sistema viene normalmente usato per registrare le password nei siti e per la posta elettronica. In questo modo non mantengono intatta l'informazione "delicata" della password, ma sono in grado di riconoscere una persona quando inserisce la propria password applicando ad essa la stessa procedura e confrontando i risultati.


Le operazioni di base della crittografia si basano sull'operatore XOR, che ha come simbolo un più in un circoletto: ⊕. Questo operatore si applica a due valori binari e restituisce un valore binario che vale 1 se i due operandi sono diversi tra loro (1 e 0 oppure 0 e 1) e restituisce 0 se sono uguali. XOR è la forma contratta di EXCLUSIVE OR (or esclusivo).

Questo operatore si può applicare anche a interi byte e produce dei byte composti dai risultati di 8 operazioni "in colonna". L'aspetto interessante dello XOR è che se aplicato due volte con lo stesso valore, esso restituisce il valore iniziale. Per esempio 1010 ⊕ 1100 = 0110 , ma se applichiamo di nuovo al risultato lo stesso XOR otteniamo: 1001 ⊕ 1100 = 1010 cioè il valore iniziale. Si può dire anche che N⊕K⊕K = N. Praticamente ripetere lo XOR la seconda volta con lo stesso valore annulla il primo XOR e ripristina il valore originale.

L'idea è quella di usare questa caratteristica per "fondere" in modo reversibile un messaggio con la chiave di crittazione. Se abbiamo un messaggio che è composto da una sequenza di bit (che rappresentano dei caratteri di testo) e una chiave composta da un'altra sequenza di bit (la traduzione in binario di "quiquoqua" per esempio) si possono comporre queste due sequenze di valori in modo da ottenere una sequenza di valori (successivamente reinterpretabili come caratteri) incomprensibile per chi non conosca la chiave di crittazione. Il ricevente, applicando la stessa trasformazione usando la stessa chiave, può decifrare il messaggio e riportarlo in chiaro. In pratica il nostro messaggio M viene elaborato con la chiave K (ripetendo la chiave se serve per coprire tutto il messaggio, che in genere è più lungo della chiave) con lo XOR: C=M⊕K. C è il messaggio cifrato che viene spedito al destinatario. A questo punto il destinatario, conoscnedo la chiave K, la può applicare al messaggio cifrato C⊕K e ottenere M.

Il problema della crittografia simmetrica è che, almeno per gli algoritmi più vecchi, è abbastanza vulnerabile. Conoscendo abbastanza informazioni sulla lingua del messaggio e osservando regolarità statistiche molto sofisticate è possibile spesso decifrare il messaggio. Questo non è più molto vero dato che gli algoritmi moderni di crittazione simmetrica sono molto molto sicuri. La fragilità del sistema simmetrico è intrinseca al sistema stesso: l'informazione più importante, la chiave, si deve trovare in due posti contemporaneamente. Inoltre quanto più spesso viene usata, tanto più vulnerabile diventa la crittazione (la statistica si fonda sui grandi numeri, più mesaggi crittati allo stesso modo sono disponibili, più appigli ci sono per decrittarli). Inoltre ci deve essere un accordo preventivo sulla chiave da usare, questo accordo deve essere fatto lungo un canale "sicuro", altrimenti la crittazione è inutile. La chiave di quando in quando va rinnovata, per quei problemi di vulnerabilità già detti, quindi la nuova chiave deve essere ritrasmessa in qualche modo tra i due partecipanti (le classiche valigette blindate legate con le manette al polso delle spie!) e questa è certamente un'enorme vulnerabilità del sistema. Non è nemmeno possibile pensare di trasmettere la nuova chiave sfruttando la vecchia crittazione, perché se qualcuno ha scoperto la vecchia chiave e intercetta il messaggio può venire a conoscenza anche della nuova chiave, e così via.

Un'ulteriore vulnerabilità (non detta a lezione) è che se malauguratamente qualcuno entrasse in possesso di UN messaggio cifrato, e dello STESSO messaggio non cifrato, potrebbe conoscere perfettamente la chiave, proprio per quelle caratteristiche dello XOR che dicevamo: se C=M⊕K, per ottenere K è sufficiente fare C⊕M!!! (praticamente decrittiamo la chiave col messaggio, invece che il messaggio con la chiave). C=M⊕K, conoscendo C e M possiamo fare M⊕C = M⊕M⊕K = K

Infatti (preso da Wikipedia nella voce di un sistema nazistra di cifratura, il sistema Lorenz):
Sul ponte-radio Vienna-Atene della Wehrmacht, in funzione dal 1941, ancora durante la fase sperimentale della macchina cifratrice, fu inviato uno stesso messaggio di circa 4.000 caratteri, due volte, una poco dopo l'altra, cifrato con la medesima posizione iniziale dei cilindri-chiave. Il destinatario aveva chiesto di ritrasmettere il messaggio poiché la parola iniziale SPRUCHNUMMER era stata sostituita con SPRUCHNR. Questo grave errore di un radiotelegrafista, commesso già all'inizio, doveva diventare decisivo per la futura violazione del sistema di cifratura Lorenz.
Tutti queti problemi venono risolti grazie ai moderni sistemi di cifratura a chiave Asimmetrica, dove esiste una chiave per crittare e una per decrittare, che verranno spiegati nella prossima lezione.

Con la crittografia ha esordito una delle menti più brillanti del Novecento, Alan Turing, che ha una storia straordinaria degna di essere letta e conosciuta. Con le sue idee ha dato vita a una serie enorme di riflessioni e di filoni scientifici, primo fra tutti quello della concezione dell'informatica come scienza, e non più solo come tecnologia. I computer fino a quel momento erano appunto questo: calcolatori. Con Turing sono diventate delle entità teoriche, matematiche, dei modelli teoretici sui quali si possono costruire concetti rivoluzionari.