Progetto e sviluppo di una PKI per la firma digitale

Transcript

Progetto e sviluppo di una PKI per la firma digitale
UNIVERSITA’ POLITECNICA DELLE MARCHE
Facoltà di INGEGNERIA
Corso di Laurea in Ingegneria Elettronica
Dipartimento di Elettronica, Intelligenza Artificiale e Telecomunicazioni
PROGETTO E SVILUPPO DI UNA PKI
PER LA
FIRMA D IGITALE BASATA SU SMART C ARD
IN AMBITO SANITARIO
Relatore
Tesi di laurea di
Chiar.mo Prof. Aldo Franco Dragoni
Matteo Liuti
Correlatore
Chiar.mo Prof. Paolo Puliti
Anno Accademico 2004/2005
Indice
Indice
Struttura della tesi....................................................................................... 1
Capitolo 1. INTRODUZIONE .................................................................... 3
1.1
Lo sviluppo dei sistemi informatici ................................................................ 4
1.2
Il problema della sicurezza ............................................................................ 4
1.3
La sicurezza nella Pubblica Amministrazione ............................................. 6
Capitolo 2. CRITTOGRAFIA .................................................................... 9
2.1
Concetti base di crittografia .......................................................................... 10
2.2
Crittografia Simmetrica................................................................................. 12
2.2.1
Cifratura a blocchi e a flusso. ............................................................... 14
Algoritmi a blocchi ........................................................................................... 14
Algoritmi a flusso.............................................................................................. 16
2.2.2
I principali algoritmi di cifratura simmetrica....................................... 17
Data Encryption Standard (DES)..................................................................... 18
Triple DES (TDES) ........................................................................................... 19
Advanced Encryption Standard (AES) ............................................................. 19
International Data Encryption Algorithm (IDEA) ........................................... 20
RC2 e RC4 ........................................................................................................ 21
2.3
Crittografia asimmetrica ............................................................................... 21
Algoritmi a chiave di cifratura pubblica .......................................................... 23
Algoritmi a chiave di decifratura pubblica ...................................................... 24
Uso combinato delle due tecniche .................................................................... 25
2.3.1
I principali algoritmi di cifratura asimmetrica..................................... 27
Rivest Shamir Adelman (RSA) .......................................................................... 28
Digital Signature Algorithm (DSA) ................................................................. 29
2.4
Considerazioni generali sulla sicurezza degli algoritmi crittografici......... 30
2.5
Funzione di Hash ............................................................................................ 32
2.6
Firma Digitale ................................................................................................. 34
2.6.1
Aspetti legali della firma digitale........................................................... 37
I
Indice
Capitolo 3. PUBLIC KEY INFRASTRUCTURE...................................41
3.1
Introduzione ....................................................................................................42
3.2
Il certificato a chiave pubblica.......................................................................43
3.2.1
Ciclo di vita di un certificato..................................................................45
3.2.2
Revoca di un certificato..........................................................................46
3.3
Certification Authority e Registration Authority ........................................48
3.3.1
Modello di fiducia...................................................................................48
3.3.2
Tipologie di collegamenti fra Autorità di Certificazione ......................49
Modello reticolare.............................................................................................50
Modello ad albero .............................................................................................52
Modelli a struttura ibrida .................................................................................53
3.3.3
3.4
Catene di certificazione ..........................................................................54
Standard...........................................................................................................57
3.4.1
Standard X.509 per i certificati a chiave pubblica ................................57
3.4.2
Standard PKCS.......................................................................................60
Capitolo 4. SMART CARD.......................................................................63
4.1
Aspetto di una Smart Card ............................................................................64
4.2
Architettura interna........................................................................................65
4.3
Tipi di Smart Card..........................................................................................66
4.4
Standard...........................................................................................................67
4.4.1
Standard ISO/IEC 7816 .........................................................................67
ISO/IEC 7816-1: Caratteristiche fisiche...........................................................69
ISO/IEC 7816-2: Dimensione e locazione dei contatti .....................................70
ISO/IEC 7816-3: Segnali elettrici e protocolli di trasmissione ........................71
4.4.2
Altri standard..........................................................................................73
4.4.3
Abstract Syntax Notation .......................................................................74
4.5
Funzionamento di una Smart Card...............................................................76
4.5.1
Sequenze di attivazione e disattivazione ................................................76
4.5.2
Sistema operativo....................................................................................78
4.5.3
File system ..............................................................................................79
4.5.4
Protocolli di trasmissione.......................................................................82
Protocollo T=0..................................................................................................82
Protocollo T=1..................................................................................................84
4.5.5
Application Protocol Data Unit .............................................................86
II
Indice
4.6
Interfaccia con le applicazioni ....................................................................... 88
4.6.1
PC/SC ..................................................................................................... 89
4.6.2
Open Card Framework .......................................................................... 90
4.6.3
Confronto tra OCF e PC/SC.................................................................. 92
4.6.4
Java Card ............................................................................................... 93
4.7
PKCS#11.......................................................................................................... 96
4.7.1
Caratteristiche tecnologiche .................................................................. 97
4.7.2
Sessioni................................................................................................... 98
Sessioni R/O...................................................................................................... 99
Sessioni R/W ................................................................................................... 100
Eventi di sessione............................................................................................ 100
4.7.3
Oggetti .................................................................................................. 101
Oggetti “Data”............................................................................................... 103
Oggetti “Key”................................................................................................. 103
Oggetti “Certificate”...................................................................................... 104
4.7.4
Considerazioni sulla sicurezza ............................................................ 105
4.7.5
Provider di sicurezza IAIK................................................................... 106
Capitolo 5. REALIZZAZIONE DEL PROGETTO............................. 109
5.1
Descrizione generale del progetto ............................................................... 110
5.1.2
5.2
Applicazione all’ambito sanitario........................................................ 112
Implementazione........................................................................................... 114
5.2.1
Strumenti utilizzati ............................................................................... 114
5.2.2
Installazione del Provider IAIK........................................................... 115
5.2.3
Software prodotto ................................................................................. 117
Software di inizializzazione ............................................................................ 118
Software di firma ............................................................................................ 122
Tool di gestione della smart card ................................................................... 125
Capitolo 6. CONCLUSIONI E SVILUPPI FUTURI ........................... 129
Appendice. CODICE JAVA................................................................... 133
Bibliografia .............................................................................................. 163
Ringraziamenti....................................................................................... 165
III
Struttura della tesi
Struttura della tesi
Ogni capitolo della tesi riguarda un argomento chiave del progetto
sviluppato. In questo lavoro hanno particolare importanza i concetti di
crittografia, infrastrutture a chiave pubblica e smart card. Per ognuno di essi
viene fornita prima una descrizione generale delle nozioni di base, andando poi
ad approfondire i concetti più importanti e inerenti al progetto.
Il primo capitolo fornisce una visione breve e introduttiva dell’evoluzione
dei sistemi informatici e dei problemi di sicurezza ad essa legati, con uno
sguardo al settore della Pubblica Amministrazione.
Il secondo capitolo descrive le tecniche crittografiche simmetriche ed
asimmetriche, necessarie per comprendere l’argomento più importante di
questo lavoro che è la firma digitale. Di essa si spiegherà il funzionamento ed il
suo valore legale.
Il terzo capitolo si occupa dell’infrastruttura a chiave pubblica (Public Key
Infrastructure)
fornendone
una
descrizione
strutturale
e
funzionale
e
introducendo gli standard di base.
Il quarto capitolo è dedicato interamente alle Smart Card, alla loro
architettura, al loro funzionamento ed ai loro requisiti in termini di normative e
standard. Presenta anche una sezione che descrive il modo con cui
un’applicazione può interagire con la smart card servendosi di un apposito
provider di sicurezza.
Il quinto capitolo descrive il lavoro che ho realizzato in collaborazione con
la ASUR zona 7 della regione Marche. Verrà fornita prima una presentazione
generale per poi andare in dettaglio sui vari aspetti del progetto e sulle scelte
fatte.
Nel capitolo sesto sono espresse alcune considerazioni personali sul
lavoro svolto e vengono proposti dei possibili punti di sviluppo.
Infine l’appendice contiene il listato del software prodotto.
1
Struttura della tesi
2
Introduzione
Capitolo 1.
INTRODUZIONE
3
Capitolo 1
1.1
Lo sviluppo dei sistemi informatici
Lo sviluppo dei sistemi informatici negli ultimi anni ha compiuto passi da
gigante, sia per quanto riguarda la continua nascita di nuove tecnologie, sia per
la sempre più ampia possibilità di accesso a queste nuove conoscenze.
Indubbiamente un notevole contributo a questa diffusione deriva
dall’enorme successo di Internet. Dal suo predecessore ARPANET (nato nel
1969 dalla collaborazione tra alcune università degli Stati Uniti1) e soprattutto
dall’introduzione del World Wide Web (nel 1992 da parte del CERN) e del
protocollo HTTP con il quale i server Web comunicano tra loro, si è verificata
una vera e propria rivoluzione che ha reso alla portata di tutti risorse che prima
erano inaccessibili. La facilità di acceso e di uso del Web, unita alla possibilità
di offrire contenuti in modo immediato, consente ai singoli e alle aziende di
rendere massima l’efficienza e la chiarezza delle comunicazioni.
Con gli anni questa sempre maggiore diffusione ha reso internet una
necessità, portando enormi vantaggi ma anche una notevole quantità di rischi.
1.2
Il problema della sicurezza
E’ perfettamente intuibile come la facilità di accesso ad un qualunque
sistema favorisca l’accesso anche da parte di persone che non hanno intenzioni
del tutto benevole. Sono sempre più frequenti infatti i cosiddetti “crimini
informatici” ad opera di soggetti che penetrano nei sistemi per visualizzare,
modificare o addirittura cancellare informazioni sensibili, o con il semplice
intento di recare danno al sistema. Le tecniche di accesso sono diverse e
vanno dal “social engineering”, allo “sniffing”, allo “scan” e così via. Le
conseguenze di questi crimini possono essere disastrose, specialmente se il
sistema in questione è quello di una grande azienda.
1
Per la nascita di ARPANET hanno collaborato l’Università dello Utah, l’Università di California e lo
Stanford Research Institute, finanziati dal progetto “Advanced Research Projects Agency” del governo
degli Stati Uniti.
4
Introduzione
Il problema della sicurezza dei sistemi informatici è quindi un argomento
molto importante che deve essere sempre considerato (nelle giuste misure2)
qualunque sia il sistema di cui si disponga. In questo scenario ci vengono in
aiuto diversi strumenti come la crittografia, la firma digitale, le PKI e le Smart
Card che impareremo a conoscere nel corso di questa trattazione.
Da quanto detto si delineano due aspetti su cui è opportuno intervenire:
•
controllo degli accessi al sistema;
•
protezione dei dati sensibili.
Il primo punto coinvolge il problema dell’autenticazione, cioè del
riconoscimento di chi accede al sistema. Si possono individuare, a tal proposito,
tre livelli di sicurezza:
•
Autenticazione ad un fattore: basata su qualcosa che l’utente sa. E’ il
caso di una coppia di login costituita da nome utente e password.
•
Autenticazione a due fattori: basata su qualcosa che l’utente sa e
qualcosa che l’utente ha. E’ il caso che esamineremo di una smart card
con PIN di autenticazione.
•
Autenticazione a tre fattori: basata su qualcosa che l’utente sa,
qualcosa che l’utente ha ed una caratteristica unica dell’utente. E’ il caso
di sistemi che integrano funzionalità di controllo biometriche come
impronte digitali, cornea o altro.
Per quanto riguarda la protezione dei dati sensibili, questa avviene
mediante l’impiego di particolari funzioni crittografiche.
La crittografia è una tecnica che ci consente di proteggere i nostri dati
rendendoli incomprensibili a chiunque, a meno che non abbia la chiave giusta
per decifrarli. In questo modo anche se un messaggio che viaggia in rete
venisse intercettato da un soggetto male intenzionato, egli non potrebbe mai
sapere che cosa tale messaggio in realtà contiene. Questo permette di
garantire la segretezza di una comunicazione, in quanto solo chi è in possesso
della chiave di decifratura può interpretare correttamente il messaggio.
2
Si tenga sempre presente che il livello di sicurezza di un sistema deve essere proporzionale
all’importanza delle informazioni che si intende proteggere.
5
Capitolo 1
Livelli di sicurezza ancora più elevati si raggiungono con la crittografia
asimmetrica che impiega due chiavi (una pubblica e una privata) per effettuare
le operazioni di cifratura e decifratura.
La crittografia (nello specifico la quella asimmetrica) trova impiego (ed
anzi è alla base) del processo di firma digitale. Questa ha lo stesso ruolo della
firma autografa su documento cartaceo3, cioè serve a garantire l’autenticità del
documento, ossia la corretta identità del mittente. In generale, quando si allega
la firma digitale ad un documento informatico si garantisce l’autenticità
dell’autore e l’integrità della trasmissione, cioè il fatto che nessuno abbia
modificato il documento dopo l’invio.
L’impiego di queste tecniche richiede una struttura capace di gestire
correttamente l’uso delle chiavi pubbliche di crittografia (tramite l’utilizzo di
appositi certificati4) e in grado di fornire i protocolli di comunicazione e le regole
base per offrire i servizi crittografici. La struttura in questione prende il nome di
Public Key Infrastructure (PKI).
Una PKI offre un elevato livello di sicurezza finché le chiavi pubbliche e
private vengono gestite correttamente, da qui l’esigenza di trovare un mezzo
che ci consenta di custodire la nostra chiave privata in estrema sicurezza, ma
anche di poterla portare sempre con noi. Il problema trova soluzione con
l’impiego delle Smart Card, cioè schede capaci non solo di contenere dati al
loro interno, ma anche di elaborarli5.
1.3
Da
La sicurezza nella Pubblica Amministrazione
qualche
anno
a
questa
parte
il
settore
della
Pubblica
Amministrazione sta attraversando una crescente informatizzazione dei servizi.
L’obiettivo principale è quello di creare servizi on-line, orientati alle necessità
dei cittadini e delle imprese e capaci di rendere più semplice e rapida ogni
interazione con le Pubbliche Amministrazioni. Inoltre si intende eliminare
gradualmente la documentazione cartacea sostituendola con documenti
3
Per una descrizione più dettagliata sugli aspetti legali della firma digitale si rimanda al paragrafo §2.6.1.
I certificati a chiave pubblica, appunto.
5
Da cui appunto il nome di scheda intelligente.
4
6
Introduzione
informatici usufruendo delle citate tecniche di crittografia e firma digitale. I
vantaggi che ne scaturiscono sono molto rilevanti: si va da una maggiore
efficienza e velocità dei servizi, ad un più facile accesso ai servizi stessi, ad una
migliore archiviazione delle informazioni, alla possibilità di effettuare ricerche
più
veloci
e
più
mirate,
alla
possibilità
di
consultare
sedi
diverse
indipendentemente dalla loro posizione geografica. Un progetto sicuramente
ambizioso ma necessario per stare al passo con il continuo sviluppo
tecnologico.
Abbiamo già parlato dei rischi che comporta l’apertura di un qualsiasi
sistema informatico alla rete telematica, e nel caso delle Pubbliche
Amministrazioni è di particolare importanza il problema della non divulgazione
dei dati sensibili degli utenti. Questo si traduce nella necessità di realizzare un
sistema di comunicazione in grado di garantire la riservatezza e la segretezza
dei dati scambiati.
Un apposito ente governativo, il CNIPA (Centro Nazionale per
l’Informatica nella Pubblica Amministrazione6), ha il preciso obiettivo di dare
supporto alla Pubblica Amministrazione nell’utilizzo efficace dell’informatica per
migliorare la qualità dei servizi e contenere i costi dell’azione amministrativa.
Diversi progetti sono stati sviluppati ed alcuni sono già operativi a livello
regionale, come ad esempio il progetto “ESCAPE7” (Electronic Signature in
Care Activities for Paper Elimination) della regione Veneto, “CRS-SISS8” (Carta
Regionale dei Servizi – Sistema Informativo Socio-Sanitario) della regione
Lombardia, “SUT9” (Sportello Unico del Territorio) e “Progetto People10” della
regione Marche.
A livello nazionale invece esistono due progetti che riguardano la Carta
di Identità Elettronica (CIE) e la Carta Nazionale dei Servizi (CNS) per
l’autenticazione
dell’individuo
e
l’accesso
ai
servizi
delle
pubbliche
amministrazioni.
La CIE è stata emessa dai comuni in sostituzione della carta d’identità
tradizionale. Essa adotta una smart card ibrida (cioè che presenta, oltre al
6
www.cnipa.gov.it
www.progettiescape.it
8
www.crs.lombardia.it
9
www.sportellounico.marche.it
10
www.progettopeople.it
7
7
Capitolo 1
microchip, anche una banda ottica) e i dati del titolare (compresa la foto) sono
impressi in modo visibile sul supporto fisico della scheda e memorizzati sia
all’interno del chip che della banda ottica. Questa doppia tecnologia da garanzie
sulla sicurezza dei dati e consente il riconoscimento in rete del titolare. La carta
d’identità elettronica è stata individuata come strumento di semplificazione del
rapporto tra Pubblica Amministrazione e cittadini, cercando di salvaguardare
diversi obiettivi, tra i quali:
•
maggiore sicurezza nel processo di identificazione ai fini di polizia;
•
utilizzo quale strumento di identificazione in rete per l’accesso ai servizi
telematici;
•
completa interoperabilità su tutto il territorio nazionale.
Per quanto riguarda la Carta Nazionale dei Servizi, invece, questa
definisce uno standard per favorire la convergenza degli strumenti di
identificazione digitale. La CNS, progettata parallelamente alla CIE, ha il fine di
anticipare le funzioni di accesso ai servizi in rete e rappresenta il punto di
riferimento per l’emissione di carte multiservizi. Mediante questa carta, infatti, è
possibile ottenere servizi sanitari, fiscali, usufruire di sistemi di pagamento
bancari e postali e utilizzare la firma digitale.
8
Crittografia
Capitolo 2.
CRITTOGRAFIA
9
Capitolo 2
2.1
Concetti base di crittografia
La crittografia è 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 rilevabile11.
Il termine deriva dal greco crypto che significa “nascondere” e graphein che
significa “scrivere”, infatti la crittografia è stata definita anche come la scienza
della scrittura segreta12.
Parallelamente alla crittografia si sviluppa un’altra disciplina che prende il
nome di crittoanalisi e si occupa di recuperare il contenuto di un messaggio
cifrato senza disporre delle informazioni necessarie alla decifratura. Ambedue
le discipline sono governate da una branca della matematica che va sotto il
nome di crittologia.
La crittografia è stata sempre presente nella storia dell’uomo, anche se
in forme diverse. Il più semplice esempio risale ai tempi di Giulio Cesare che
nella sua corrispondenza scambiava l’ordine delle lettere spostandole di quattro
verso destra in modo che la A risultasse la D e così via.
Figura 1. Esempio di cifrario di sostituzione monoalfabetica impiegato da Giulio Cesare.
E’ una tecnica molto semplice di cifrario di sostituzione monoalfabetica che
risulta completamente inefficace una volta noto l’algoritmo utilizzato.
L’evoluzione delle tecniche crittografiche ha avuto una svolta proprio
quando si è deciso di rendere pubblici gli algoritmi di cifratura e decifratura dei
messaggi, legando la capacità di leggerne correttamente il contenuto ad una
ulteriore informazione che è appunto la chiave di decifratura. Da qui nascono le
moderne tecniche di crittografia come la crittografia simmetrica e quella
11
12
Bruce Schneider: “Applied Cryptography Second Edition: protocols, algorithms and source code in C”
Jonathan Knudsen: “Java Cryptography”.
10
Crittografia
asimmetrica che vedremo approfonditamente nei prossimi paragrafi. I vantaggi
che questo nuovo modo di pensare ha portato sono molti:
•
la pubblicazione degli algoritmi rende possibile il loro studio da parte dei
crittoanalisti di tutto il mondo consentendo di scoprirne eventuali
debolezze;
•
come conseguenza del punto precedente si hanno nuovi algoritmi
sempre più sicuri;
•
si rendono molto più accessibili le tecniche di protezione dati anche ad
aziende che non dispongono di personale specializzato.
Grazie a queste nuove tecniche un sistema crittografico è in grado di
garantire i seguenti requisiti:
•
Autenticazione d’identità: verifica dell’identità di una o entrambe le
parti coinvolte in una comunicazione;
•
Integrità dei dati: il documento trasmesso deve contenere tutte le
informazioni in esso presenti sin dalla redazione, con la possibilità di
verificare le eventuali alterazioni, intenzionali o meno, che i dati possono
aver subito attraversando un canale insicuro;
•
Autenticità dei dati: verifica dell’effettiva identità del mittente;
•
Non ripudio: impossibilità, da parte sia del mittente che del destinatario,
di negare l’avvenuto scambio di dati.
Nel seguito del capitolo andremo a studiare le principali tecniche di
crittografia
simmetrica
e
asimmetrica,
analizzandone
il
principio
di
funzionamento, i pregi e i difetti. Verranno inoltre fornite delle brevi indicazioni
sugli algoritmi che queste tecniche adottano, focalizzando maggiormente
l’attenzione sull’algoritmo RSA, in quanto è forse il più conosciuto ed è quello
impiegato nello sviluppo di questo progetto.
Negli esempi e negli schemi che verranno riportati si farà spesso
riferimento ad un ipotetico scambio di dati tra un “Mittente” e un “Destinatario”.
La situazione si presenta in questo modo:
11
Capitolo 2
Mittente
Messaggio
in chiaro
Messaggio
cifrato
Cifratura
Chiave
Canale di
trasmissione
Destinatario
Messaggio
in chiaro
Chiave
Decifratura
Messaggio
cifrato
Figura 2. Schema di principio di una comunicazione cifrata tra due entità
Il messaggio originale (messaggio in chiaro) viene opportunamente cifrato con
una apposita chiave. Il risultante messaggio cifrato sarà spedito sul canale di
trasmissione e giungerà al destinatario che effettuerà le operazioni di
decifratura per recuperare il contenuto originale del messaggio. Lungo il canale
il messaggio è visibile a tutti, ma questo non compromette la sicurezza della
comunicazione in quanto, essendo cifrato, solo chi è in possesso dell’apposita
chiave è in grado di comprenderne il contenuto.
2.2
Crittografia Simmetrica
La crittografia simmetrica, detta anche a chiave segreta, utilizza algoritmi
che impiegano un’unica chiave sia per le operazioni di cifratura sia per quelle di
decifratura13.
Il mittente e il destinatario devono essere in possesso della stesa chiave per
fare in modo che l’intera operazione abbia successo. L’uso di una chiave
diversa comporterebbe l’impossibilità di recuperare le informazioni dal
messaggio cifrato e, di conseguenza, la necessità di ripetere la trasmissione.
La sicurezza è garantita fintantoché la chiave rimane a conoscenza solo dei
due interlocutori e segreta ad ogni altro14.
13
14
Da qui il nome di crittografia simmetrica.
Da qui il nome di crittografia a chiave segreta.
12
Crittografia
Lo schema di funzionamento è il seguente:
Mittente
Messaggio
in chiaro
Messaggio
cifrato
Cifratura
Chiave
Canale sicuro
Canale insicuro
Destinatario
Messaggio
in chiaro
Decifratura
Messaggio
cifrato
Figura 3. Schema di funzionamento di una comunicazione cifrata con tecnica simmetrica.
Come si può vedere il funzionamento è molto simile allo schema di crittografia
di base introdotto precedentemente. Si può notare però l’impiego di due canali
di trasmissione: un canale sicuro15 riservato alla chiave segreta ed un canale
insicuro in cui viene spedito il messaggio cifrato.
Il mittente e il destinatario devono innanzitutto concordare in segreto la chiave
da utilizzare per la cifratura e decifratura, il mittente quindi, prima dell’invio del
messaggio, genera la chiave segreta e la spedisce al destinatario attraverso un
canale sicuro.
Il difetto principale di questa tecnica sta proprio in questo scambio, in
quanto, anche se si adotta un canale sicuro, c’è sempre il rischio che le
informazioni vengano intercettate e, poiché l’informazione che sta viaggiando in
rete è proprio la chiave segreta, la sua intercettazione comprometterebbe la
sicurezza di tutta la comunicazione. In questo caso infatti verrebbe meno non
solo il requisito di segretezza, ma anche quelli di integrità del messaggio ed
autenticazione del mittente. Se una terza parte infatti riuscisse ad entrare in
possesso della chiave segreta, potrebbe intercettare il messaggio cifrato,
modificarlo e cifrarlo di nuovo, senza che il destinatario si accorga di nulla.
Un altro svantaggio della crittografia simmetrica riguarda il fatto che ogni
utente deve disporre di una chiave diversa per ogni altro utente con cui intenda
15
Ad esempio un canale SSL.
13
Capitolo 2
comunicare. Questo rappresenta un problema tanto più serio quanto più il
numero di utenti è elevato. Per avere un riscontro pratico si pensi che in un
generico sistema di n utenti ci si troverebbe a dover gestire un numero di chiavi
segrete pari a:
n ⋅ (n − 1)
.
2
2.2.1 Cifratura a blocchi e a flusso.
Gli algoritmi impiegati nella crittografia simmetrica si possono distinguere
in due categorie:
•
algoritmi a blocchi: l’operazione di cifratura o decifratura viene effettuata
su gruppi di bit (o byte, o parole) detti appunto blocchi;
•
algoritmi a flusso: l’operazione di cifratura o decifratura viene effettuata
sui singoli bit (o byte, o parole).
Algoritmi a blocchi
Il messaggio da cifrare (o decifrare) viene suddiviso in blocchi di
lunghezza prefissata (solitamente 64 bit) e l’algoritmo viene applicato ad
ognuno di questo blocchi singolarmente. E’ necessario che il messaggio abbia
lunghezza esattamente multipla della dimensione del blocco altrimenti si verifica
un errore nell’applicazione dell’algoritmo. Per evitare questo problema si
prevede
il
riempimento
dell’ultimo
blocco
con
opportuni
caratteri
di
allineamento. Questo procedimento è noto come “pad” ed in figura è riportato
l’esempio di un messaggio suddiviso in n blocchi in cui al blocco n-esimo sono
stati aggiunti i caratteri di riempimento (parte tratteggiata).
14
Crittografia
Blocco 1
Blocco 2
…..
Blocco 3
Blocco
n-1
Blocco n
Figura 4. Esempio di suddivisione in blocchi di un messaggio e
applicazione dei caratteri di riempimento (tratteggio).
Esistono diversi modi per eseguire l’operazione di “pad” a seconda dei
diversi tipi di dato. Di seguito vengono brevemente descritti quelli più comuni:
•
il più semplice di tutti non fa altro che aggiungere zeri fino al
raggiungimento della lunghezza stabilita per il blocco;
•
se i dati sono binari si integra il blocco con bit che sono l’opposto degli
ultimi bit costituenti il messaggio;
•
nel caso di caratteri ASCII si usano byte di riempimento casuali
specificando nell’ultimo byte il carattere ASCII corrispondente al numero
di byte aggiunti;
•
un’ultima tecnica impiega anch’essa bit di riempimento casuali, ma negli
ultimi tre bit vengono indicati il numero di bit originali (quindi non
aggiunti) che costituiscono l’ultimo blocco. Un difetto di questa tecnica si
incontra quando il messaggio è esattamente multiplo della dimensione
del blocco (ad esempio 64 bit) e quindi non si necessiterebbe di alcun
tipo di padding. In questo caso si dovrà aggiungere un ulteriore blocco
con 61 bit random e gli ultimi tre nulli.
Citiamo ora i più comuni algoritmi a blocchi:
•
Electronic Codebook (ECB): è il metodo più semplice in cui il risultato
dell’operazione dipende solo dal valore della chiave. In questo modo,
fissata una chiave K, un certo blocco B al quale viene applicato
l’algoritmo darà come risultato sempre lo stesso blocco B’. Questa
caratteristica di univocità del risultato apre la strada all’elaborazione
parallela, in cui diversi blocchi del messaggio possono essere trasformati
in modo indipendente (anche da più calcolatori) ottenendo lo stesso
risultato di una elaborazione singola ma a tutto vantaggio della velocità di
esecuzione. L’altra faccia della medaglia riguarda il fatto che un
crittoanalista (o peggio un hacker che sia entrato in possesso della
15
Capitolo 2
chiave segreta) può risalire dal messaggio cifrato a quello originale
tramite un attacco a forza bruta, ovvero cifrando diversi messaggi fino a
che non ottiene la stessa sequenza cifrata16.
•
Cipher Block Chaining (CBC): questa tecnica prevede che ciascun
blocco in chiaro venga messo in XOR con in blocco cifrato precedente e
poi ulteriormente cifrato con la chiave segreta. Questo modo di
procedere fa si che il risultato dell’operazione ad ogni blocco dipenda
non solo dalla chiave utilizzata, ma anche dalla cifratura di tutti i blocchi
precedenti. Diventa così impossibile effettuare un attacco a forza bruta
su un blocco n-esimo del messaggio senza conoscere anche i
precedenti, in quanto non è più detto che due blocchi uguali, cifrati con la
stessa chiave, diano lo stesso risultato. Rimane il fatto però che due
messaggi identici saranno cifrati in modo identico. Per evitare ciò viene
allora inserito in testa ad ogni blocco da cifrare un vettore di
inizializzazione, che non è altro che un blocco casuale di dati.
•
Cipher Feedback (CFB): i blocchi vengono “incatenati” in modo molto
simile a quello della tecnica precedente. In questo caso però ogni blocco
cifrato viene messo in XOR con il corrente blocco in chiaro spezzettato in
segmenti più piccoli. La cifratura elementare di un blocco viene quindi
effettuata su gruppi di 4 o 8 bit alla volta man mano che questi giungono
al cifratore. L’idea è quella di elaborare i dati non appena divengono
disponibili invece di aspettare che un blocco sia del tutto completato.
Algoritmi a flusso
Negli algoritmi simmetrici a flusso il messaggio in chiaro si presenta in
ingresso come un stream (un flusso, appunto) di dati e l’operazione di cifratura
(o decifratura) viene effettuata su ogni singolo bit (o byte) di ingresso.
Più in dettaglio questi algoritmi fanno uso di un generatore di bit che, a
seconda della chiave fornita, è in grado di produrre una sequenza di bit
16
Si intende in questo tipo di attacco che la terza persona (crittoanalista o hacker che sia) sia a
conoscenza della chiave segreta e comunque la buona riuscita dell’attacco richiede tempi lunghissimi
(tanto più lunghi quanto più è grande il blocco).
16
Crittografia
apparentemente casuale17. Nell’effettiva operazione di cifratura i dati in ingresso
vengono messi in XOR con i dati provenienti dal generatore. In questo modo
non si verifica mai che due messaggi identici, cifrati con la stessa chiave, diano
origine a due messaggi cifrati uguali.
Gli algoritmi a flusso a loro volta si possono dividere in due categorie:
•
Algoritmi autosincronizzanti: in questo tipo di algoritmi il generatore di
numeri casuali prende in ingresso, ad ogni passo, anche un certo
numero di bit cifrati precedentemente. Quindi, comunque sia fissata una
chiave, uno stesso bit (o byte) potrà essere cifrato ogni volta in modo
diverso a seconda delle precedenti informazioni elaborate dal flusso in
ingresso.
•
Algoritmi sincroni: in questi algoritmi il flusso di bit generati è
completamente indipendente dal flusso di dati in ingresso. Questo
comporta il vantaggio di ridurre la propagazione degli errori: si pensi ad
esempio ad un canale di trasmissione rumoroso in cui si verifica un
errore su un bit durante l’invio del messaggio cifrato. In ricezione il
decifratore sbaglierà, ovviamente, il bit incriminato, ma questo errore non
si ripercuoterà su altri bit, in quanto non c’è la dipendenza dagli stati
precedenti
(come
invece
avviene
nel
caso
degli
algoritmi
autosincronizzanti).
2.2.2 I principali algoritmi di cifratura simmetrica
Verranno ora presentati alcuni tra i più noti algoritmi impiegati nella
crittografia simmetrica. Per ognuno di essi si illustreranno i concetti base
riguardanti il loro funzionamento e si effettueranno delle brevi considerazioni
sulla loro sicurezza.
17
Tale sequenza di bit pseudocasuali è il risultato di complesse operazioni aritmetiche che si basano sui
parametri costituenti la chiave. Di fatto risulta (quasi) impossibile prevedere la sequenza generata senza
conoscere la chiave.
17
Capitolo 2
Data Encryption Standard (DES)
Il Data Encryption Standard (DES) venne adottato dal governo degli Stati
Uniti nel 1977 come standard per la crittografia simmetrica. E’ stato sviluppato
dalla IBM come evoluzione di un altro algoritmo, Lucifer, risalente ai primi anni
‘70. Sebbene la sua validità dovesse essere programmata di 5 o 10 anni, il DES
è rimasto un riferimento per molti anni a seguire18.
L’algoritmo che utilizza, il DEA (Data Encryption Algorithm), rientra nella
classe dei codici a blocchi ed è utilizzabile con tutti i modelli visti
precedentemente. Ogni blocco ha la dimensione di 64 bit.
Più in dettaglio il DES impiega blocchi di 64 bit ed utilizza chiavi di
cifratura di 64 bit suddivise in 8 sottoblocchi di 8 bit ciascuno. L’ultimo bit di ogni
sottoblocco è di controllo, di conseguenza è come se avessimo a che fare con
una chiave a 56 bit.
Durante la cifratura il blocco di testo in chiaro viene innanzitutto trasposto
e poi diviso in una metà destra e una metà sinistra di 32 bit ciascuna. In
seguito, ad ognuna di queste metà, vengono applicate 16 passate (dette round)
tramite una funzione che opera trasposizioni e sostituzioni mediante apposite
sottochiavi19. Durante ogni round l’output della metà sinistra diventa l’input della
destra e viceversa. Dopo il completamento di tutti i round i due sottoblocchi
vengono riuniti e il risultato permutato per invertire la trasposizione iniziale.
L’operazione di decifratura avviene in modo del tutto analogo, con la sola
accortezza di assegnare le sottochiavi in ordine inverso a quello utilizzato
durante la cifratura.
Questo algoritmo, che potrebbe a prima vista sembrare molto cavilloso,
in realtà sfrutta operazioni molto semplici come trasposizione, sostituzione e
XOR di bit. Nonostante abbia resistito anche più del dovuto come standard, il
DES non è considerato un algoritmo molto sicuro ed è utilizzato per la cifratura
di dati relativamente importanti. Il difetto maggiore è il limitato spazio delle
chiavi (keyspace20) di cui dispone che è pari a 256. Esistono inoltre delle
18
Già nei primi anni 90 non era più considerato abbastanza sicuro e nel 1998 è stato violato per la prima
volta.
19
Le sottochiavi vengono ricavate dividendo i bit effettivi che costituiscono la chiave in due sottoblocchi
di 28 bit ciascuno. Ad ogni round questi semiblocchi vengono sciatati verso sinistra dando origine alle
sottochiavi.
20
Per keyspace si intende l’insieme di tutte le chiavi, diverse l’una dall’altra, ricavabili come
combinazione di n bit (dove n rappresenta la dimensione della chiave).
18
Crittografia
perplessità riguardanti la sua sicurezza derivanti dal ruolo che ha avuto l’NSA21
nel validare l’algoritmo. In particolare si contesta la scelta di ridurre la
dimensione delle chiavi da 128 bit a 64 bit, dando adito a congetture sulla
robustezza di DES.
Triple DES (TDES)
Una evoluzione del DES può essere considerata il triplo-DES (noto
anche come DESede), così denominato in quanto utilizza tre chiavi indipendenti
in tre diversi passaggi. Ci sono molte varianti del TDES, di seguito ne
illustreremo due tra le più comuni.
La prima impiega sue chiavi K1 e K2 di 56 bit ciascuna raddoppiando così
l’effettiva lunghezza della chiave (che ora è di 112 bit) ed incrementando il
keypsace di un fattore 256. Ogni blocco di 64 bit viene prima cifrato con la prima
chiave (K1), poi decifrato con la seconda (K2), poi di nuovo cifrato ancora con la
prima chiave (K1). Questo modo di procedere rende TDES un algoritmo molto
più sicuro del precedente.
Una particolarità riguarda il fatto che se le due chiavi K1 e K2 risultassero uguali,
allora l’applicazione di questo algoritmo porterebbe un risultato identico
all’applicazione dell’algoritmo DES.
Un’altra versione di TDES sfrutta tre chiavi diverse e indipendenti da 56
bit ciascuna, con un effettivo keyspace di 168 bit. Ogni blocco viene cifrato per
tre volte, ogni volta con una chiave diversa. E’ sicuramente un algoritmo più
complesso e più costoso (soprattutto in termini di tempo) dei precedenti, ma è
anche il più sicuro.
Advanced Encryption Standard (AES)
E’ un algoritmo di cifratura a blocchi, noto anche come algoritmo di
Rijndael22, sviluppato dai crittografi belgi Joan Daemen e Vincent Rijmen. E
stato adottato dalla National Institute of Standards and Technology (NIST) e
dalla US Federal Information Processing Standard (FIPS) nel novembre 2001.
21
22
National Security Agency
Più propriamente AES è una particolare implementazione dell’algoritmo Rijndael.
19
Capitolo 2
Ogni blocco ha dimensione fissa di 128 bit e possono essere impiegate
chiavi di 128, 192 o anche 256 bit. AES opera su delle matrici chiamate stati.
Con 128 bit in input (ovvero le dimensioni di un blocco) ogni stato è composto
da 4 righe e 4 colonne di 32 bit ciascuna, cioè matrici di 4x4 byte. Durante la
cifratura, ad ogni fase (round), vengono eseguite le operazioni sostituzione,
spostamento, combinazione lineare dei byte ed inoltre ogni byte viene
combinato in XOR con una chiave di sessione calcolata dal gestore delle chiavi.
Questo algoritmo presenta molti vantaggi, primo fra tutti la possibilità di
impiego di chiavi di lunghezza diversa e comunque tale da garantire un ottimo
livello di sicurezza. Si pensi che, secondo l’NSA, la dimensione di una chiave
impiegata per cifrare dati Top Secret deve essere di 192 o 256 bit. Inoltre AES
è di facile implementazione sia hardware che software e le sue richieste di
risorse sono limitate. Questo lo rende applicabile a qualsiasi tipo di strumento
capace di eseguire operazioni crittografiche ed è un grosso incentivo per la sua
diffusione.
International Data Encryption Algorithm (IDEA)
IDEA è nato nel 1991 sotto il nome di IPES (Improved Proposed
Encryption Standard) ideato dai crittologi Xuejja Lai e James L. Massey. E’
anch’esso un algoritmo a blocchi di 64 bit ed è applicabile a tutti i modelli di
cifratura a blocchi.
Utilizza chiavi a 128 bit e l’operazione di cifratura comporta una divisione
del blocco in chiaro in quattro sottoblocchi di 16 bit. Ognuno subisce otto round
di trasformazioni durante le quali vengono eseguite le operazioni di XOR dei bit,
addizione e moltiplicazione modulare. Nell’ultimo round i quattro sottoblocchi
vengono concatenati per produrre il blocco cifrato.
Durante gli otto round sono coinvolte nelle operazioni 52 chiavi diverse (sei per
ogni round) che vengono ricavate dividendo la chiave iniziale in otto stringhe di
16 bit che costituiscono le prime otto chiavi. In seguito i 128 bit della chiave
originale vengono shiftati di 25 bit a sinistra ottenendo una nuova sequenza che
verrà ancora divisa in otto stringhe a 16 bit per ricavare altre otto sottochiavi.
Iterando il procedimento si ricavano tutte le 52 sottochiavi.
20
Crittografia
L’operazione di decifratura è identica eccezion fatta per il modo con cui
vengono ricavate le sottochiavi.
Offre un buon grado di sicurezza, al livello del TDES23 ed il suo utilizzo
per scopi non commerciali è libero.
RC2 e RC4
Questi algoritmi sono stati sviluppati dalla RSA Data Security Inc. e
l’ideatore è Ron Rivest24. Sono algoritmi applicabili sia nella cifratura a blocchi
che in quella a flusso.
In particolare RC2 opera una tripla cifratura, come nel caso TDES, ma
risulta molto più veloce. La caratteristica dei due algoritmi è che utilizzano chiavi
di lunghezza arbitraria come seme per un generatore di numeri pseudo-casuali
che vengono messi in XOR con i dati da cifrare.
Sono giudicati algoritmi sicuri, ma il loro libero utilizzo è limitato a sole
chiavi di lunghezza non superiore di 40 bit.
2.3
Crittografia asimmetrica
Nel 1976 Whitfield Diffie e Martin Hellmann, due crittologi americani,
pubblicarono uno scritto in cui, ipotizzando di poter disporre di un cifrario
asimmetrico, dimostravano la fattibilità di sistemi crittografici di nuovo tipo
mediante il concetto di chiavi pubbliche. Un sistema di questo tipo si sarebbe
servito di due chiavi distinte, l’una l’inverso dell’altra, con le seguenti
caratteristiche:
•
complementari: se una chiave è usata per cifrare l’altra deve essere
usata per decifrare e viceversa;
•
indipendenti: la conoscenza di una chiave non deve consentire di risalire
all’altra chiave.
Di fatto è stato il punto di inizio dal quale si sono poi sviluppate tutte le
tecniche che vedremo nel corso della trattazione.
23
24
Alcuni crittologi sostengono sia migliore IDEA, altri invece sostengono il contrario.
Da cui il nome RC: Ron’s Code (o Rivest’s Code).
21
Capitolo 2
La crittografia asimmetrica, detta anche crittografia a chiave pubblica,
prevede l’utilizzo di due chiavi diverse per le operazioni di cifratura e
decifratura. Una di queste chiavi deve rimanere nota al solo possessore, che
quindi è l’unica persona in grado di utilizzarla. Tale chiave è detta chiave
privata. L’altra chiave invece può essere resa liberamente nota ed è utilizzabile
da qualsiasi utente necessiti il suo impiego in una comunicazione. Tale chiave è
detta chiave pubblica. Le due chiavi sono legate matematicamente tra loro,
ma costruite in modo che sia impossibile risalire alla chiave privata partendo da
quella pubblica. La distribuzione delle chiavi pubbliche avviene tramite l’utilizzo
di appositi certificati, detti certificati a chiave pubblica, ed è affidata ad una
entità detta Autorità di Certificazione.
Questi concetti verranno ripresi ed approfonditi nel capitolo successivo
riguardante l’infrastruttura a chiave pubblica, per ora ci basta sapere che un
certificato è un mezzo tramite il quale vengono rese note le chiavi pubbliche di
un particolare utente, e l’Autorità di Certificazione ci garantisce che quella
chiave appartiene effettivamente all’utente in questione.
Nella crittografia asimmetrica un messaggio cifrato con una delle due
chiavi della coppia può essere decifrato solo con la chiave ad essa associata.
L’ordine di utilizzo delle chiavi è arbitrario ai fini della corretta decifratura, quindi
è possibile cifrare un messaggio con la propria chiave privata e decifrarlo con
quella pubblica, oppure cifrare con la chiave pubblica e decifrare con quella
privata. In ambedue i casi si è capaci di risalire correttamente al messaggio
originale, ciò che cambia riguarda alcuni requisiti di sicurezza che vedremo tra
poco.
Proprio sulla base dell’arbitrarietà di utilizzo delle chiavi è possibile
dividere gli algoritmi asimmetrici in due categorie:
•
algoritmi a chiave di cifratura pubblica: impiegano la chiave pubblica in
cifratura e quella privata in decifratura;
•
algoritmi a chiave di decifratura pubblica: impiegano la chiave privata in
cifratura e quella pubblica in decifratura.
22
Crittografia
Algoritmi a chiave di cifratura pubblica
Il funzionamento di questo tipo di algoritmi asimmetrici è illustrato nello
schema seguente in cui si considera l’esempio di una comunicazione tra un
generico “Mittente” ed un altrettanto generico “Destinatario”. Si indicano con
KprivD e KpubD rispettivamente le chiavi privata e pubblica del destinatario.
Mittente
Messaggio
in chiaro
Messaggio
cifrato
Cifratura
KpubD
Canale insicuro
KpubD
KprivD
Destinatario
Messaggio
in chiaro
Decifratura
Messaggio
cifrato
Figura 5. Schema di funzionamento di un algoritmo a chiave di cifratura pubblica.
E’ opportuno fare una considerazione prima di proseguire. Nello schema
viene raffigurato l’invio della chiave pubblica dal destinatario al mittente (la
freccia tratteggiata). Questa rappresentazione vuole solo indicare che la chiave
pubblica che si utilizza appartiene effettivamente al destinatario, e che il
mittente, in qualche modo, ne viene in possesso. Il modo in cui questo avviene
è stato citato ad inizio capitolo e verrà approfondito nella prossima sezione.
Il funzionamento dei questo schema è molto semplice e ricorda quello a
cifratura simmetrica, eccezion fatta per la distinzione tra chiave pubblica e
privata. Il Mittente cifra il messaggio in chiaro con la chiave pubblica del
Destinatario, quest’ultimo riceve il messaggio cifrato e, tramite l’utilizzo della
propria chiave privata, riesce a risalire al messaggio originale.
Ricordiamo che l’impiego di una qualsiasi altra chiave nella decifratura
darebbe un risultato del tutto senza senso e, di conseguenza, l’impossibilità da
parte del destinatario di conoscere il messaggio originale. Questa caratteristica
dell’algoritmo, unita alla fondamentale proprietà di uso esclusivo delle chiavi
23
Capitolo 2
private da parte dei soli possessori, garantisce un importante requisito di
sicurezza: la segretezza della comunicazione. Infatti il Mittente, utilizzando la
chiave pubblica del Destinatario, sa che quel messaggio potrà essere decifrato
solo dall’effettivo possessore della chiave associata. Anche se il cifrato venisse
intercettato da una terza entità (ricordiamo che si fa uso di un canale insicuro)
questa non sarà capace di comprenderne il significato.
Il difetto di questo schema sta nel fatto che il Destinatario non può essere
sicuro dell’effettiva identità del mittente, in quanto chiunque può procurarsi la
sua chiave pubblica e spedirgli dei messaggi cifrati.
Algoritmi a chiave di decifratura pubblica
Lo schema di funzionamento è illustrato nella figura seguente in cui con
KprivM e KpubM si intendono rispettivamente le chiavi privata e pubblica del
mittente. Anche in questo caso valgono le considerazioni dell’esempio
precedente riguardanti lo scambio della chiave pubblica tra i due interlocutori.
24
Crittografia
Mittente
Messaggio
in chiaro
Messaggio
cifrato
Cifratura
KprivM
KpubM
Canale insicuro
KpubM
Destinatario
Messaggio
in chiaro
Decifratura
Messaggio
cifrato
Figura 6. Schema di funzionamento di un algoritmo a chiave di decifratura pubblica.
Il Mittente cifra il messaggio in chiaro con la propria chiave privata ed il
Destinatario utilizza la chiave pubblica del Mittente per decifrare il messaggio.
In questo modo, se il destinatario riesce a recuperare correttamente il
messaggio originale, vuol dire che questo è stato cifrato con la chiave privata
associata a quella pubblica che ha utilizzato nella decifratura, e solo una
persona ha la facoltà di usufruire di detta chiave privata: il Mittente. In altre
parole il destinatario è sicuro dell’effettiva identità del mittente, viene cioè
garantito con questo schema un altro requisito di sicurezza fondamentale:
l’autenticazione d’identità.
Dall’altra parte però viene meno la caratteristica di segretezza (tipica del
caso precedente) in quanto chiunque può venire a conoscenza della chiave
pubblica del mittente e quindi chiunque è in grado di decifrare il messaggio.
Questo tipo di cifratura trova largo impiego nei sistemi che fanno uso
della firma digitale, come vedremo più avanti nel corso del capitolo.
Uso combinato delle due tecniche
Abbiamo visto come i due schemi di cifratura asimmetrica riescano a
garantire alternativamente la segretezza della comunicazione e l’autenticazione
del mittente. Sono però queste due caratteristiche troppo importanti che devono
25
Capitolo 2
essere presenti contemporaneamente in una comunicazione crittografata. Si
può allora pensare di adottare contemporaneamente i due schemi in modo
combinato così da poter raggiungere un livello di sicurezza ancora maggiore.
Il risultato dell’impiego delle due tecniche è riportato nel seguente
schema:
Mittente
Text
T’
Cifratura
KprivM
Cipher
Cifratura
KpubD
Canale insicuro
Destinatario
Text
T’
Decifratura
Cipher
Decifratura
KpubM
KprivD
Figura 7. Schema di utilizzo della cifratura asimmetrica per l’invio di un messaggio
autenticato e segreto.
Con “Text” si vuole indicare il messaggio in chiaro, “T’” rappresenta un
messaggio cifrato intermedio diverso da quello finale che viene spedito al
mittente e che è invece indicato con “Cipher”. Per quanto riguarda le chiavi si
ha la stessa nomenclatura dei casi precedenti.
Avvengono due successive operazioni di cifratura:
•
prima il Mittente cifra il messaggio in chiaro con la propria chiave privata
ottenendo un messaggio intermedio T’;
•
poi T’ viene ancora cifrato con la chiave pubblica del Destinatario
ottenendo il messaggio cifrato finale (Cipher).
In ricezione il Destinatario andrà a decifrare il messaggio prima
impiegando la sua chiave privata e poi quella pubblica del Mittente.
26
Crittografia
In realtà, in cifratura, l’ordine di utilizzo delle due chiavi è arbitrario, ma
deve essere noto, in quanto chi riceve il messaggio dovrà eseguire la
decifratura impiegando le chiavi in ordine inverso.
In termini di sicurezza l’utilizzo della chiave privata del mittente
garantisce la proprietà di autenticazione del messaggio, mentre l’impiego della
chiave privata del destinatario garantisce la segretezza della trasmissione.
Un’ultima considerazione riguarda l’incremento del numero delle chiavi
all’aumentare del numero di utenti che vogliono comunicare tra loro. Questo
problema era particolarmente sentito nella crittografia simmetrica in cui si aveva
un incremento quadratico delle chiavi. Nella crittografia asimmetrica non è
invece necessario che un utente crei una chiave diversa per ogni
comunicazione con un altro utente. Ognuno infatti dispone di una propria coppia
di chiavi ed utilizza sempre questa coppia per comunicare con qualsiasi altro
utente. In questo modo si ha un incremento lineare del numero di chiavi in
funzione del numero di utenti.
Nella realtà lo schema appena descritto non è molto utilizzato perché
piuttosto complesso. Non è raro invece l’utilizzo di tecniche miste che
uniscono la semplicità della crittografia simmetrica con la sicurezza di quella
asimmetrica. L’esempio più immediato riguarda la tecnica impiegata nel
protocollo SSL25 in cui, nella comunicazione tra due entità, viene creata “al volo”
una chiave segreta, detta chiave di sessione, per cifrare il messaggio. La
chiave a sua volta viene cifrata con la chiave pubblica del destinatario ed
allegata al messaggio stesso.
2.3.1 I principali algoritmi di cifratura asimmetrica
La crittografia asimmetrica consente di cifrare solo blocchi di dati di
dimensione fissa. E’ infatti impossibile cifrare i dati in ingresso bit a bit come
avveniva negli algoritmi simmetrici a flusso. Possiamo quindi dire che la
crittografia asimmetrica lavora solo su blocchi di bit.
25
“Secure Socket Layer”, chiamato nelle sue ultime versioni con il nome di “Transport Layer Security”
(TLS).
27
Capitolo 2
In questo paragrafo verranno introdotti alcuni tra i più noti algoritmi di
crittografia asimmetrica, andando ad esaminare più in dettaglio solo uno tra
questi, l’algoritmo RSA, che, oltre ad essere forse il più famoso, è quello
impiegato in questo progetto di firma digitale.
Rivest Shamir Adelman (RSA)
L’algoritmo RSA è stato sviluppato da Ron Rivest, Adi Shamir e Len
Adelman26. Descritto per la prima volta nel 1977 è stato poi brevettato nel 1983
negli Stati Uniti dal MIT27.
Si basa sul problema matematico della fattorizzazione di un numero, che
consiste nel trovare quei numeri primi che, moltiplicati tra loro, forniscono il
numero dato. E’ questo un problema tanto più complesso quanto più è grande il
numero iniziale. Forniamo ora una breve descrizione dell’algoritmo.
Per generare la coppia di chiavi si eseguono queste operazioni:
1. si scelgono due numeri primi p e q abbastanza grandi da garantire un
adeguato livello di sicurezza;
2. si calcola il prodotto n = p ⋅ q (detto modulo);
3. si sceglie un numero e (detto esponente pubblico) che sia più piccolo e
primo rispetto a ( p − 1) ⋅ (q − 1) ;
4. si
calcola
un
numero
d
(detto
esponente
privato)
tale
che:
(e ⋅ d ) ⋅ mod[( p − 1) ⋅ (q − 1)] = 1 ;
5. la coppia (n, e ) costituisce la chiave pubblica, mentre la coppia (n, d )
costituisce la chiave privata.
A questo punto le chiavi sono state create ed i fattori p e q possono
essere distrutti (anche se in realtà vengono mantenuti all’interno della chiave
privata). Due chiavi create in questo modo sono chiaramente legate tra loro (dal
fattore n) e inoltre per calcolare d da e (e quindi la chiave privata a partire da
quella pubblica) non basta conoscere n, ma serve anche il prodotto
( p − 1) ⋅ (q − 1) . In ogni caso è un’operazione molto costosa in termini di tempo,
soprattutto se n è grande.
26
27
Il nome RSA è infatti acronimo dei loro cognomi.
Massachusetts Institute of Technology.
28
Crittografia
L’operazione di cifratura avviene nel seguente modo:
1. l’utente si procura la chiave pubblica del destinatario (n, e ) ;
2. il messaggio in chiaro m viene cifrato attraverso l’operazione
c = m e mod(n ) , in cui “c” indica il messaggio cifrato.
L’operazione di decifratura prevede che l’utente, con la propria chiave
privata (n, d ) , compia la seguente operazione: m = c d mod(n ) .
L’algoritmo permette anche di invertire l’ordine di utilizzo delle chiavi,
cioè è possibile cifrare con la chiave privata e decifrare con quella pubblica.
In ogni caso il procedimento restituisce il messaggio originale solo se le
chiavi utilizzate nella cifratura e nella decifratura appartengono alla stessa
coppia, e sono quindi legate dal fattore n secondo la relazione descritta nel
punto 4.
Da questa breve presentazione nasce però un dubbio sulla sicurezza
dell’algoritmo, in quanto si basa sull’assunzione che il calcolo di
e
c mod(n ) (con
n numero composto di cui non si conoscono i fattori) sia computazionalmente
intrattabile28. Il dubbio nasce dal fatto che questa assunzione non è mai stata
dimostrata!
Digital Signature Algorithm (DSA)
L’algoritmo DSA, proposto nel 1991 dal NIST per l’utilizzo nell’ambito
dello
standard
DSS
(Digital
Signature
Standard),
è
stato
progettato
appositamente per la realizzazione di firme digitali. Il procedimento di cifratura
infatti prevede anche l’utilizzo di una funzione di Hash29 (nello specifico la
funzione SHA) ed apposite operazioni di verifica della firma.
Esso si basa sulla difficoltà di risoluzione del problema del logaritmo
discreto. In linea teorica sarebbe possibile ricavare la chiave privata calcolando
il logaritmo discreto di quella pubblica. Nella realtà però questa operazione è
impraticabile a causa della grandezza dei numeri in gioco.
Tale algoritmo però non viene molto utilizzato in quanto esistono
algoritmi ritenuti molto più sicuri.
28
29
Nota come “assunzione RSA”.
La funzione di Hash sarà illustrata tra poco in questo stesso capitolo.
29
Capitolo 2
2.4
Considerazioni
generali
sulla
sicurezza
degli
algoritmi crittografici
Ogni algoritmo crittografico viene studiato dai crittoanalisti per valutarne
l’effettiva robustezza a vari tipi di attacchi e quindi misurarne la sicurezza.
Nel corso di tutto il capitolo sono stati presentati molti algoritmi diversi tra
loro, ognuno con determinate caratteristiche che lo rendevano più o meno
sicuro di un altro. Come detto ad inizio capitolo, però, l’evoluzione crittografica
più importante si è verificata quando è stato abbandonato il principio di security
by obscurity secondo il quale un sistema (in questo caso un particolare
algoritmo crittografico) risulta sicuro fintantoché rimane segreto alle persone
non autorizzate ad accedervi, in quanto, non conoscendolo, non sono in grado
di violarlo. Ad esso si è sostituito il concetto, che è diventato un fondamento
della crittografia moderna, secondo il quale la sicurezza di un sistema
crittografico dipende esclusivamente dalla conoscenza della chiave.
Tutti gli algoritmi introdotti nei paragrafi dedicati alla crittografia simmetrica e
asimmetrica sono infatti di dominio pubblico ed il loro funzionamento è noto a
chiunque, eppure questo non costituisce una minaccia alla loro sicurezza, anzi,
al contrario, è un incentivo al loro sviluppo, in quanto è più facile scoprirne difetti
e debolezze e quindi porvi rimedio.
Ciononostante la chiave non è altro che una sequenza di bit generata in
modo più o meno casuale che, in linea teorica, può sempre essere ricavata.
Esistono infatti dei metodi di ricerca esaustiva che consentono di risalire alla
chiave utilizzata nella cifratura provando ad applicare l’algoritmo ad un testo
cifrato, impiegando chiavi sempre diverse, fino a che non si ottiene un risultato
sensato. Questo modo di procedere è noto come “attacco a forza bruta” (brute
force attack). Il successo di questo tipo di attacchi dipende dal numero massimo
di tentativi che possono essere fatti, ovvero dal numero massimo di chiavi che
quel particolare algoritmo può accettare, cioè dal keyspace.
Per darci un’idea di quanto influisca la lunghezza della chiave in un
attacco a forza bruta si può considerare l’esempio riportato in tabella che indica
30
Crittografia
i tempi necessari al completamento dell’attacco variando le dimensioni della
chiave, sotto l’ipotesi di poter effettuare un milione di tentativi al secondo.
Lunghezza
della chiave
Dimensioni
del keyspace
Tempo di
ricerca
32 bit
4,29*109
1,2 ore
40 bit
1,1*1012
13 giorni
48 bit
56 bit
64 bit
2,81*10
14
8,9 anni
7,21*10
16
2.300 anni
1,84*10
19
580.000 anni
Tabella 1. Tempo di ricerca necessario per un attacco a forza bruta nell’ipotesi che si possano
effettuare un milione di tentativi al secondo.
Ancora una volta la sicurezza del sistema è legata solo alla chiave ed in
particolare ad una sua caratteristica che è la lunghezza. Si può decidere di
scegliere una chiave talmente lunga da rendere materialmente impossibile un
attacco a forza bruta30, questo però comporterebbe anche una notevole
riduzione delle prestazioni del nostro sistema, in quanto una chiave più lunga
richiederebbe calcoli più complessi e quindi un rallentamento delle operazioni di
cifratura e decifratura. Occorre quindi trovare un giusto compromesso tra il
grado di sicurezza che si vuole raggiungere e la velocità di esecuzione
richiesta31.
In generale, quando si vuole realizzare un sistema di sicurezza, bisogna
sempre tenere presente che tipo di dati si stanno proteggendo. Il livello di
sicurezza del sistema deve essere tanto più alto quanto più sono sensibili le
informazioni in gioco. In quest’ottica è opportuno seguire due linee guida:
•
il costo32 richiesto per violare l’algoritmo deve essere superiore al valore
dei dati protetti;
•
il tempo richiesto per violare l’algoritmo deve risultare superiore al tempo
per cui i dati cifrati devono rimanere segreti.
30
Si intende con le tecnologie attualmente disponibili. In futuro un aumento delle capacità di calcolo o
una nuova tecnica di crittoanalisi potrebbe ridurre drasticamente i tempi necessari al recupero della
chiave.
31
Si pensi in particolare al caso della Smart Card che sono dispositivi estremamente sicuri, ma con
limitatissime risorse di calcolo.
32
Si intende “costo” non solo in senso monetario, ma anche in termini di risorse e tempo impiegati.
31
Capitolo 2
Sotto queste ipotesi, qualsiasi tentativo di attacco, anche se andasse a buon
fine, non comporterebbe alcun vantaggio al soggetto attaccante.
2.5
Funzione di Hash
La funzione di Hash è un processo di trasformazione dei bit, che si
differenzia dagli algoritmi crittografici finora trattati.
Un qualsiasi messaggio elaborato tramite funzione di Hash restituisce
una stringa di bit di lunghezza fissa (solitamente 128 o 160 bit), detta message
digest (impronta digitale). Tale impronta rappresenta una sorta di riassunto, o
sintesi matematica, del messaggio.
Andiamo ora ad enunciare le proprietà che caratterizzano la funzione di
Hash e che la rendono “crittograficamente sicura” :
•
è applicabile a qualsiasi sequenza di dati di qualsiasi tipo e dimensione;
•
il risultato della sua applicazione è una stringa di bit di dimensione fissa
(128 o 160bit) indipendente dalla dimensione del messaggio originale;
•
la variazione di un solo bit del messaggio originale comporta la
variazione dell’intero digest;
•
è una funzione a senso unico (one way), cioè risulta impossibile risalire
al messaggio originale partendo dal digest;
•
è una funzione senza collisioni (collision free), nel senso che è
impossibile trovare due messaggi diversi tra loro che restituiscano lo
stesso digest.
E’ necessario a questo punto fare una precisazione.
Negli ultimi due punti si è utilizzato il termine “impossibile”. Questo in
realtà non è del tutto corretto, sarebbe più opportuno parlare di “bassa
probabilità” piuttosto che di “impossibilità”.
Come abbiamo detto, la funzione di Hash restituisce sempre una
sequenza di lunghezza fissa indipendentemente dal tipo e dalla dimensione del
messaggio originale. In termini più precisi si può dire che la funzione di Hash
realizza una applicazione non iniettiva che ha come dominio uno spazio a
dimensione infinita (che rappresenta l’insieme di tutti i messaggi in chiaro di
32
Crittografia
qualsiasi lunghezza) e come codominio uno spazio a dimensione finita (che
rappresenta l’insieme di tutti i possibili digest di lunghezza prefissata).
Figura 8. Rappresentazione della funzione di Hash come applicazione
dall’insieme infinito V dei messaggi in chiaro all’insieme finito W di tutti
i possibili digest di lunghezza prefissata.
Di fatto effettua una compressione dello spazio, per questo motivo prima
è stata utilizzata l’espressione di “riassunto matematico” per definire l’impronta
di un messaggio. Risulta però matematicamente impossibile (e questa volta il
termine è impiegato correttamente) che ad ogni elemento del dominio
corrisponda un unico elemento del codominio! La matematica comunque ci
assicura anche che la probabilità che a due elementi distinti del dominio
corrisponda uno stesso elemento del condominio è, se pur diversa da zero,
estremamente bassa. In senso pratico non si sono ancora trovati due messaggi
diversi che abbiano lo stesso digest.
Da questa considerazione si può ritenere ragionevole l’assunto che la
funzione di Hash risulti crittograficamente sicura, cioè a senso unico e priva di
collisioni.
Una conseguenza immediata di quest’ultima proprietà è che può risultare
altrettanto ragionevole dire che “due messaggi che presentato lo stesso digest
sono uguali tra loro”. Questa è una definizione particolarmente interessante in
quanto ci permette di utilizzare la funzione di Hash ogniqualvolta ci interessi
confrontare due messaggi tra loro per verificarne l’uguaglianza. Essendo i
33
Capitolo 2
messaggi di dimensioni arbitrarie, infatti, risulta sicuramente più comodo
eseguire il confronto direttamente sui digest che sono a lunghezza fissa.
Questa tecnica apre la strada ad una delle più importanti applicazioni
della funzione di Hash: la firma digitale.
Prima di concludere il paragrafo facciamo una veloce panoramica sugli
algoritmi che la funzione di Hash utilizza:
•
MD5 (Message Digest 5): è un algoritmo sviluppato dai laboratori RSA
che fornisce digest di 128 bit;
•
SHA (Secure Hash Algorithm): chiamato anche Secure Hash Standard
(SHS) è un algoritmo pubblicato dal Governo degli Stati Uniti che
produce digest di 160 bit;
•
SHA-1: è la versione migliorata del precedente algoritmo. Produce
anch’esso digest di 160 bit, ma, a differenza del suo predecessore,
l’SHA-1 non è stato ancora violato.
2.6
Firma Digitale
Si è già discusso sulla tendenza, da parte di enti pubblici e privati, ad
eliminare (o quantomeno ridurre) la documentazione cartacea e favorire quella
digitale, evidenziando i vantaggi che questo comporterebbe in termini di:
•
migliore gestione degli archivi;
•
più efficienza nei servizi;
•
minor costo;
•
realizzazione di sistemi sicuri che garantiscano: autenticazione d’identità,
integrità dei dati, autenticità dei dati, non ripudio.
La firma digitale rende possibile tutto questo in quanto, lo dice la parola
stessa, consente la firma di documenti direttamente in formato digitale. Questo
processo deve essere ovviamente regolamentato da opportune normative
giuridiche che garantiscano adeguati livelli di sicurezza, ma di queste ci
occuperemo nel prossimo paragrafo.
La firma digitale è una tecnologia matematico-informatica che consente
la creazione e la gestione di documenti informatici sicuri, ovvero documenti dei
34
Crittografia
quali sia possibile attribuirne la provenienza soggettiva e verificarne l’integrità
del contenuto dal momento della loro formazione.
Alla base del processo di firma digitale troviamo due concetti già noti,
che sono la crittografia asimmetrica e la funzione di Hash.
In particolare, della crittografia asimmetrica, si sfrutta l’algoritmo a chiave
di decifratura pubblica secondo il quale un documento viene cifrato con la
chiave privata del mittente consentendo sempre la sua piena identificazione.
La funzione di Hash invece ci consente di rendere la cifratura più
semplice e veloce, in quanto non viene cifrato il documento originale, ma bensì
la sua impronta (digest) che sappiamo essere di lunghezza fissa.
Vediamo ora come si realizza la firma digitale di un qualsiasi documento
informatico:
Mittente
Text
Digest
Hash
Cifratura
Firma
KprivM
Text + Firma
Figura 9. Processo di firma digitale di un documento informatico.
Il processo prevede tre stadi principali:
•
generazione del digest: il messaggio originale (Text) viene elaborato
mediante la funzione di Hash ottendo così la sua impronta (Digest);
•
generazione della firma: il digest viene cifrato con la chiave privata del
mittente (KpriM);
•
apposizione della firma: al messaggio in chiaro si allega la firma
precedentemente ottenuta (ed eventualmente il certificato contenente la
chiave pubblica di decifratura).
35
Capitolo 2
Il documento firmato così ottenuto viene inviato al destinatario che, a sua
volta, dovrà eseguire dei controlli per assicurarsi della validità della firma. Le
operazioni che compie sono riportate nel seguente schema:
Hash
Text
Digest
Destinatario
Text + Firma
Confronto
Firma
Decifratura
Digest
presunto
KpubM
Figura 10. Processo di verifica della firma digitale.
Il processo di verifica della firma digitale prevede i seguenti stadi:
•
il documento firmato viene diviso nella parte di documento in chiaro ed in
quella relativa alla firma e le due parti vengono elaborate separatamente;
•
il documento in chiaro viene sottoposto alla funzione di Hash e se ne
calcola il digest;
•
la firma viene decifrata con la chiave pubblica del mittente (recuperata
dal certificato relativo al mittente stesso) ottenendo così il “digest
presunto”, ovvero l’impronta del documento originale al momento della
firma;
•
i due digest vengono tra loro confrontati e a questo punto ci sono due
possiblità:
o i digest risultano uguali: allora la firma è valida ed il documento è
integro;
o i digest sono diversi: significa che il documento ha subito delle
modifiche (dolose o accidentali) dal momento in cui è stato firmato
dal mittente a quello in cui è stato ricevuto dal destinatario.
La firma digitale così ottenuta lega l’entità, che detiene l’uso esclusivo
della chiave privata, ai dati, tramite l’impiego del digest. Infatti ogni firma, anche
se apposta con la stesa chiave privata, è unica e diversa in relazione ad un
diverso documento.
36
Crittografia
Questo tipo di firma offre tutte le garanzie di sicurezza di una normale
firma autografa, portando in più due vantaggi fondamentali:
•
è più difficile da falsificare: in quanto si dovrebbe entrare in possesso
della chiave privata del mittente;
•
garantisce l’integrità del documento: la modifica anche di un solo bit del
documento comporta la variazione dell’intero digest.
Prima di discutere gli aspetti legali vorrei puntualizzare un aspetto che è
passato un po’ in secondo piano per dare maggiore risalto ai processi di firma e
verifica.
Da quanto detto il documento firmato, costituito dal testo in chiaro con
allegata la firma, viene spedito al destinatario su un canale telematico. E’
opportuno precisare che in questa operazione vengono utilizzati canali di
comunicazione sicuri (come ad esempio SSL) e quindi in rete viaggiano sempre
messaggi cifrati. In questo modo rimane garantita la segretezza della
trasmissione.
Inoltre non è necessario che il documento e la sua firma si trovino sullo
stesso supporto digitale, le due parti possono anche essere separate e spedite
su canali diversi senza che per questo venga meno il legame esistente fra di
esse33.
2.6.1 Aspetti legali della firma digitale
La sicurezza di una operazione giuridica, cioè la possibilità di
dimostrarne efficacemente l’esistenza e il contenuto, deriva dal poter disporre di
una documentazione sicura, ossia non alterabile o che mantenga traccia delle
eventuali alterazioni.
Oggi la funzione di mezzo probatorio è assolta fondamentalmente dai
documenti cartacei, tuttavia l’impiego sempre più frequente delle nuove
tecnologie ha fatto sorgere l’esigenza di riconoscere uno status giuridico ai
documenti su supporto informatico e la loro validità ai fini probatori. A questo
33
Con l’accortezza che il destinatario disponga di un sistema in grado di riconoscere e recuperare le due
parti.
37
Capitolo 2
scopo devono essere garantiti i requisiti fondamentali di integrità, non
modificabilità e autenticazione. Nel caso del tradizionale supporto cartaceo
questo è possibile grazie all’inscindibilità fisica tra contenuto (il testo del
documento) e contenitore (il foglio di carta) e all’apposizione della sottoscrizione
autografa. Diversamente, nel caso dei documenti informatici, il medesimo
contenuto è facilmente riproducibile su diversi contenitori, ed ogni copia risulta
esattamente identica all’originale. Grazie alle elaborazioni previste nel processo
di firma digitale è possibile rendere il documento informatico altrettanto sicuro
garantendo tutti i requisiti necessari.
La legislazione italiana è stata tra le prime a livello mondiale a dettare
una disciplina organica in materia di firma digitale e documento informatico.
L’introduzione nel nostro ordinamento dell’istituto della firma digitale è avvenuto
in modo progressivo.
Il primo passo risale alle normativa del 15 marzo 1997 noto come “Legge
Bassanini” in materia di riforma della Pubblica Amministrazione e di
semplificazione amministrativa. Esso testualmente disponeva che “gli atti, dati e
documenti formati dalla pubblica amministrazione e dai privati con strumenti
informatici o telematici, i contratti stipulati nelle medesime forme, nonché la loro
archiviazione e trasmissione con strumenti informatici, sono validi e rilevanti a
tutti gli effetti di legge”.
In attuazione da quanto previsto da tale norma il 10 novembre 1997 è
stato emesso il decreto legge n.513 contenente i criteri e le modalità per la
formazione, l’archiviazione e la trasmissione di documenti con strumenti
informatici e telematici.
In seguito, l’8 febbraio 1999, fu emanato un successivo decreto recante
le regole tecniche per la formazione, la trasmissione, la duplicazione, la
riproduzione e la validazione, anche temporale, dei documenti informatici.
Successivamente
l’Autorità
per
l’Informatica
nella
Pubblica
Amministrazione34 ha elaborato uno schema di Testo Unico delle disposizioni
legislative e regolamentari in materia di documentazione amministrativa,
applicabile per la parte relativa ai documenti informatici e alla firma digitale
34
Oggi CNIPA: Centro Nazionale per l’Informatica nella Pubblica Amministrazione.
38
Crittografia
anche nei rapporti tra privati. Tale testo è stato approvato definitivamente il 6
ottobre 200 ed è entrato in vigore il 28 dicembre dello stesso anno.
Questa serie di normative ha sancito la totale equiparazione della firma
digitale alla sottoscrizione autografa e del documento informatico firmato
digitalmente alla scrittura privata, purché conforme alle disposizioni del Testo
Unico.
39
Capitolo 2
40
Public Key Infrastructure
Capitolo 3.
PUBLIC KEY INFRASTRUCTURE
41
Capitolo 3
3.1
Introduzione
Nel capitolo precedente si è discusso il funzionamento di alcune tecniche
crittografiche e si sono fatte delle considerazioni sulla loro sicurezza. In
particolare abbiamo visto che le applicazioni di firma digitale utilizzano algoritmi
crittografici asimmetrici e che la sicurezza di questi algoritmi è legata
esclusivamente alla segretezza della chiave privata. Di questo ovviamente si
deve occupare l’utente stesso cercando di divulgare il meno possibile le
informazioni riguardanti la sua chiave privata e soprattutto evitando di
delegarne l’uso a terzi. Si consiglia l’utente di dotarsi di apposite Smart Card
che rendono il compito più semplice.
Questo però non basta per garantire del tutto la sicurezza del sistema.
La firma digitale lega infatti un documento non al suo autore, ma alla chiave
privata impiegata nell’operazione di cifratura. Si ha quindi bisogno di una entità
che ci assicuri che quella chiave appartiene ad una certa persona.
Inoltre un sistema informatico che faccia uso della firma digitale, per
essere completamente funzionante, deve poter gestire in modo corretto lo
scambio e la divulgazione delle chiavi pubbliche.
Si introduce così il concetto di infrastruttura a chiave pubblica35, in cui
un’autorità fidata si preoccupa di identificare e autenticare tutti gli utenti che
vogliano usufruire dei suoi servizi e garantisce inoltre l’appartenenza di una
chiave pubblica ad uno specifico utente mediante l’emanazione di un certificato.
Si può definire una PKI come un insieme di hardware, software, risorse
umane, protocolli, regole e procedure necessarie per fornire supporto all’utilizzo
su larga scala dei sistemi di crittografia asimmetrici.
Prima di
procedere alla descrizione di una PKI ritengo opportuno
spiegare il meccanismo di gestione delle chiavi pubbliche. Il prossimo
paragrafo, infatti, introdurrà il concetto di certificato a chiave pubblica, che
verrà poi ripreso nella parte dedicata agli standard.
35
PKI: Public Key Infrastructure
42
Public Key Infrastructure
3.2
Il certificato a chiave pubblica
Un certificato a chiave pubblica è un documento informatico che associa
una chiave pubblica ad un soggetto. In esso dovranno quindi essere scritti
alcuni dati necessari all’identificazione del soggetto stesso.
Per risultare valido, un certificato deve essere firmato da una apposita
entità (l’Autorità di Certificazione) che garantisca l’effettiva appartenenza della
chiave pubblica al soggetto in questione.
Un certificato a chiave pubblica deve quindi contenere:
•
Informazioni varie sul formato del certificato;
•
Subject: dati identificativi del soggetto;
•
Chiave pubblica del soggetto e informazioni relative (algoritmo di
cifratura utilizzato, impieghi previsti e altro);
•
Periodo di validità del certificato;
•
Issuer: dati identificativi dell’emettitore del certificato;
•
Signature: un digest delle informazioni precedenti cifrato con la chiave
privata dell’emettitore.
In pratica un utente (soggetto) si rivolge ad una Autorità di Certificazione
per farsi rilasciare il certificato a chiave pubblica. In una comunicazione tra due
entità il mittente appone la firma sul documento originale ed invia il documento
firmato ed il certificato. Il destinatario deve verificare l’attendibilità del certificato
prima ancora di verificare la firma. Deve quindi decifrare la signature con la
chiave pubblica dell’issuer ottenendo un digest presunto da confrontare con il
digest ricavato da tutti gli altri campi del certificato elaborati con la funzione di
Hash. Se il confronto ha esito positivo allora il certificato è valido e si procede
alla verifica della firma.
Le figure sottostanti mostrano i processi di firma e verifica di un
certificato:
43
Capitolo 3
Root CA private key
Root certificate
enc
Data
Root CA public key
digest
hash
Signature
Subject certificate
enc
Data
digest
hash
Subject public key
Signature
Figura 11. Firma del certificato da parte di un soggetto e di una Autorità di Certificazione.
Root CA certificate
Data
Root CA public key
Signature
dec
Presumed digest
Subject certificate
Data
hash
digest
Subject public key
=? Ok
Signature
Figura 12. Verifica di un certificato a chiave pubblica.
L’impiego dei certificati a chiave pubblica non è comunque obbligatorio.
Nel Testo Unico36 si afferma che l’attività di certificazione è necessaria solo ove
si vogliano conseguire gli effetti di “validità e rilevanza a tutti gli effetti di legge”.
E’ del tutto lecito infatti scambiarsi documenti con la tecnica delle chiavi
asimmetriche senza ricorrere all’uso dei certificati, ad esempio nel caso in cui si
dispone di una rete di piccole dimensioni in cui ci si scambiano dati non troppo
riservati e quindi si può tollerare un livello di sicurezza meno restrittivo.
36
Vedi paragrafo § 2.6.1 “Aspetti legali della firma digitale”.
44
Public Key Infrastructure
La certificazione diventa necessaria quando si desidera che il documento
acquisti pieno valore probatorio.
In ultimo si può fare un’osservazione sul fatto che un certificato a chiave
pubblica lega una chiave pubblica ad una certa persona (che abbiamo chiamato
soggetto). In realtà eravamo partiti dall’esigenza di legare la chiave privata al
soggetto in questione. Una PKI in realtà non può gestire le chiavi private (per
evidenti motivi di sicurezza), ma abbiamo visto il legame matematico forte che
associa indissolubilmente le chiavi pubblica e privata. Un certificato quindi lega
un soggetto ad una coppia di chiavi, fornendosi della sola informazione di cui
può disporre, che è la chiave pubblica.
3.2.1 Ciclo di vita di un certificato
L’emissione effettiva di un certificato elettronico da parte di una Autorità
di Certificazione a favore di un utente finale deve essere preceduta da una fase
di registrazione dell’utente stesso. Attraverso il processo di registrazione
l’utente richiedente il servizio di certificazione si identifica presso l’autorità
preposta al servizio di registrazione. Le credenziali che in questa fase l’utente
deve sottoporre all’Autorità di Registrazione dipendono fortemente dalle
modalità e procedure di registrazione definita nell’ambito di una politica di
sicurezza.
Il processo di registrazione stabilisce una relazione iniziale tra utente
finale e Autorità di Certificazione. L’utente finale, una volta attestata l’autenticità
della sua identità, viene registrato nel dominio di fiducia gestito dalla CA.
L’obiettivo di primaria importanza del processo di registrazione è quindi quello
di garantire che la chiave pubblica, di cui un certo utente finale richiede la
certificazione, appartenga effettivamente al nome del richiedente.
Terminata la fase di registrazione, l’utente può richiedere l’emissione di
un certificato elettronico. La procedura di generazione di un certificato
elettronico consiste dei seguenti passaggi:
•
L’utente finale sottopone all’Autorità di Certificazione le informazioni da
certificare.
45
Capitolo 3
•
L’Autorità di Certificazione può verificare l’accuratezza delle informazioni
presentate in accordo a politiche e standard applicabili.
•
L’Autorità di Certificazione firma le informazioni generando il certificato a
chiave pubblica e lo inserisce in un database pubblico. Solitamente la CA
archivia una copia del certificato anche sul suo database privato. Ogni
operazione di generazione dei certificati elettronici viene registrata su un
archivio di registrazione dati.
Ogni certificato elettronico generato ha una validità temporale limitata, al
termine della quale va sostituito. Il periodo di validità di un certificato, in
assenza di compromissioni o di usi illeciti, garantisce l’utente che deve utilizzare
tale certificato che la chiave pubblica possa essere utilizzata per lo scopo per
cui è stata generata e che l’associazione tra la chiave pubblica e le altre
informazioni contenute nel certificato sia ancora valida.
3.2.2 Revoca di un certificato
L’operazione di revoca di un certificato costituisce una fase molto critica
della gestione del ciclo di vita dei certificati. Un certificato elettronico deve
essere revocato in presenza di almeno una delle seguenti condizioni:
•
Compromissione rilevata, o semplicemente sospettata, della chiave
privata corrispondente alla chiave pubblica contenuta nel certificato.
•
Cambiamento di una qualsiasi delle informazioni contenute nel certificato
elettronico o delle condizioni iniziali di registrazione.
La revoca del certificato elettronico è effettuata dalla Autorità di
Certificazione e generalmente viene avviata su richiesta dello stesso utente
finale. In questo caso, data la criticità e le implicazioni dell’operazione di revoca,
è indispensabile predisporre un sistema di autenticazione della richiesta di
revoca.
Ogniqualvolta un certificato viene revocato, tutti gli utenti appartenenti
alla stessa infrastruttura devono essere informati dell’avvenuta revoca. Il
meccanismo più comunemente utilizzato per la notifica su larga scala di
avvenute revoche fa uso della cosiddetta lista di revoca dei certificati (CRL:
46
Public Key Infrastructure
Certificate Revocation List). La gestione di tali liste è delegata alla
Certification Authority. Nell’ambito del dominio amministrato ogni CA pubblica
periodicamente una struttura dati contenente l’elenco dei certificati revocati,
ossia una lista firmata digitalmente dalla CA che riporta i certificati revocati, la
data temporale in cui è avvenuta la revoca ed eventualmente il motivo della
revoca. Di seguito è schematizzato il formato di una lista di revoca dei
certificato conforme allo standard X509.
Figura 13. Formato di una CRL secondo lo standard X509.
Le liste di revoca giocano un ruolo di fondamentale importanza in tutti i
processi crittografici, in quanto devono essere consultate sia in fase di cifratura,
sia in fase di verifica della firma. Infatti, prima di cifrare un messaggio, va
verificato che la chiave pubblica che si deve usare per la cifratura appartenga
ad un certificato valido. Analogo discorso vale per la verifica della firma, poiché
una firma può essere ritenuta valida solo se il certificato del firmatario, oltre ad
essere autentico ed integro, non è stato revocato.
47
Capitolo 3
3.3
Certification Authority e Registration Authority
Le principali entità che costituiscono una PKI sono:
•
Certification
Authority
(CA):
o
Autorità
di
Certificazione
(già
menzionata in precedenza) è l’entità che rilascia i certificati. Una CA
garantisce per un certo numero di utenti o per altre Autorità di
Certificazione. E’ un punto molto critico della struttura in quanto la
compromissione di una CA (ad esempio la venuta a conoscenza della
sua chiave privata da parte di terzi) potrebbe compromettere la sicurezza
dell’intera PKI. E’ quindi opportuno che sia l’hardware che il software che
hanno accesso diretto alla chiave privata della CA si trovino su una
macchina off-line.
•
Registration Authority (RA): o Autorità di Registrazione, è l’entità che
si occupa della creazione delle chiavi, della distribuzione dei certificati, di
assegnare gli identificativi (alias) ai client, di archiviare chiavi e certificati,
di generare e gestire le richieste di certificato e altro ancora. In pratica
svolge tutte quelle funzioni che servono per interfacciare l’utente con
l’Autorità di Certificazione.
3.3.1 Modello di fiducia
Abbiamo appena detto che una Autorità di Certificazione garantisce per
un certo numero di utenti o, eventualmente, per altre Autorità di Certificazione.
Questo significa che ogni utente che appartiene ad una certa AC è a
conoscenza delle chiavi pubbliche di tutti gli utenti appartenenti alla stessa AC e
può quindi verificare la firma di ognuno di essi. Nel caso fossero coinvolti gli
utenti di diverse AC, è necessario che le AC in questione emettano degli
appositi certificati (detti cross certificate) che consentano ad ogni utente di
fidarsi della AC esterna.
La modalità con cui l’utente arriva a fidarsi di un certificato emesso da
una AC a lui sconosciuta, partendo dalla fiducia che egli ripone in una singola
48
Public Key Infrastructure
AC a lui nota, viene indicata come modello di fiducia (Trust Model)
dell’infrastruttura. Più precisamente un modello di fiducia specifica in che modo
si può porre fiducia nell’asserzione che un utente remoto sia effettivamente chi
dice di essere (autenticazione) e che abbia effettivamente i diritti di accesso al
servizio o informazione che sta richiedendo (autorizzazione).
Quindi il modello di fiducia si pone alla base dell’infrastruttura a chiave
pubblica, specificando quali procedure riescono a garantire il corretto
funzionamento dei servizi di sicurezza offerti dall’infrastruttura stessa.
Un esempio di modello di fiducia è il cosiddetto web of trust (rete di
fiducia) utilizzato dal programma di cifratura PGP. In questo particolare modello
non si fa ricorso ad Autorità di Certificazione centralizzate, ma sono gli utenti
stessi a certificarsi reciprocamente le chiavi di cui possono garantire la
provenienza, firmandole. Tale meccanismo si basa sul presupposto che un
utente firmi la chiave pubblica altrui solo quando ha la certezza sull’identità del
suo titolare. Nessuno però può assicurare che venga firmata una chiave
pubblica sulla quale non sono stati esercitati accurati controlli.
Questo modello, anche se del tutto funzionale, non ha validità giuridica in
quanto ritenuto poco sicuro. Esistono comunque altri modelli, e li vedremo nel
prossimo paragrafo, che prevedono strutture reticolari o strutture gerarchiche
ad albero, e che hanno maggiore valenza legale.
3.3.2 Tipologie di collegamenti fra Autorità di Certificazione
In genere una PKI è composta da diversi Certificatori37 ognuno dei quali
garantisce per un certo numero di utenti. Nasce però un problema quando un
utente che si riferisce ad una CA riceve un messaggio da un altro utente che fa
riferimento ad un’altra CA. Non conoscendo quest’ultima l’utente non è in grado
di identificare il mittente, quindi cade un fondamentale requisito di sicurezza. Da
qui la necessità di far interagire tra loro le varie CA.
37
Nel “Testo Unico” dell’AIPA il nome di “Certification Authority” è stato tradotto in “Certificatore”,
anche se risulta di uso più comune la traduzione letterale “Autorità di Certificazione”. I due termini
indicano comunque la stessa entità ed in questo testo sono utilizzati in modo del tutto equivalente.
49
Capitolo 3
Esistono due modelli principali di collegamento fra Autorità di
Certificazione:
•
Modello reticolare: ogni CA nasce come autorità locale di cui si fidano
tutti e solo gli utenti appartenenti ad essa.
•
Modello ad albero: prevede una CA globale di cui tutti si fidano, che
distribuisce opportunamente le sue mansioni ad altre CA locali, ognuna
facente capo ad una comunità ristretta di utenti o ad altre CA ancora più
localizzate.
Modello reticolare
La figura sottostante indica un esempio di PKI composta da quattro
Autorità di Certificazione ognuna facente capo a tre utenti.
Figura 14. PKI strutturata secondo il modello reticolare.
L’interoperabilità tra Autorità di Certificazione diverse è ottenuta
mediante accordi fra le AC stesse.
Si supponga che l’utente U11 riceva un messaggio firmato dall’utente
U32 e ne voglia quindi verificare la firma. L’Autorità cui U11 fa riferimento (AC1)
non possiede la chiave di U32, quindi non è in grado di fornirla direttamente. E’
allora necessario che AC1 si metta in contatto con AC2 chiedendogli la chiave
di U32.
50
Public Key Infrastructure
In particolare, nella comunicazione tra le due Autorità di Certificazione,
AC1 verifica in primo luogo che AC2 adotti politiche di sicurezza uguali, o
comunque che garantiscano un livello di sicurezza almeno pari a quello
garantito dalle proprie politiche, in seguito AC1 rilascia un certificato, detto
cross certificate, che:
•
garantisce che una chiave certificata da AC2 è valida;
•
contiene la chiave di verifica dei certificati di AC2.
Tale certificato, una volta reso noto a tutti gli utenti appartenenti ad AC1,
permette loro di fidarsi di una chiave certificata da AC2.
E’ proprio grazie a questi cross certificate che un’Autorità di
Certificazione ripone la sua fiducia su un’altra AC. Di fatto un utente può
verificare la firma di un qualsiasi altro utente la cui AC abbia instaurato un cross
certificate con la propria.
Bisogna notare che questo modello prevede che, agli occhi di un utente,
sia sempre la propria Autorità di Certificazione a garantire l’autenticità delle
firma delle altre AC, in linea con un modello di distribuzione della fiducia che
prevede che ogni entità si fidi soltanto della AC di appartenenza.
Il rilascio dei cross certificate però presenta aspetti problematici. Prima di
rilasciare un cross certificate una Autorità di Certificazione deve assicurarsi che
l’altra AC garantisca un livello di sicurezza almeno pari a quello da lei offerto.
Questo in realtà non capita mai, perché le AC fanno riferimento a realtà
ambientali diverse fra loro e probabilmente anche di diversi paesi, quindi
soggette a specifiche politiche di sicurezza. Quello che in effetti è il vantaggio di
una struttura reticolare, cioè collegare diverse AC indipendenti fra loro, senza
creare un sistema centralizzato, si rivela un’arma a doppio taglio, in quanto
proprio questa indipendenza può manifestarsi come un limite alle possibilità di
comunicazione tra gli utenti.
In generale il livello di sicurezza di una Autorità di Certificazione, di
conseguenza l’affidabilità dei certificati da essa rilasciati, risulta determinato dai
seguenti fattori:
•
gli algoritmi crittografici impiegati nei processi di firma digitale;
•
le politiche di accesso agli elaboratori adottate;
•
il software utilizzato;
51
Capitolo 3
•
le procedure per l’identificazione e l’autenticazione preliminare degli
utenti.
Modello ad albero
Facendo uso delle stesse convenzioni del caso precedente, riportiamo
l’esempio di una PKI composta da quattro Autorità di Certificazione strutturata
secondo il modello ad albero.
Figura 15. PKI strutturata secondo il modello ad albero.
Nel modello ad albero esiste un’unica Autorità di Certificazione globale
della quale tutti gli utenti dell’infrastruttura di fidano. Ogni utente però non
interagisce direttamente con essa, ma con altre AC, ciascuna locale ad una
comunità ristretta di utenti.
Questo modello prevede che le AC siano distribuite gerarchicamente,
secondo una struttura ad albero, in cui ogni livello corrisponde ad una Autorità
di Certificazione con un ruolo diverso all’interno dell’infrastruttura. Ogni AC
garantisce per tutti i livelli ad essa sottostanti firmando i certificati a chiave
pubblica con la propria chiave privata. La AC globale, che è all’apice della
gerarchia, garantisce per se stessa con un certificato autofirmato.
52
Public Key Infrastructure
Si può definire il modello ad albero come un caso particolare del modello
reticolare, considerando i certificati che legano le AC “padre” con le AC “figlie”
dei veri e propri cross certificate. Ciò che distingue i due modelli è il fatto che
normalmente una AC padre rilascia un cross certificate per ogni AC figlia,
mentre non è necessario il procedimento inverso, cioè che le AC figlie rilascino
un cross certificate per la AC padre. Questo perché la struttura ad albero è
accentrata ed il possesso della chiave pubblica della AC radice permette la
verifica di qualsiasi certificato rilasciato da qualsiasi altra AC dell’albero. Un
utente infatti, per verificare il certificato emesso da un’altra AC, deve risalire la
gerarchia dell’albero verificando tutti i cross certificate che portano alla radice.
Questo tipo di collegamento tende a minimizzare il problema delle
diverse politiche di sicurezza adottate da ogni AC. La AC globale infatti ha
anche il compito di dettare delle linee di sicurezza alle quali tutte le AC facenti
parte dell’albero devono attenersi.
Nelle applicazioni pratiche, le PKI con effetti legali impiegano un modello
ad albero che si sviluppa su due livelli, con il livello superiore di emanazione
Statale o pubblica che certifica le autorità inferiori, normalmente private.
Modelli a struttura ibrida
In questo caso si hanno più infrastrutture ad albero che, per necessità di
cooperazione, si riuniscono in un’unica rete di AC secondo le modalità del
modello infrastrutturale a rete. Soltanto le AC radice devono rilasciarsi
mutuamente dei cross certificate, e questo garantisce l’interoperabilità fra tutte
le AC appartenenti agli alberi le cui radici si sono mutuamente certificate.
La situazione finale è simile a quella di una rete di AC, ma con una
differenza sostanziale: ogni utente continua a fidarsi soltanto della AC radice
dell’albero contenente la sua AC locale di appartenenza.
Una struttura ibrida di questo tipo è quella destinata a formarsi in una
realtà di ampiezza continentale o mondiale, in cui ogni stato sviluppa una
infrastruttura nazionale gerarchica indipendentemente dagli altri, poi, se le varie
infrastrutture sono compatibili tra loro, una serie di certificazioni mutue riesce a
garantire l’interoperabilità fra di esse.
53
Capitolo 3
3.3.3 Catene di certificazione
In uno scenario costituito da una molteplicità di Autorità di Certificazione
su larga scala, strutturate secondo un certo modello organizzativo, non è
pensabile che ogni utente abbia diretta conoscenza della chiavi pubbliche di
ogni potenziale interlocutore, sottoforma di certificato elettronico, o delle chiavi
pubbliche delle corrispondenti Autorità di Certificazione competenti.
Occorre quindi disporre di un meccanismo corretto di ritrovamento dei
certificati elettronici degli interlocutori appartenenti a domini di sicurezza esterni.
Il modello generale su cui si basano tutti i sistemi di distribuzione su larga scala
della chiavi pubbliche sottoforma di certificati elettronici, utilizza le cosiddette
catene di certificazione, anche note come cammini di certificazione.
Il problema del ritrovamento di un cammino di certificazione consiste
sostanzialmente nel trovare, se esiste, un cammino di certificazione che
permetta di verificare l’autenticità di un certificato elettronico di uno specifico
utente remoto, a partire da un insieme di chiavi pubbliche, assunte come radici
del cammino, delle quali si ha la diretta e sicura conoscenza.
La risoluzione del problema quindi assume per date certe condizioni
iniziali: tali condizioni iniziali si identificano nella conoscenza di chiavi di
specifiche autorità di certificazione già note, e che quindi già dispongono della
nostra fiducia.
La figura sottostante mostra un esempio di catena di certificazione,
costituita da tre certificati, in una ipotetica comunicazione tra Alice e Bob
appartenenti a due CA diverse.
54
Public Key Infrastructure
Figura 16. Esempio di catena di certificazione.
La presenza del certificato 1 garantisce Alice sull’autenticità della chiave
pubblica dell’autorità di certificazione B; Alice può quindi utilizzare la chiave
pubblica di B per verificare l’autenticità del certificato 2. La presenza del
certificato 2 garantisce ora Alice sull’autenticità della chiave pubblica
dell’autorità di certificazione C; ora Alice può utilizzare la chiave pubblica
dell’autorità di certificazione C per verificare l’autenticità del certificato 3 e quindi
della chiave pubblica di Bob. Se fosse venuto a mancare il certificato 2 Alice
non avrebbe potuto verificare l’autenticità del certificato elettronico di Bob e
conseguentemente avviare con Bob una comunicazione sicura.
Il cammino che si percorre all’interno di una catena di certificazione
riflette il modello strutturale che costituisce la PKI. L’esempio precedente è
riconducibile ad un modello reticolare in cui il certificato 1 ed il certificato 2
costituiscono due cross certificate che legano rispettivamente l’autorità di
certificazione A con B, e l’autorità di certificazione B con C.
In un modello ad albero si avrebbe uno schema molto simile, nel quale i
cross certificate legano le autorità di certificazione padre con le figlie. La
differenza risiede nel certificato all’apice della catena, che rappresenta l’autorità
di certificazione radice. Tale certificato infatti è autofirmato, in quanto la CA
55
Capitolo 3
radice garantisce per se stessa, quindi i campi “subject” e “issuer” del certificato
rappresentano la stessa entità.
Riportiamo di seguito l’esempio di un cammino di certificazione che si
potrebbe trovare in una infrastruttura che utilizza un modello ad albero.
L’autorità di certificazione A è la CA radice.
Figura 17. Esempio di catena di certificazione in una struttura ad albero.
56
Public Key Infrastructure
3.4
Standard
Questo paragrafo descrive brevemente gli standard in vigore che
disciplinano i certificati a chiave pubblica e le PKI. Questi standard riguardano
molti campi tra cui il formato con cui i dati devono essere contenuti in un
certificato, le regole di implementazione degli algoritmi crittografici, le regole di
utilizzo di hardware crittografici e altro ancora.
3.4.1 Standard X.509 per i certificati a chiave pubblica
Lo standard ormai diffusamente riconosciuto di definizione del formato
dei certificati è quello descritto nelle specifiche ITU X.50938, corrispondenti alle
specifiche ISO/IEC 9594-839.
Tale standard è giunto alla terza versione (X.509v3), dopo che le due
precedenti versioni si erano dimostrate insufficienti a risolvere certe
problematiche. Vediamo da quali campi è composto un certificato:
•
Version: indica la versione del formato del certificato.
•
Serial Number: è un codice numerico che identifica univocamente il
certificato.
•
Signature Algorithm: specifica l’algoritmo utilizzato dalla CA per firmare
il certificato.
•
Issuer X.500 Name: indica il nome della CA (secondo lo standard di
naming X.500).
•
Validity Period: specifica la data e l’ora di inizio validità e fine validità del
certificato.
•
Subject X.500 Name: nome del possessore del certificato.
•
Subject Public Key Information: contiene il valore della chiave pubblica
del possessore del certificato e l’algoritmo con cui tale chiave viene
usata.
38
International Telecommunication Unit.
International Standard Organization / International Electrotechnical Commission.
39
57
Capitolo 3
•
Issuer Unique Identifier: è una stringa di bit aggiuntivi, opzionale, usata
nel caso in cui nella struttura ad albero ci siano due CA.
•
Subject Unique Identifier: stringa opzionale di bit usata nel caso di
omonimia tra due membri di una stessa CA.
•
CA Signature: è la firma digitale della CA sul certificato.
Nella terza versione dello standard è stato aggiunto un ulteriore campo:
Standard Extention. Questo campo è suddiviso in tre sottoinsiemi:
l’identificatore del tipo di estensione, un indicatore di criticità e il valore effettivo
dell’estensione. L’indicatore di criticità facilita l’interoperabilità tra sistemi che
non utilizzano certificati con determinate estensioni e sistemi che, invece,
interpretano tutte le estensioni definite a livello di standard. Tale indicatore è
semplicemente un flag che indica se l’estensione è critica o non critica;
nell’ultimo caso il sistema che deve elaborare il certificato può eventualmente
ignorare l’estensione in questione se non è in grado di interpretarla.
Le estensioni standard definite nei certificati X.509v3 si dividono in
quattro gruppi:
•
Estensioni contenenti informazioni sulla chiave pubblica che specificano
il tipo di utilizzo per cui è stata emessa una certa chiave.
•
Estensioni contenenti informazioni aggiuntive relative alla CA e all’utente
possessore del certificato.
•
Estensioni contenenti informazioni sulle politiche di emissione e sulle
finalità di utilizzo dei certificati.
•
Estensioni contenenti informazioni sui vincoli di spazio di nomi o di
politica da imporre durante il ritrovamento o la verifica di un certificato
appartenente ad un dominio di fiducia esterno.
Vediamo di seguito un esempio di certificato X.509 v3.
58
Public Key Infrastructure
Figura 18. Esempio di certificato X.509v3.
Per avere un’idea di come si presenta nella pratica un certificato a chiave
pubblica conforme allo standard X.509 riportiamo di seguito l’esempio di un
certificato (autofirmato) rilasciato dall’Autorità di Certificazione della BNL (BNL
Multiservizi)40.
Version: V3
Subject: CN=Proxy Locale Multiservizi, OU=Certification Service Provider,
O=Multiservizi S.p.A., L=Roma, ST=rm, C=IT
Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
Key: SunJSSE RSA public key:
public exponent:
010001
modulus:
d5d04894 9b80aca4 1fb8228b cc319e8f 4dd956f3 a010e5f2 d42bbe13 2ad8ce46
a53c044c eb8e4073 ebe42ff5 04263dde 44ade1c9 5a4d19ac 31da9390 c2f50ccd
Validity: [From: Fri Feb 18 11:46:14 CET 2000,
To: Mon Feb 15 11:46:14 CET 2010]
Issuer: CN=Proxy Locale Multiservizi, OU=Certification Service Provider,
O=Multiservizi S.p.A., L=Roma, ST=rm, C=IT
SerialNumber: [
01]
Certificate Extensions: 1
[1]: ObjectId: 2.16.840.1.113730.1.13 Criticality=false
Extension unknown: DER encoded OCTET string =
0000: 04 25 16 23 45 6D 69 73
73 69 6F 6E 65 20 63 65
0010: 72 74 69 66 69 63 61 74
69 20 70 65 72 20 4D 4C
40
.%.#Emissione ce
rtificati per ML
Questo certificato è in dotazione con il software di installazione del lettore di Smart Card “GemPC410”
della Gemplus utilizzato nello sviluppo di questo lavoro.
59
Capitolo 3
0020: 53 20 50 72 6F 78 79
Algorithm: [SHA1withRSA]
Signature:
0000: 63 05 15 93 DE 7D 2B
0010: 2C 90 34 CB 29 0F 71
0020: 28 0A 28 71 C3 97 AB
0030: B3 F2 66 42 C5 06 E7
S Proxy
55
EE
BF
03
5B
C6
32
DB
C0
85
47
7F
77
08
DC
25
42
A0
B3
4E
2E
10
1E
0C
C4
7A
12
B2
95
E7
1B
16
D5
4A
47
E9
c.....+U[.wB....
,.4.).q......z.J
(.(q....2G.....G
..fB......%N....
3.4.2 Standard PKCS
PKCS è l’acronimo di Public Key Cryptography Standard e rappresenta
una famiglia di standard rilasciati dalla RSA Laboratories41, con lo scopo di
accelerare lo sviluppo e l’impiego delle tecniche di crittografia asimmetrica.
Pubblicati per la prima volta nel 1991, queste specifiche sono presto diventate
un punto di riferimento per il settore. Ogni specifica riguarda uno o più aspetti
legati al mondo della crittografia e della sicurezza. Questo standard si articola in
quindici normative che definiscono gli algoritmi di crittografia, la sintassi e le
interfacce per l’utilizzo di vari strumenti crittografici. Di seguito ne riportiamo una
breve descrizione42:
•
PKCS#1: RSA Cryptography Standard. Definisce le linee guida per
l’implementazione dell’algoritmo RSA sui calcolatori digitali.
•
PKCS#3: Diffie-Hellman Key Agreement Standard. Standard per
l’implementazione dell’algoritmo di key agreement Diffie-Hellman.
•
PKCS#5: Password-Based Criptography Standard. Raccomandazioni
per l’implementazione della cifratura basata su password.
•
PKCS#6: Extended-Certificate Sysntax Standard. Propone una
sintassi ASN.1 che estende quella dei certificati X.509.
•
PKCS#7: Cryptographic Message Syntax Standard. Sintassi generale
per i dati crittografati. Su questo formato si basa ad esempio il protocollo
di posta elettronica S/MIME e molti altri formati di interscambio per le
informazioni di identificazione personale.
41
42
www.rsasecurity.com/rsalabs/
Le specifiche PKCS#2 e PKCS#4 sono state incorporate nel PKCS#1.
60
Public Key Infrastructure
•
PKCS#8: Private-Key Information Syntax Standard. Sintassi ASN.1
per le informazioni relative ad una chiave privata, e descrizione della
sintassi per la chiavi private cifrate.
•
PKCS#9: Selected Attribute Types. Definisce i tipi ASN.1 degli attributi
usati in PKCS#6, PKCS#7, PKCS#8 e PKCS#10.
•
PKCS#10: Certification Request Syntax Standard. Descrive una
sintassi per la richiesta di firma di un certificato.
•
PKCS#11: Cryptographic Token Interface Standard. Specifica una
API (Cryptoki) per i dispositivi in grado di eseguire operazioni
crittografiche e trattare le informazioni relative (chiavi e certificati). È lo
standard de facto per l’interoperabilità tra i diversi modelli e tipi di HSM
(Hardware Security Module). Definisce un modello ad oggetti del token
indipendente dall’hardware sottostante e dalla piattaforma operativa.
•
PKCS#12: Personal Information Excange Syntax Standard. Specifica
un formato portabile per la memorizzazione o il trasporto di informazioni
personali, come chiavi private, certificati e altro. È il formato utilizzato nei
browser più comuni per l’importazione e l’esportazione di chiavi e
certificati (Netscape/Mozilla, Internet Explorer, Opera, Konqueror).
•
PKCS#13: Elliptic Curve Cryptografy Standard. Standard ancora in
fase di sviluppo, che specifica molti aspetti della crittografia basata sulla
teoria delle curve ellittiche.
•
PKCS#15: Cryptographic Token Information Format Standard.
Propone un modello generalizzato per l’accesso alle smart card e ai
token crittografici, al fine di favorire maggiormente l’interoperabilità tra
l’hardware dei diversi vendor.
61
Capitolo 3
62
Smart Card
Capitolo 4.
SMART CARD
63
Capitolo 4
4.1
Aspetto di una Smart Card
Le Smart Card sono schede del tutto simili, nella forma, a quelle che si
utilizzano per telefonare o per le operazioni bancarie (carte di credito). Sono
infatti delle tessere di plastica capaci di contenere dati al loro interno. La
caratteristica che distingue le Smart Card dalle altre schede però, sta nel fatto
che esse contengono un processore in grado di dotarle di una certa
“intelligenza” (da cui appunto il nome di “scheda intelligente”), che consente non
solo la semplice memorizzazione dei dati, ma anche la loro elaborazione.
Secondo lo standard ISO vengono definite “Integrated Circuit Card” (ICC,
ovvero “schede a circuito integrato”). La figura sottostante da un’idea di come
viene inserito il microchip all’interno della tessera.
Figura 19. Applicazione del chip sulla scheda.
In pratica questo processore consente di eseguire operazioni sui dati
direttamente all’interno della card. E’ questa una proprietà da non sottovalutare
in quanto fornisce un enorme contributo alla sicurezza. Infatti le operazioni che
si svolgono sulla scheda riguardano soprattutto dati sensibili (dati personali del
possessore della carta, certificati a chiave pubblica, chiavi private…) e più
questi rimangono legati alla scheda, maggiore è il livello di sicurezza.
Ma vediamo ora più in dettaglio come è fatta una Smart Card.
64
Smart Card
4.2
Architettura interna
Abbiamo già detto che una Smart Card possiede al suo interno un
processore, ma questo da solo non basta per eseguire le operazioni
menzionate. Ecco come è composta schematicamente una Smart Card:
Figura 20. Architettura interna di una Smart Card.
•
CPU: è il processore centrale, di tipo CISC a 8, 16 o 32 bit e con un
clock di 3,5 o 5 MHz;
•
ROM: è una memoria di sola lettura le cui dimensioni variano da 2 a 64
KByte e contiene il sistema operativo della scheda;
•
PROM: è una memoria molto piccola (32 o 64 Byte) che contiene il
numero seriale della scheda;
•
EEPROM: ha una capacità di circa 128 KByte e contiene informazioni
relative a dati e applicazioni (è la memoria di massa);
•
RAM: memoria di lavoro volatile, varia tra 128 e 1024 Byte;
•
Sottosistema I/O: è l’interfaccia per lo scambio dati con l’esterno.
65
Capitolo 4
Come si può vedere la struttura di una Smart Card è molto simile a
quella di un normale computer.
Alcune schede possono presentare delle variazioni allo schema descritto
(che è da ritenersi una struttura base di riferimento) a seconda delle funzioni cui
sono destinate. Un esempio che ci riguarda molto da vicino è dato proprio dalle
schede crittografiche. Gli algoritmi che queste devono eseguire sono molto
complessi quindi necessitano di un ulteriore processore chiamato appunto
coprocessore crittografico. Altri esempi si possono avere nel campo della
biometria in cui i dati relativi al riconoscimento dell’impronta digitale, o della
retina, o di qualunque altra caratteristica biometrica, sono molto ingombranti
quindi necessitano di una espansione di memoria realizzata ad esempio con
una banda ottica (che può arrivare a contenere diversi MByte).
4.3
Tipi di Smart Card
E’ opportuno a questo punto spendere qualche parola in più sui diversi
tipi di Smart Card. La prima distinzione che si può fare riguarda la presenza o
meno del microchip, abbiamo allora:
•
Schede di memorizzazione (memory card): non hanno al loro interno
un processore, ma solo un dispositivo di memorizzazione (ad es. banda
magnetica). Consentono la memorizzazione e il recupero dati.
Potrebbero contenere anche una logica di sicurezza per l’accesso ai dati
(autenticazione);
•
Schede con processore (ICC): contengono un microchip che consente
di memorizzare, recuperare e manipolare i dati. Alcune di esse
presentano anche un coprocessore di supporto per le operazioni più
complesse (schede crittografiche).
Un’altra classificazione delle Smart Card può essere fatta in base al loro
modo di comunicare con il mondo esterno, si hanno quindi:
•
Smart Card con contatti: si accede alla scheda per mezzo di contatti
posti sulla superficie della tessera;
66
Smart Card
•
Smart Card senza contatti: presentano un dispositivo capace di
trasmettere e ricevere onde elettromagnetiche utilizzate per scambiare i
dati.
4.4
Standard
Le Smart Card, anche se diverse nell’architettura, devono rispettare
alcuni standard riguardanti le loro caratteristiche fisiche, i protocolli di
comunicazione, i comandi etc. Due enti in particolare (International Standard
Organization43 e International Electrotechnical Commission44) si sono proposti
di sviluppare una serie di requisiti di riferimento per i produttori di Smart Card. I
produttori, dal lato loro, hanno tutto l’interesse a rispettare tali requisiti, in
quanto questo garantisce l’interoperabilità, cioè la possibilità di utilizzare schede
diverse su di uno stesso hardware (o software), e quindi facilita la diffusione
delle schede.
In questo paragrafo verranno illustrati alcuni standard, con particolare
attenzione allo standard ISO/IEC.
4.4.1 Standard ISO/IEC 7816
Tutte le caratteristiche fondamentali di una Smart Card sono esposte
nella normativa ISO/IEC 7816 che comprende le seguenti sezioni:
ISO/IEC 7816-1:
Physical characteristics;
ISO/IEC 7816-2:
Dimensions and location of the contacts;
ISO/IEC 7816-3:
Electronic signals and transmission protocols;
ISO/IEC 7816-4:
Inter-industry commands for interchange;
ISO/IEC 7816-5:
Numbering
system
and
application identifiers;
ISO/IEC 7816-6:
43
44
Inter-industry data elements;
www.iso.org.
www.iec.ch
67
registration
procedure
for
Capitolo 4
ISO/IEC 7816-7:
Inter-industry commands for Structured Card Query
Language;
ISO/IEC 7816-8:
Security related inter-industry commands;
ISO/IEC 7816-9:
Enhanced inter-industry commands;
ISO/IEC 7816-10:
Electronic signals answer to reset for synchronous card;
ISO/IEC 7816-11:
Card structure and enhanced functions for multi-application
use;
ISO/IEC 7816-15:
Cryptographic information application.
Questi standard sono in continua evoluzione a seguito dell’uscita di
nuove tecnologie o dell’impiego di particolari soluzioni nate come proprietarie
(dall’iniziativa di un produttore) e poi sviluppatesi fino a diventare di uso
comune.
Gli standard forniscono delle linee guida da seguire quando si ha a che
fare con le Smart Card. Tuttavia ogni produttore è consigliato a seguire tali
requisiti, ma non obbligato, per questo non è raro imbattersi in particolari
schede che implementano funzioni non inerenti agli standard descritti
(soprattutto nel campo della crittografia), ma che un produttore ha ritenuto
opportuno implementare come migliore soluzione per un determinato impiego.
E’ comunque il buon senso a suggerirci di trovare un compromesso tra rispetto
degli standard e libera iniziativa a soluzioni proprietarie. Si pensi a cosa
succederebbe se, ad esempio, ognuno producesse schede di differente forma e
con diversi protocolli di comunicazione! Si verrebbe a creare il caos più
assoluto!
Senza
dimenticarci
di
una
proprietà
fondamentale
come
l’interoperabilità che sarebbe completamente persa. Per questo è necessario
attenersi ad alcuni riferimenti comuni a tutti, e sono proprio quelli che troviamo
nelle prime tre sezioni dello standard ISO/IEC 7816. Di fatto, una scheda
dichiarata conforme al suddetto standard risulta conforme almeno alle prime tre
sezioni.
68
Smart Card
ISO/IEC 7816-1: Caratteristiche fisiche
Questo standard definisce le caratteristiche fisiche di una Smart Card, in
particolare:
•
le sue dimensioni:
Figura 21. Dimensioni di una Smart Card secondo lo standard ISO/IEC 7816-1.
•
il valore minimo di radiazione ultravioletta che la scheda deve
sopportare, stimato al livello medio di radiazione ambientale;
•
il valore minimo di esposizione ai raggi X che non provochi danni alla
scheda, stimato ad una energia media corrispondente alla quantità
cumulativa annuale;
•
il profilo della superficie dei contatti: la differenza tra il livello dei contatti e
quello della superficie della scheda deve essere minore di 0,1 mm;
•
la resistenza alle sollecitazioni meccaniche sia della scheda che dei
contatti: questi non devono essere danneggiati dalla pressione provocata
da una sfera di acciaio del diametro di 1,5 mm alla quale è applicata una
forza di 1,5 N;
•
la resistenza elettrica tra i contatti: non deve essere superiore a 0,5 Ω
per valori di corrente compresi tra 50 µA e 300 mA;
•
il valore minimo di campo magnetico statico che la scheda deve
sopportare;
69
Capitolo 4
•
la resistenza a scariche elettrostatiche: il chip non deve subire danni se
sottoposto ad una scarica elettrica di 1500 V provenienti da una capacità
di 100 pF attraverso una resistenza di 1500 Ω;
•
i limiti massimi di flessione della scheda: deve resistere ad una
deformazione di 2 cm dal lato lungo, o di 1 cm dal lato corto, con una
periodicità di 30 flessioni al minuto.
ISO/IEC 7816-2: Dimensione e locazione dei contatti
Questa sezione si occupa di definire le dimensioni fisiche, la locazione e
l’assegnamento dei contatti del chip sulla carta. In figura è riportato lo schema
dei contatti esterni del microcontroller previsti dallo standard, la loro
disposizione sulla tessera plastificata e la dimensione dei contatti stessi.
Figura 22. Posizione e dimensione dei contatti sulla Smart Card.
70
Smart Card
Figura 23. Assegnazione dei contatti.
•
VCC. Tensione continua di alimentazione, 3 o 5V;
•
RST. Linea di reset;
•
CLK. Segnale di clock del microcontroller. Lo spazio esiguo non
permette alle smart card di disporre di un’alimentazione interna, e il
segnale di clock deve essere fornito dall’interfaccia esterna (IFD:
Interface Device o CAD: Card Acceptance Device);
•
GND. Riferimento di massa per le tensioni applicate;
•
VPP. Alcune smart card hanno bisogno, in fase di programmazione, di
una tensione continua supplementare, fornita su questa linea.
•
I/O. Linea per l’input/output seriale.
I contatti C4 e C8 non sono collegati, e sono riservati ad usi futuri
(Reserved for Future Use).
ISO/IEC 7816-3: Segnali elettrici e protocolli di trasmissione
Questo standard descrive i segnali elettrici e i protocolli di trasmissione
utilizzati nelle Smart Card. In particolare vengono date indicazioni sui livelli delle
tensioni e correnti riguardanti tutti i segnali introdotti precedentemente, nonché
sui tempi di salita e discesa e sulle capacità parassite.
Di seguito sono riportate solo le specifiche su alcuni segnali, tra i quali quelli
fondamentali di alimentazione e clock, il reset che verrà discusso ulteriormente
71
Capitolo 4
più avanti, e l'I/O. Viene tralasciato Vpp il cui utilizzo è opzionale e interessa più
il programmatore della scheda che non l'utente finale.
Symbol
Conditions
Minimum
Maximum
Unit
Vih
Either (1)
Iih max = +/- 500uA
2
VCC
V
Iih max = +/- 50uA
0.7 VCC
VCC (3)
V
Vil
Iil max = 1mA
0
0.8
V
Voh
Either (2)
Iol max = +/- 100uA
2.4
VCC
V
Iol max = +/- 20uA
3.8
VCC
V
Vol
Iol max = 1mA
0
0.4
V
tr, tf
Cin = 30pF; Cout = 30pF
1
us
(1)
For
the
interface
device,
take
into
account
both
conditions.
(2) It is assumed that a pull up resistor is used in the interface device (recommended value
20k
Ohm.
(3) The voltage on I/O shall remain between 0.3V and VCC+0.3V.
Figura 24. Caratteristiche elettriche di I/O sotto normali condizioni operative.
Symbol
Conditions
Either (1)
Vih
Minimum
Maximum
Unit
IIih max = +/- 200uA
2.4
VCC (2)
V
Iih max = +/- 20uA
0.7*VCC
VCC (2)
V
Iih max = +/- 10uA
VCC-0.7
VCC (2)
V
0 (2)
0.5
V
Iol max = +/- 100uA
2.4
VCC
V
Iol max = +/- 20uA
3.8
VCC
V
Vil
Iil max = +/-200 uA
Voh
Either (2)
tr, tf
Cin = 30pF
9%
of
the
with a max:0.5us
(1)
For
the
interface
device,
take
into
account
(2) The voltage on CLK shall remain between 0.3V and Vcc+0.3V.
three
period
conditions.
Figura 25. Caratteristiche elettriche di CLK sotto normali condizioni operative.
Symbol
Conditions
Minimum
Maximum
Unit
Vih
Either (1)
IIih max = +/- 200uA
4
VCC (2)
V
Iih max = +/- 20uA
VCC-0.7
VCC (2)
V
Vil
Iil max = +/-200 uA
0 (2)
0.6
V
(1)
For
the
interface
device,
take
into
account
(2) The voltage on RST shall remain between 0.3V and VCC+0.3V.
both
conditions.
Figura 26. Caratteristiche elettriche di RST sotto normali condizioni operative.
72
Smart Card
Symbol
Minimum
Maximum
Unit
Vcc
4.75
5.25
V
200
mA
Icc
Figura 27. Caratteristiche elettriche di Vcc sotto normali condizioni operative.
Inoltre in questo standard sono definite anche le sequenze di attivazione
e il comportamento del microcontroller al segnale di reset.
Sono infine definiti due protocolli half-dupex asincroni di trasferimento dei
dati chiamati T=0 e T=1.
Questi ultimi concetti saranno ripresi ed analizzati più in dettaglio nel
paragrafo riguardante il funzionamento di una Smart Card.
4.4.2 Altri standard
Abbiamo visto come le prime tre sezioni dello standard ISO/IEC 7816
definiscano i requisiti che regolamentano le caratteristiche fisiche, i protocolli di
comunicazione e il funzionamento di basso livello della Smart Card.
Salendo di un livello troviamo il set di comandi di cui dispone la scheda.
Una sua definizione viene data nella parte quarta dello standard precedente,
tuttavia i comandi disponibili sono legati alle operazioni che la scheda è
destinata a compiere, quindi è possibile trovare diversi set di comandi per
diversi campi applicativi, ognuno comunque regolato da un opportuno standard.
Di seguito sono riportati gli standard principali relativi ai set di comandi:
•
ISO/IEC 7816-4. Fornisce indicazioni riguardanti:
o il contenuto dei messaggi (sia di comando che di risposta) inviati
dal lettore alla scheda e viceversa;
o la struttura dei file e dei dati interni alla scheda;
o i metodi di accesso a file e dati nella scheda;
o i metodi di secure messaging;
o i metodi di accesso agli algoritmi presenti nella scheda (senza
occuparsi di descrivere tali algoritmi).
73
Capitolo 4
•
EMV (Europay, Mastercard, Visa). È uno standard industriale che
definisce comandi specifici per le transazioni finanziarie. Non è uno
standard internazionale, ma costituisce comunque un riferimento per il
settore.
•
GSM 11.11. Costituisce lo standard per le applicazioni legate alla
telefonia mobile.
•
CEN EN 1546. Standard che definisce comandi specifici per applicazioni
di moneta elettronica (electronic purse).
4.4.3 Abstract Syntax Notation
L’Abstract Syntax Notation (ASN) è il metodo più usato per strutturare i
dati nelle smart card e trova particolare applicazione nelle schede crittografiche.
Rispetta gli standard internazionali ISO/IEC 8824 relativi alla sintassi e ISO/IEC
8825 per quanto riguarda le regole di codifica. Ambedue sono inerenti alle
raccomandazioni X.409 del CCITT.
La struttura dati ASN.1 è una struttura flessibile, cioè vengono specificati
di volta in volta il tipo di dato che si sta trasmettendo e la sua lunghezza. Gli
sviluppatori di questo standard hanno preferito evitare strutture fisse in quanto
potrebbero risultare incompatibili con eventuali sviluppi futuri comportando così
costi aggiuntivi di adattamento.
Di seguito è riportato un esempio di struttura dati che rispetta le Basic
Encoding Rules (BER) dello standard ASN.1 e nota con il nome di struttura
TLV.
TAG
LENGTH
VALUE
1 o 2 byte
da 1 a 3 byte
n byte
Figura 28. Struttura dati TLV dello standard ASN.1.
74
Smart Card
E’ composta da tre campi:
•
Tag: è un’etichetta che identifica il dato e ne specifica il tipo;
•
Length: specifica la lunghezza del dato. La codifica di questo campo è
definita nelle Distinguished Encoding Rules (DER) che sono un
sottoinsieme delle BER.
•
Value: rappresenta il dato vero e proprio.
Vediamo ora più in dettaglio il campo Tag.
I due bit più significativi selezionano un tipo (o classe) di dato presente nel
campo Value tra i quattro disponibili:
•
universal (00): rappresenta un dato generico;
•
application (01): specifica un dato che appartiene ad una applicazione o
ad uno standard;
•
context-specific (10);
•
private (11).
Le ultime due classi si riferiscono a dati di applicazioni non standardizzate.
Il bit successivo specifica se l’oggetto in questione è una primitiva o un
constructed (se è stato creato da altri oggetti).
I rimanenti bit (cinque se il campo tag fosse di un solo byte, più altri otto
se il campo fosse lungo due byte) codificano l’effettiva etichetta scelta
dall’utente per identificare il dato.
MSB
0
1
classe
2
3
4
constr.
5
6
7
LSB
etichetta
Figura 29. Significato dei bit costituenti il campo TAG.
Questo tipo di struttura ha il vantaggio di essere semplice, flessibile e
permette di scambiare qualsiasi tipo di dato. Per contro potrebbe comportare un
elevato costo di gestione nel caso in cui il campo Value fosse di pochi byte, in
quanto si avrebbero più byte impiegati per descrivere il dato (nei campi T e L)
rispetto a quelli costituenti il dato vero e proprio (campo V).
75
Capitolo 4
4.5
Funzionamento di una Smart Card
In questo paragrafo verranno ripresi i concetti, già citati nella descrizione
dello standard ISO/IEC 7816-3, relativi alle sequenze di attivazione e
disattivazione della scheda e ai protocolli di trasmissione che essa utilizza.
Inoltre verranno brevemente descritti anche il sistema operativo impiegato dalla
scheda e la struttura del file system per la gestione dei dati. Infine si
illustreranno anche i concetti base del protocollo APDU.
4.5.1 Sequenze di attivazione e disattivazione
Lo scambio dei dati tra smart card e interfacce esterne è regolato da una
procedura descritta dettagliatamente nella terza sezione della normativa
ISO/IEC 7816, nella quale il segnale applicato alla linea di reset (RST) gioca un
ruolo fondamentale.
La sequenza di attivazione è la seguente:
•
mantenere RST basso;
•
applicare Vcc;
•
mettere il contatto I/O in modalità ricezione;
•
applicare, se previsto, la tensione Vpp;
•
applicare un segnale di clock stabile (CLK).
La figura seguente mostra l’andamento temporale dei segnali appena
descritti.
76
Smart Card
GND
VCC
CLK
RST
ATR
I/O
t
Inserimento
smart card
Stabilizzazione
contatti
Figura 30. Sequenza di attivazione.
Con RST a livello basso, il microcontroller è nello stato di reset. Dopo un
certo numero di cicli di clock, RST viene portato a livello alto. La smart card
inizia la comunicazione in un intervallo di tempo compreso tra 400 e 40.000 cicli
di clock, inviando sulla linea seriale una trama chiamata ATR (Answer To
Reset), che include informazioni relative ai protocolli di trasmissione
supportatati, all’identificazione del tipo di smart card, dell’hardware on-board e
del sistema operativo, varie informazioni aggiuntive (historical characters) che
possono anche essere inserite dal produttore della carta e infine da un
checksum di controllo. Con l’ATR è possibile identificare univocamente il
modello di smart card con il quale l’IFD sta comunicando.
Se nell’ATR la card dichiara di supportare più di un protocollo di
comunicazione (ad esempio sia T=0 che T=1), l’IFD invia una trama detta PTS
request (Protocol Type Selection). Dopo la risposta della card (PTS
response) sarà selezionato uno tra i protocolli negoziabili, e inizierà la
comunicazione vera e propria.
77
Capitolo 4
La sequenza di disattivazione è la seguente:
•
abbassare il livello di RST;
•
abbassare CLK;
•
scollegare Vpp;
•
abbassare I/O;
•
disattivare l’alimentazione Vcc.
4.5.2 Sistema operativo
L’elaborazione dei comandi, la gestione del file system e molte altre
caratteristiche delle smart card dipendono dal particolare sistema operativo
cablato in ROM, che pilota le operazioni del microcontroller.
In un certo senso possiamo pensare ad una smart card come ad una
scatola nera alla quale inviamo dei comandi e dalla quale riceviamo delle
risposte.
Sebbene chiamare Sistema Operativo i pochi Kbyte cablati nelle ROM
delle smart card potrebbe sembrare fuorviante, per rendersi conto dell’ alto
grado di sviluppo al quale si è arrivati è sufficiente pensare al fatto che molti tra
i sistemi operativi per smart card permettono di incorporare interpreti per
linguaggi di alto livello come Basic o Java.
Lo sviluppo di un Sistema Operativo per una Smart Card è diverso da
quello che si avrebbe in un computer tradizionale, in quanto sono diverse le
condizioni ambientali (in cui il SO è inserito) e le condizioni di utilizzo.
In una smart card si ha a disposizione pochissima memoria (nell’ordine
dei Kbyte), non è presente alcuna interfaccia utente ed infine sono ottimizzate
per garantire la massima sicurezza dei programmi, durante la loro esecuzione,
e dei dati, durante il loro accesso o elaborazione. Queste condizioni sono molto
restrittive e rendono necessario lo sviluppo di un sistema specifico che, pur
avendo affinità di base con i normali sistemi operativi, deve per forza
differenziarsi da essi.
78
Smart Card
Le dimensioni di un sistema operativo per smart card dipendono dalle
caratteristiche e dalle funzioni della scheda. In generale si va dai 3 KB di
sistemi per singole applicazioni, ai 30 KB per smart card multiapplicazione.
I compiti principali che un sistema operativo per smart card deve
assolvere sono:
• trasferimento dei dati dalla smart card verso l’esterno e dall’esterno verso
la smart card;
• controllo dell’esecuzione dei comandi;
• gestione dei file;
• gestione ed esecuzione di algoritmi crittografici (per smart card
crittografiche).
4.5.3 File system
Molti dei comandi dello standard ISO/IEC 7816-4 sono rivolti alla
gestione del file system. Una smart card consente solo l’utilizzo di strutture
standardizzate di file. I dati sono organizzati secondo la gerarchia ad albero
illustrata nella figura seguente.
MF
DF
EF
…
…
…
…
…
…
Figura 31. Struttura gerarchica del file system di una smart card.
79
Capitolo 4
I file si dividono principalmente in due categorie:
•
Dedicated File (DF): è un contenitore di file (directory) che può avere al
suo interno degli EF o anche altri DF di livello inferiore. Il DF radice è
chiamato Master File (MF) e rappresenta la directory root del file
system. Non esistono limitazioni al livello di profondità dei DF (eccetto la
limitazione di spazio). Nelle schede multiapplicazione si tende a creare
una directory (e quindi un DF) per ogni applicazione.
•
Elementary File (EF): contengono i dati utili per le applicazioni. Si
dividono a loro volta in:
o Internal EF: contengono dati che utilizza il sistema operativo (ad
esempio dati del SO stesso, di una applicazione, chiavi segrete o
codice programma). L’accesso a questi file è protetto.
o Working EF: contengono dati utili per le applicazioni esterne, cioè
dati che sono destinati ad un utilizzo al di fuori della scheda.
La figura sottostante mostra una schematizzazione dei vari tipi di file.
File
Directory
Data
MF
EF
Internal EF
DF
Working EF
Figura 32. Tipi di file presenti in una smart card.
I dati all’interno degli EF possono essere organizzati secondo una di
queste quattro strutture predefinite:
80
Smart Card
• Transparent. Ci si riferisce con questo termine ad una sequenza binaria
non strutturata, alla quale si può accedere in lettura o scrittura per singoli
byte o per blocchi;
• Linear Fixed. I dati sono organizzati in record di lunghezza fissa: ogni
file può contenerne al massimo 254. Questa struttura permette
operazioni di lettura/scrittura di un numero intero di record. La lunghezza
di ogni record può essere al massimo di 254 byte;
• Linear Variable. Come per la struttura linear fixed, l’unità minima di
lettura/scrittura è il record, fino ad un massimo di 254 per ogni file. La
dimensione dei record è variabile (da un minimo di un byte fino ad un
massimo di 254 byte), e ogni record ha un campo supplementare che ne
indica la lunghezza. La tipica applicazione di una struttura simile è una
rubrica telefonica, nella quale i nomi e i numeri di telefono non hanno
lunghezza fissa: usare allo stesso scopo una struttura linear fixed è
possibile, ma non efficiente in termini di gestione dello spazio in
memoria;
• Cyclic. È basata sulla struttura linear fixed (dimensione massima di un
record 254 byte), ma ha in più un puntatore che indica l’ultimo record che
è stato scritto. Raggiunto l’ultimo record, il puntatore indirizzerà i
successivi accessi al primo record della struttura (lista ciclica). Anche in
questa struttura il massimo numero di record memorizzabile è 254.
Ognuno dei file appena introdotti, oltre a contenere i dati, deve anche
fornire alcune informazioni sul suo formato. Tutte le informazioni riguardanti il
file sono contenute sul file stesso attraverso una struttura di questo tipo:
Header
Body
Figura 33. Struttura interna di un file.
81
File
Capitolo 4
Un file è costituito da una intestazione (header) che contiene
informazioni sulla struttura del file e sulle condizioni di accesso. Questa punta al
corpo del file (body) che contiene i dati veri e propri.
Per motivi di sicurezza solo il sistema operativo può accedere
all’intestazione del file, mentre all’utente (o a qualsiasi applicazione esterna)
sarà proposto solo il corpo del file. Per questo l’header e il body sono contenuti
in due pagine diverse della memoria, in quanto, in caso contrario, si potrebbero
sfruttare dei trucchi per accedere all’header e cambiare le condizioni di accesso
al file.
Ogni file, infine, può essere selezionato usando un opportuno
identificatore (FID: File Identifier), cioè un campo di due byte che contiene il
nome del file (in esadecimale45). L’utilizzo di alcuni di questi identificatori è
riservato, come ad esempio FID “3F00” che è associato al master file, oppure
FID “FFFF” riservato ad applicazioni future.
Analogamente esiste anche un identificatore per le applicazioni chiamato
Application Identifier (AID).
4.5.4 Protocolli di trasmissione
Attualmente le smart card utilizzano due protocolli di trasmissione
denominati T=0 e T=1. Sono due protocolli per comunicazioni seriali asincrone
di tipo half duplex. Per il futuro sono previsti anche altri tipi di protocolli, come
ad esempio il T=2 che sarà in grado di gestire comunicazioni full duplex, ma
sono ancora in fase di sviluppo.
Protocollo T=0
Il protocollo T=0 è forse il più comune, anche perché largamente
impiegato nello standard GSM. Si tratta di un protocollo di comunicazione byteoriented, nel quale ogni unità di trasmissione è preceduta da un bit di start a
45
La smart card impiega un modo di indirizzamento codificato in esadecimale in quanto, non esistendo
alcuna interfaccia utente, tali indirizzi devono essere compresi solo dai programmi.
82
Smart Card
livello basso e seguito da un bit di parità e da un livello alto della durata di due
bit (guard time) che segnala la fine della trasmissione.
start bit n
data byte n
parity bit n
start bit n+1
guard time
Figura 34. Esempio di un byte dati e bit di controllo del protocollo T=0.
T=0 adotta un modello di comunicazione master-slave, nel quale il
segnale di comando è sempre generato dall’IFD (master) e il segnale di
risposta dalla smart card (slave).
I dati scambiati tra IFD e smart card sono organizzati in trame chiamate
TPDU (Transmission Protocol Data Unit). La trama di comando inviata
dall’IFD alla smart card ha sempre la seguente struttura.
CLA
INS
P1
P2
P3
Figura 35. Trama di comando T=0.
Nella trama di comando distinguiamo i seguenti campi:
•
CLA. Classe dell’istruzione.
•
INS. Codice dell’istruzione.
•
P1, P2. Parametri dell’istruzione.
•
P3. Lunghezza dell’eventuale blocco di dati seguente.
Dopo ogni comando il protocollo prevede l’invio da parte della smart
card, di un codice di risposta (ACK). A seconda del tipo di istruzione
selezionata dalla trama di comando, ad ACK segue la trasmissione dei dati da o
83
Capitolo 4
per la smart card. Se viene rilevato un errore di parità su un byte del blocco
trasmesso, il ricevente (IFD o smart card) abbassa il livello della linea I/O prima
che termini il guard time, forzando la ripetizione della trasmissione dell’intera
trama. La comunicazione termina con due byte di stato inviati dalla smart card
all’IFD (SW1 e SW2), che contengono gli eventuali codici di errore. Il valore
0x9000 segnala il successo dell’operazione.
Il controllo di parità può rilevare solo errori sul singolo bit; inoltre, se
durante il trasferimento dall’IFD alla card di una sequenza di lunghezza P3,
viene perso un byte, si incorre nello stallo (deadlock) della card, che si può
sbloccare solo riattivando la linea RST. La probabilità che si verifichino errori di
questo tipo è comunque molto bassa.
T=0 si colloca tra il primo (livello fisico) e il secondo (data link) livello
dello stack ISO/OSI, poiché interviene sia sull’elaborazione del singolo byte
(introducendo i bit di parità), che nella definizione dell’intera trama. La mancata
separazione dei layer rende T=0 poco adatto al trattamento di dati cifrati, per i
quali è preferibile che i blocchi trasmessi siano trattati direttamente dai livelli
sorgente e destinazione, lasciando ai layer intermedi il solo compito di inserire
le intestazioni che gli competono.
T=0 garantisce un buon transfer rate medio46, e la larga diffusione sul
mercato, unita alla semplicità della realizzazione, lo rendono una soluzione
ancora molto praticata, sebbene in rapida obsolescenza.
Protocollo T=1
T=1 è un protocollo block-oriented più complesso e articolato di T=0,
classificabile al livello data-link dello stack ISO/OSI. La differenza fondamentale
con T=0 è che l’unità minima di trasmissione è una sequenza di byte di
lunghezza variabile (block o frame). T=1 si appoggia su un protocollo del livello
fisico simile a T=0, ma senza controllo di parità. Il controllo degli errori viene
effettuato sull’intero blocco dei dati scambiati tra smart card e IFD, realizzando
in questo modo la separazione dei layer e rendendo T=1 più adatto per il
trasporto di dati cifrati.
46
Il valore del transfer rate dipende dalla frequenza di clock del microcontroller e da altri parametri in
gioco.
84
Smart Card
La comunicazione inizia dopo la ricezione dell’ATR da parte dell’IFD,
oppure dopo un eventuale PTS andato a buon fine.
La struttura di un blocco è illustrata qui sotto.
Information field
Epilogue field
node address
NAD
protocol control byte
PCB
Prologue field
length
LEN
APDU
EDC
1 byte
1 byte
1 byte
0... 254 byte
1... 2 byte
Figura 36. Struttura di un blocco T=1.
Il campo NAD permette di controllare la tensione Vpp (2 bit) e di
codificare indirizzi logici di sorgente e destinazione dei dati (ognuno su 3 bit).
PCB codifica varie informazioni sulla gestione del protocollo.
LEN codifica la lunghezza in byte del campo successivo. Il valore 0xFF
per questo campo è riservato per future estensioni.
Il campo APDU (Application Protocol Data Unit) contiene i dati da o per il
livello applicativo.
EDC (Error Detection Code) contiene un codice di correzione degli errori
calcolato sui campi precedenti, selezionabile via ATR tra un codice di
ridondanza ciclica (CRC) o longitudinale (LRC).
A parità di condizioni generali (frequenza di clock e altri parametri)
l’analisi delle prestazioni indica che i transfer rate ottenibili con T=0 e con T=1
sono molto simili. T=1 dispone di un meccanismo di rilevazione e correzione
degli errori più affidabile e, come abbiamo visto, realizza una separazione tra i
livelli preferibile in determinate circostanze (secure messaging). Dall’altro lato,
T=1 richiede una programmazione più complessa e un buffer sulla scheda di
dimensioni in media quattro volte maggiori rispetto al buffer sufficiente per T=0
(300 byte contro 1100).
85
Capitolo 4
4.5.5 Application Protocol Data Unit
Le strutture dati APDU (Application Protocol Data Unit) definite nello
standard ISO/IEC 7816-4 contengono sia i comandi provenienti dal livello
applicativo e destinati alla smart card, sia le risposte che quest’ultima restituisce
ai livelli superiori dopo aver elaborato i dati in ingresso. Le APDU sono quindi
distinte in due classi: command APDU e response APDU.
La struttura più generale di un APDU di comando è la seguente.
CLA
INS
P1
P2
Lc
header
Data
Le
body
Figura 37. APDU di comando.
I primi quattro campi sono lunghi ciascuno un byte e costituiscono
l’intestazione (header); i restanti tre (body) sono opzionali e di lunghezza
variabile.
CLA identifica lo specifico set di comandi che si sta usando: ad esempio
un valore 0xA0 per CLA identifica il set di comandi dello standard GSM 11.11.
Ai comandi ISO è assegnato il range 0x0X (dove X è una qualsiasi cifra
esadecimale), mentre i valori di CLA appartenenti al range 0x8X e 0x9X sono
riservati per i comandi proprietari definiti dal costruttore della card.
INS contiene la codifica dell’istruzione. Per motivi di compatibilità con i
protocolli di trasferimento dati sottostanti (T=0 e T=1) sono vietate le
configurazioni con INS pari, e i range 0x6X e 0x9X.
I byte seguenti dell’intestazione (P1 e P2) possono assumere qualsiasi
valore, e vengono usati per fornire maggiori informazioni sull’istruzione
codificata in INS (sono i parametri del comando).
Il corpo dell’istruzione può mancare del tutto o essere presente solo
parzialmente, dando luogo a quattro possibili configurazioni significative per un
APDU di comando.
86
Smart Card
a)
header
b)
header
Le
c)
header
Lc
data
d)
header
Lc
data
Le
Figura 38. Possibili configurazioni di una APDU di comando.
I campi Lc e Le hanno lunghezza variabile da uno a tre byte, e
codificano rispettivamente la lunghezza in byte del successivo campo dati, e il
numero di byte che ci si aspetta in risposta dalla smart card. Il campo data
contiene gli eventuali dati che la card dovrà processare.
La struttura dell’APDU di risposta è la seguente.
Data
SW1
SW2
Figura 39. APDU di risposta.
Il campo Data è opzionale, con lunghezza pari al valore del campo Le
del comando che ha richiesto la risposta, e naturalmente contiene il risultato
dell’elaborazione della smart card. I due campi SW1 e SW2 sono obbligatori e
contengono i codici di stato (Status Word) della smart card. Valori pari a
0x61XX o 0x9000 identificano l’assenza di errori o di condizioni anomale,
mentre altri valori, così come specificato nello standard, si riferiscono ad errori o
situazioni eccezionali.
Come si può notare, la struttura descritta è molto simile a quella definita
nel protocollo di trasferimento T=0: la corrispondenza con i TPDU è definita
caso per caso nella normativa. Ad esempio, per una command APDU con il
solo header il campo P3 del TPDU è impostato a 0x00.
Nel caso del protocollo T=1, le APDU vengono mappate nel campo
information senza alcun cambiamento.
87
Capitolo 4
La figura seguente mostra l’integrazione tra i protocolli di trasmissione
descritti nel paragrafo precedente e i comandi del livello applicativo: nel blocco
Card si può identificare il sottosistema di I/O, e in APDU Processor il sistema
operativo/CPU.
Application
Command
Funzioni
specifiche
della card
Response
Command
Reader
(T=0 / T=1)
Command
Card
Response
Response
APDU
Processor
Figura 40. Schema di una comunicazione tra una applicazione e la smart card.
4.6
Interfaccia con le applicazioni
Abbiamo visto in che modo una smart card comunica con il proprio
lettore, attraverso i protocolli T=0 o T=1, e con le applicazioni, attraverso le
APDU di comando e di risposta.
In questo paragrafo andremo a descrivere più in dettaglio la struttura
dell’interfaccia tra la smart card e le applicazioni che richiedono i suoi servizi.
Verranno illustrate e discusse tre principali architetture: PC/SC, Open Card
Framework e Java Card.
88
Smart Card
4.6.1 PC/SC
Il progetto PC/SC è centralizzato sull’interoperabilità tra smart card e
card terminal e la cooperazione tra card terminal e personal computer.
Si struttura in otto parti che ricoprono tutte le specifiche: dalle
caratteristiche fisiche della smart card e del suo lettore fino al livello
applicazione.
Figura 41. Architettura PC/SC.
89
Capitolo 4
Part 1.
Fornisce una descrizione introduttiva dell’architettura PC/SC.
Part 2.
Specifica le caratteristiche fisiche della scheda (ICC) e del lettore
(IFD) e da indicazioni sulle regole di gestione degli errori.
Part 3.
Specifica le caratteristiche dell’interfaccia tra lettore e PC in modo da
rendere il sistema indipendente dal dispositivo fisico. La parte 3 e la
parte 2 (quindi l’IFD e l’IFD Handler) costituiscono quello che viene
chiamato Interface Device Subsystem.
Part 4.
Descrive le linee guida per lo sviluppo di protocolli interni relativi
all’interfaccia descritta nella parte 3.
Part 5.
Definisce
il
componente
base
dell’architettura
PC/SC:
l’ICC
Resource Manager. Esso si occupa di gestire le richieste provenienti
dalle applicazioni e smistarle ai diversi lettori di schede, nonché
regolare gli accessi multipli ad una stessa risorsa.
Part 6.
Specifica le due interfacce primarie usate dall’applicazione:
• ICC Service Provider: contiene una classe che mantiene il
contesto della comunicazione con la smart card (necessaria nel
caso di accessi multipli). In più può anche fornire primitive per
l’accesso ai file della scheda o per le operazioni di autenticazione.
• Crypto Service Provider: specifica le primitive per le operazioni
crittografiche quali generazione e gestione delle chiavi, firma
digitale, funzioni di hash e altre ancora.
Part 7.
Contiene consigli per il programmatore sull’utilizzo di questa
interfaccia.
Part 8.
Contiene consigli su come gestire l’identificazione, l’autenticazione e
la memorizzazione sicura dei dati.
4.6.2 Open Card Framework
Lo scopo che gli sviluppatori di OCF hanno voluto raggiungere è quello di
realizzare un’interfaccia di alto livello tra la smart card e le applicazioni il più
possibile universale in termini sia di tipologie di schede adottabili, sia di diversi
tipi di computer o sistemi operativi. Tale progetto è stato sviluppato con
tecnologia Java sfruttando i vantaggi di una struttura orientata agli oggetti.
90
Smart Card
L’Open Card Framework è strutturato in questo modo:
Figura 42. Architettura OCF.
Nel livello più alto c’è l’applicazione (application developer) che vuole
comunicare con la smart card.
Il Card Issuer è responsabile dell’application management layer che si
occupa di eseguire e far coesistere più applicazioni in una stessa card.
Può accadere che un’applicazione richieda una funzione specifica di una
determinata smart card (ad esempio una funzione crittografica), in questo caso,
se si dispone di una JavaCard la funzione viene eseguita come applet
all’interno della card stessa, altrimenti la funzione deve essere fornita
dall’interfaccia OCF tramite il Card Service. Esso contiene tutte le informazioni
riguardanti il sistema operativo e le funzioni supportate dalla scheda.
Nel livello più basso troviamo il Card Terminal che interfaccia
direttamente con l’hardware (è una classe che astrae il lettore della scheda).
L’Open
Card
Framework
Core
contiene
cinque
oggetti:
CardServiceScheduler, SmartCard (che non è il dispositivo fisico ma una sua
91
Capitolo 4
astrazione),
CardID
e
i
due
registri:
CardServiceRegistry
e
CardTerminalRegistry.
Quando viene inserita una smart card nel lettore per prima cosa vengono
creati gli oggetti SmartCard e CardID che identificano il tipo di scheda.
Il CardServiceFactory contiene le informazioni riguardanti i servizi offerti
da una smart card. Quando un’applicazione richiede un certo servizio ad una
determinata scheda il CardServiceRegistry chiama tutti i CardServiceFactory
relativi al CardID dell’oggetto SmartCard finché non viene creato un appropriato
oggetto CardService.
In modo analogo, quando si inserisce la smart card (e dopo l’avvenuta
identificazione), il CardTerminalRegistry chiama tutti i CardTerminalFactory
relativi al CardID dell’oggetto SmartCard finché non viene creato l’oggetto
CardTerminal opportuno.
Per fare in modo che OCF funzioni con diverse smart card, ognuna di
esse deve disporre del relativo CardTerminal.
4.6.3 Confronto tra OCF e PC/SC
La prima differenza sta nella struttura architetturale delle due soluzioni.
OCF segue maggiormente una filosofia ad oggetti accentrata principalmente sui
servizi offerti dalla smart card, PC/SC invece è meno orientato agli oggetti e
tiene più in considerazione i dispositivi fisici che sono appunto personal
computer e smart card. Un immediato riscontro di questo diverso approccio lo si
può trovare analizzando il CardTerminal di OCF che non fornisce specifiche sul
suo funzionamento di basso livello, cosa che invece avviene (e in modo molto
dettagliato) sia nell’IFD che nell’IFD Handler di PC/SC.
Una differenza più forte si evidenzia nell’ambito delle applicazioni
crittografiche. PC/SC presenta un componente dedicato a questo tipo di
funzioni: il Crypto Service Provider, cosa che invece viene a mancare nell’altra
struttura. Per questo si può dire che PC/SC è più orientato verso la crittografia
rispetto ad OCF.
Le due soluzioni comunque hanno anche molte cose in comune, come è
facile aspettarsi da due progetti che, nonostante seguano strade diverse, si
92
Smart Card
pongono lo stesso obiettivo. Ci sono infatti alcuni componenti che offrono
funzionalità simili (e a volte equivalenti). E’ il caso dell’”ICC Service Provider” di
PC/SC e del “CardService” di OCF; oppure l’”Interface Device Subsystem” di
PC/SC e il “CardTerminal” di OCF.
In definitiva, sia OCF che PC/SC offrono, in un modo o nell’altro, una
valida interfaccia che garantisce tutti i servizi offerti dalla scheda e richiesti dalle
applicazioni.
Forse la differenza più importante riguarda il loro campo di utilizzo. OCF
infatti, essendo strutturato ad oggetti e sviluppato in Java, può essere utilizzato
in modo indipendente dal sistema operativo che il personal computer supporta,
mentre PC/SC è strettamente legato a Microsoft Windows. Dall’altra parte
PC/SC è in grado di interfacciarsi con qualsiasi linguaggio di programmazione,
mentre OCF è ristretto al campo delle applicazioni Java.
4.6.4 Java Card
Una Java Card è un particolare tipo si smart card che consente l’utilizzo,
all’interno della scheda stessa, del linguaggio di programmazione Java, così da
poterne sfruttare le caratteristiche di sicurezza, robustezza e compatibilità con
vari sistemi operativi.
La Java Card contiene una versione rivista della Java Virtual Machine
chiamata Java Card Virtual Machine (JCVM) che interagisce col sistema
operativo della smart card. Questa, in pratica, implementa tutte le funzioni che
la smart card deve offrire e le rende disponibili sottoforma di applet. La JCVM in
realtà contiene un sottoinsieme di tutte le classi costituenti il linguaggio Java a
causa delle forti limitazioni di spazio e potenza di calcolo presenti in una smart
card.
L’insieme delle classi caricate nella Java Card costituisce l’interfaccia
(API) con le funzioni della scheda ed è chiamata Java Card Framework.
Questa è composta da quattro package:
•
javacard.framework: è il package più importante e fornisce la struttura
base del linguaggio Java. Deve essere in ogni Java Card;
•
javacardx.framework: contiene le classi per la gestione dei file;
93
Capitolo 4
•
javacardx.crypto: implementa le funzioni crittografiche;
•
javacardx.cryptoEnc: fornisce i metodi di cifratura.
Il primo è essenziale ed è installato su tutte le Java Card, mentre gli altri
tre sono delle estensioni (opzionali) che vengono installate appositamente dal
costruttore.
Sul secondo package è bene fare una precisazione: in effetti una Java
Card non include un file system vero e proprio, ma la gestione dei file è affidata
ad apposite applet (contenute appunto in questo pacchetto). Queste applet
ovviamente rispettano lo standard ISO/IEC 7816-4 riguardante la sintassi e la
struttura dei file.
Meritano una nota particolare i due ultimi pacchetti. La poca memoria
disponibile in una smart card rende impossibile (o comunque molto lenta)
l’esecuzione di algoritmi crittografici complessi programmati in Java, per questo
nei due package sono contenute classi che riportano gli algoritmi in codice
macchina nativo in modo da velocizzarne l’esecuzione. Non è stato possibile
unificare tutte le funzioni crittografiche in un solo pacchetto a causa di alcune
restrizioni legislative. Queste riguardano l’esportazione e l’utilizzo di funzioni
crittografiche. L’uso della crittografia infatti non è consentito liberamente, ma è
soggetto a leggi locali diverse da paese a paese. In particolare se si intende
usare algoritmi crittografici per le sole operazioni di decifratura è sufficiente
servirsi del pacchetto “javacardx.crypto”, mentre se si hanno anche esigenze di
cifratura allora occorre implementare il pacchetto “javacardx.cryptoEnc”.
In definitiva tutte le funzioni della Java Card vengono eseguite come
applet all’interno della JCVM. Vediamo ora più in dettaglio l’iter da seguire per
lo sviluppo e l’esecuzione di una applicazione destinata ad una Java Card.
94
Smart Card
Figura 43. Processo di sviluppo di una applicazione per Java Card.
Il procedimento è del tutto simile a quello impiegato per realizzare un
qualsiasi software Java per computer: si parte dal codice sorgente e si compila
per ottenere il bytecode.
La differenza sta proprio nella Virtual Machine. La JCVM infatti è
composta di due parti:
•
una Off-card VM che riceve il bytecode e vi esegue le varie operazioni di
verifica (riguardanti il formato, la sintassi e, se presente, la firma). Questa
inoltre crea un file CAP (Card Application File) da inviare all’altra parte
della VM;
•
una On-card VM che riceve il file CAP e ne testa e interpreta il bytecode
generando le istruzioni macchina per il processore della smart card.
Una soluzione di questo tipo porta tutti i vantaggi che sono caratteristici
del linguaggio Java, in particolare la robustezza, la sicurezza e l’indipendenza
dall’hardware in uso.
Con questa struttura è inoltre possibile eseguire più applet su una stessa Java
Card garantendo comunque la loro indipendenza (attraverso un controller di
accesso) e la sicurezza dei dati.
Il problema più grande invece riguarda l’impiego di risorse. Nelle smart
card la memoria disponibile è poca e va preziosamente custodita. Per una
95
Capitolo 4
stessa funzione l’impiego di una Java Card richiede maggiori risorse rispetto ad
una smart card tradizionale. Questo si fa sentire maggiormente in applicazioni
crittografiche, dove le esigenze di calcolo sono più elevate.
Da quanto detto si può concludere che l’utilizzo di una Java Card può
risultare vantaggioso fin quando si eseguono applicazioni “semplici” come ad
esempio la gestione dei file (in pratica quando si utilizzano smart card per fini
che esulano dalla crittografia, come ad esempio operazioni bancarie o
telefoniche). Quando invece si entra nell’ambito crittografico si deve
raggiungere un compromesso tra una maggiore sicurezza e indipendenza
dall’hardware ed una minore capacità prestazionale dovuta appunto ad un
impiego più massiccio di risorse.
4.7
PKCS#11
Abbiamo già introdotto (nel capitolo relativo alle infrastrutture a chiave
pubblica) la famiglia di standard PKCS47 che regolamentano le condizioni di
impiego di algoritmi crittografici asimmetrici. Analizzeremo ora in dettaglio una
particolare sezione dello standard, denominata “PKCS#11: Cryptographic
Token Interface Standard”.
Questo standard specifica un’interfaccia per la programmazione di
applicazioni (API), detta Cryptoki (Cryptographic Token Interface), per tutti
quegli strumenti che contengono informazioni, o sono in grado di implementare
funzioni, di tipo crittografico. Cryptoki segue un approccio basato sulla
programmazione
ad
oggetti
cercando
di
raggiungere
l’obiettivo
dell’indipendenza tecnologica e della condivisione di risorse presentando alle
applicazioni una visione comune e di tipo logico del dispositivo crittografico che
viene denominato cryptographic token.
Lo standard specifica i tipi di dato e le funzioni disponibili per
un’applicazione che richiede servizi crittografici. Cryptoki isola un’applicazione
dai dettagli del dispositivo crittografico. L’applicazione non deve cambiare se
vuole interfacciarsi con un nuovo tipo di periferica o se vuole girare sotto un
47
Vedi paragrafo § 3.4.2 “Standard PKCS”.
96
Smart Card
altro ambiente, in altre parole l’applicazione diventa portabile e si garantisce la
proprietà di interoperabilità.
E’ importante precisare che non è necessario che tutti i dispositivi
crittografici siano in grado di eseguire la totalità delle funzioni offerte
dall’interfaccia. Il compito di cryptoki è quello di rendere disponibile un modo
logico di programmare i dispositivi, di qualunque tipo essi siano. Per cui ognuno
di essi, nella realtà, implementerà un sottoinsieme delle funzioni offerte da
cryptoki.
PKCS#11 non specifica i dettagli di programmazione, ma si limita a
fornire una descrizione precisa dei tipi di dato e delle funzioni che possono
essere utilizzati da uno sviluppatore di software per scrivere la propria
applicazione.
4.7.1 Caratteristiche tecnologiche
Il modello generale di cryptoki è illustrato nella seguente figura.
Figura 44. Modello generale Cryptoki.
97
Capitolo 4
Il modello illustra i vari stadi di una comunicazione tra una o più
applicazioni che richiedono operazioni crittografiche e uno o più dispositivi in
grado di eseguire tali operazioni. L’applicazione non comunica direttamente con
il dispositivo fisico, ma, tramite l’interfaccia cryptoki, accede ad un oggetto che
rappresenta la sua astrazione logica: il Token. In particolare si possono
evidenziare due oggetti: il Token, che astrae il dispositivo fisico in grado di
svolgere operazioni crittografiche (ad esempio la smart card); e lo Slot, che
astrae il dispositivo fisico di lettura. Questo modello rende tutti i dispositivi
crittografici logicamente uguali, in modo che l’applicazione non debba
interfacciarsi direttamente ai driver della periferica e ciò rende possibile
l’interoperabilità.
Cryptoki permette inoltre ad una o più applicazioni di accedere ad uno o
più token. E’ capace infatti di gestire il funzionamento multisessione attraverso il
blocco “Device Contention/Synchronization” che smista le richieste delle
applicazioni ai rispettivi token.
Cryptoki viene implementato tramite una libreria scritta in ANSI48 C alla
quale l’applicazione si può collegare in modo diretto o dinamico.
4.7.2 Sessioni
Cryptoki richiede che un’applicazione apra una o più sessioni con un
token per guadagnare l’accesso agli oggetti ed alle funzioni del token stesso.
Una sessione fornisce una connessione logica tra l’applicazione e il
token, e può essere di due tipi: R/W (Read/Write) oppure R/O (Read/Only). Le
denominazioni R/W e R/O si riferiscono agli oggetti del token, non a quelli della
sessione. In entrambi i tipi di sessione, infatti, un’applicazione può creare,
leggere, scrivere e distruggere oggetti sessione e leggere oggetti token. Solo in
una sessione R/W è però consentito creare, modificare o distruggere oggetti
token.
48
American National Standard for Programming Language.
98
Smart Card
Una volta aperta la sessione l’applicazione ha accesso a tutti gli oggetti
pubblici del token, per accedere a quelli privati è necessario autenticarsi tramite
una procedura di login (nella quale bisogna fornire il PIN del token).
Quando una sessione viene chiusa tutti gli oggetti creati al suo interno
vengono distrutti, questo vale anche per oggetti che sono in uso da parte di
altre sessioni. Cryptoki infatti supporta le operazioni multissessione, ma un
particolare token permette solo un certo numero di sessioni aperte per ogni
applicazione.
Sessioni R/O
Una sessione di sola lettura è costituita da due diversi stati.
Figura 45. Stati di una sessione R/O.
Quando la sessione viene aperta può trovarsi nello stato R/O Public
Session se non è stata eseguita alcuna autenticazione, o nello stato R/O User
Functions se l’utente è stato autenticato. Nel primo caso l’applicazione ha
accesso in sola lettura agli oggetti token pubblici e in lettura e scrittura agli
oggetti sessione pubblici. Nel secondo caso l’applicazione ha accesso in sola
lettura a tutti gli oggetti del token (pubblici e privati) e in lettura e scrittura a tutti
gli oggetti sessione (pubblici e privati).
99
Capitolo 4
Sessioni R/W
Una sessione di lettura e scrittura è costituita da tre stati.
Figura 46. Stati di una sessione R/W.
Quando la sessione è aperta si può trovare nello stato R/W Public
Session se non sono state eseguite autenticazioni, nello stato R/W User
Functions se è stata eseguita una autenticazione, nello stato R/W SO
Functions se è stato autenticato un utente di tipo SO (Security Officer: ha il
compito di inizializzare il token impostando il PIN o manipolando alcuni oggetti
pubblici). Nel primo caso l’applicazione ha accesso in lettura e scrittura a tutti gli
oggetti pubblici. Nel secondo caso l’applicazione ha accesso in lettura e
scrittura a tutti gli oggetti. Nell’ultimo caso l’applicazione ha accesso in lettura e
scrittura ai soli oggetti pubblici del token.
Eventi di sessione
A seguito di particolari operazioni una sessione può cambiare il suo
attuale stato. Gli eventi responsabili del cambiamento di stato di una sessione
sono:
100
Smart Card
•
Log In SO: il Security Officer è stato autenticato dal token.
•
Log In User: il normal user è stato autenticato dal token.
•
Log Out: l’applicazione disconnette l’utente corrente (che sia SO o
normal user).
•
Colse Session: l’applicazione chiude la sessione corrente o tutte le
sessioni da lei aperte.
•
Device Removed: il token viene rimosso dal dispositivo di lettura.
In Cryptoki tutte le sessioni che un’applicazione ha con un token devono
avere lo stesso stato di autenticazione. Quando un’applicazione si autentica
all’interno di un token tutte le sessioni di quell’applicazione diventano
autenticate dal token stesso e se un’applicazione si disconnette da un token
tutte le sessioni dell’applicazione vengono automaticamente chiuse.
Le sessioni vengono gestite da un handle di sessione, che è un valore
che identifica univocamente una sessione. Tale valore viene specificato alle
funzioni per indicare loro su quale sessione devono agire.
4.7.3 Oggetti
Un token è un dispositivo che contiene oggetti e può operare funzioni di
tipo crittografico. Cryptoki definisce tre classi di oggetti: dati, certificati e
chiavi. Un oggetto “dato” è specificato dall’applicazione, un oggetto “certificato”
contiene un certificato digitale, un oggetto “chiave” contiene una chiave
crittografica che può essere pubblica, privata o segreta. Ogni oggetto chiave
possiede dei sottotipi che ne specificano l’utilizzo nei meccanismi49.
La gerarchia degli oggetti è la seguente.
49
Nel testo tecnico “PKCS#11: Cryptographic Token Interface Standard” della RSA Laboratories, gli
algoritmi crittografici vengono indicati con il nome di “mechanism” e di conseguenza tradotti in
“meccanismi”.
101
Capitolo 4
Figura 47. Gerarchia degli oggetti definiti in cryptoki.
Gli oggetti possono anche essere classificati in base al loro tempo di vita
e alla loro visibilità, si possono quindi distinguere:
•
Oggetti token: sono visibili a tutte le applicazioni connesse al token che
hanno un permesso sufficiente e permangono all’interno del token anche
quando la sessione viene chiusa ed il token rimosso dallo slot.
•
Oggetti sessione: ogni volta che una sessione viene chiusa tutti gli
oggetti creati dalla sessione vengono distrutti. In aggiunta tali oggetti
sono visibili solo all’applicazione che li ha creati.
Un’ulteriore classificazione può essere fatta in base ai requisiti di
accesso, quindi troviamo:
•
Oggetti pubblici: un’applicazione non ha necessità di eseguire un login
al token per vederli.
•
Oggetti privati: sono visibili solo a seguito di una avvenuto login.
In generale un oggetto consiste in una serie di attributi, ognuno dei quali
è caratterizzato da un determinato valore. Andiamo ora a vedere più da vicino
le tre principali classi di oggetti definite da cryptoki.
102
Smart Card
Oggetti “Data”
Un oggetto Data contiene informazioni relative alle applicazioni ed è
definito da cryptoki con i seguenti attributi:
Data object
Application
Object ID
Value
Figura 48. Attributi di un oggetto Data.
Oggetti “Key”
Gli oggetti Key contengono chiavi di crittografia e autenticazione, che
possono essere private, pubbliche o segrete.
Key
Key type
Key ID
Start Date
End Date
Derive
Local
Key Gen Mechanism
Public Key
Subject
Trusted
Encrypt
Verify
Verify Recover
Wrap
Private Key
Subject
Sensitive
Decrypt
Sign
Sign Recover
Unwrap
Extractable
Always Sensitive
Never Extractable
Secret Key
Sensitive
Encrypt
Decrypt
Sign
Verify
Wrap
Unwrap
Extractable
Always Sensitive
Never Extractable
Figura 49. Gerarchia e attributi di un oggetto Key.
103
Capitolo 4
Oggetti “Certificate”
Gli oggetti Certificate possono memorizzare certificati a chiave pubblica.
Cryptoki specifica la modalità di accesso a questo tipo di oggetti, ma non
attribuisce significati ed usi ai certificati.
Certificate
Certificate Type
Trusted
X.509 Public Key
Certificate
X.509 Attribute
Certificate
Subject
Certificate ID
Issuer
Serial Number
Value
Owner
Issuer
Serial Number
Attribute Types
Value
Figura 50. Gerarchia e attributi di un oggetto Certificate.
In realtà cryptoki prevede anche altri tipi di oggetti, che forniscono
informazioni aggiuntive riguardanti, ad esempio, le caratteristiche hardware del
dispositivo e gli algoritmi crittografici supportati. La visione generale della
gerarchia di alto livello degli oggetti definiti dallo standard cryptoki e di alcuni
attributi ad essi associati è illustrata nella seguente figura.
104
Smart Card
Figura 51. Gerarchia completa degli oggetti definiti nello standard cryptoki.
4.7.4 Considerazioni sulla sicurezza
Come interfaccia ai dispositivi crittografici Cryptoki fornisce le basi per la
sicurezza all’interno di un computer o di un sistema di comunicazione. Le due
principali caratteristiche dell’interfaccia che facilitano tale compito sono:
•
L’accesso agli oggetti privati, le funzioni crittografiche e i certificati di un
token richiede un PIN. Quindi il semplice possesso del dispositivo
crittografico non è sufficiente per usarlo, è necessario anche conoscere il
PIN di autenticazione.
•
Una protezione aggiuntiva per le chiavi private o segrete può essere
garantita designandole come sensitive, cioè che non possono mai
essere rivelate in chiaro al di fuori del token, oppure unextractable,
ovvero non possono mai essere rivelate al di fuori del token neanche in
forma criptata (anche se rimangono comunque utilizzabili).
Ci si aspetta che l’accesso ad oggetti privati di tipo sensitive o
unextractable risulti difficile all’infuori dell’interfaccia Cryptoki. Un dispositivo è
solitamente dotato di un ambiente protetto (ad esempio una memoria protetta)
105
Capitolo 4
in cui memorizzare dati di questo tipo, alcuni dispositivi però non hanno questa
possibilità, quindi devono proteggere i loro oggetti in altro modo. Una soluzione
è quella di cifrare tali oggetti con una chiave speciale, detta master key, che
viene ricavata dal PIN dell’utente.
Sicuramente la crittografia è solo un elemento di sicurezza, e il token
rappresenta solo un componente di un sistema, per cui la sicurezza deve
essere intesa a livello globale. Mentre un token può essere considerato sicuro,
bisogna allargare il campo di vista anche al sistema operativo che ospita
l’applicazione che fa uso del token. E’ infatti possibile che altre applicazioni ostili
intercettino informazioni riservate (come ad esempio il PIN del dispositivo)
mentre queste sono gestite dal sistema operativo oppure attraversano un
canale di comunicazione, con la conseguenza che l’applicazione pirata
potrebbe far eseguire qualsiasi tipo di operazione al token. Da notare
comunque che, in ognuno di questi spiacevoli casi, le chiavi marcate “sensitive”
o “unextractable” non possono in alcun modo essere rilevate o modificate.
Si può quindi concludere che Cryptoki non garantisce la sicurezza
dell’intero sistema, ma fornisce una buona e solida base per lo sviluppo di
applicazioni che fanno uso di dispositivi crittografici.
4.7.5 Provider di sicurezza IAIK
Un provider di sicurezza è un software in grado di fornire la più ampia
varietà di funzioni crittografiche e realizzare un’interfaccia per l’accesso al
dispositivo crittografico.
In questo lavoro è stata utilizzata un’implementazione dello standard
PKCS#11 sviluppata dall’Institute for Applied Information Processing and
Communications
(IAIK)
presso
l’università
austriaca
“University
of
Technology” di Graz50.
Il Provider IAIK fornisce un insieme di funzioni crittografiche accessibili
mediante le API standard Java JCA (Java Cryptography Architecture) e JCE
50
http://www.iaik.tugraz.at/
106
Smart Card
(Java Cryptography Extention) e permette l’accesso al dispositivo fisico tramite
una libreria conforme al descritto standard PKCS#11.
La parte che si occupa di comunicare direttamente col il token prende il
nome di Wrapper. La libreria fornita dal wrapper fa uso dei metodi nativi di Java
JNI (Java Native Interface) che permettono alle applicazioni scritte in Java di
usare le API Cryptoki (che, ricordiamo, sono scritte in C).
Nella figura seguente è illustrata l’organizzazione dei livelli software
coperti dal wrapper IAIK.
Figura 52. Struttura dei livelli software del wrapper IAIK.
Lo strato più basso è occupato dalla libreria dinamica di sistema fornita
dal produttore del token, compilata per la piattaforma di destinazione, seguendo
le direttive della specifica PKCS#11. Lo strato immediatamente superiore del
wrapper è necessario per realizzare lo strato JNI che permette al codice Java di
utilizzare funzioni C. Questo strato e quello ancora superiore devono quindi
rispettare la convenzione dei nomi (name mangling) delle funzioni e dei metodi
nativi prevista da JNI. Alla cima dello stack c’è il livello API, che è una struttura
Object-Oriented con la quale si interfacciano le applicazioni.
Il provider IAIK è dedicato all’uso di particolari dispositivi crittografici,
come le smart card, e gli oggetti utilizzati durante l’esecuzione delle funzioni
crittografiche vengono gestiti in modo specifico. Ad esempio gli oggetti “chiave”
del provider PKCS#11 rappresentano chiavi contenute all’interno di un token e
quindi non possono essere gestite come normali chiavi software. Infatti se
un’applicazione richiede l’utilizzo di una chiave per un’operazione crittografica, il
provider non trasferisce la chiave alla JVM, bensì invia il dato da elaborare
107
Capitolo 4
all’interno del token e chiede al token stesso di eseguire l’operazione prevista
con la specifica chiave. In questo modo la chiave non esce mai al di fuori del
token che contiene, oltre alla chiave stessa, anche l’implementazione
dell’algoritmo necessario ad eseguire l’operazione direttamente dentro il token.
Possiamo immaginare il token come una scatola nera all’esterno della quale
vediamo entrare ed uscire dati in chiaro e dati cifrati, ma non possiamo in alcun
modo vedere cosa avviene all’interno della scatola.
108
Realizzazione del progetto
Capitolo 5.
REALIZZAZIONE DEL PROGETTO
109
Capitolo 5
5.1
Descrizione generale del progetto
Il lavoro che andrò ora a presentare è stato sviluppato in collaborazione
con la ASUR zona 7 della regione Marche.
Nel corso di questa tesi si è fatto spesso riferimento al settore della
Pubblica Amministrazione e alla sua progressiva migrazione verso le tecnologie
informatiche, allo scopo di trarre vantaggi sia per chi lavora (in termini di
migliore gestione degli archivi e procedure più veloci), sia per l’utenza pubblica
(garantendo più efficienza nei servizi e minori tempi di attesa). Proprio in
quest’ottica va ad inserirsi questo progetto, del quale ora illustreremo le linee
guida.
L’obiettivo è quello di progettare un software che utilizzi le smart card per
realizzare la firma digitale di documenti elettronici. Il campo di applicazione è
appunto l’ambito sanitario, in cui un medico può inviare o richiedere dei referti
ad un database (chiamato repository) per eventuali operazioni di teleconsulto o
di second opinion. Il referto in questione, prima di essere spedito, dovrà essere
firmato digitalmente, in modo da garantire i requisiti base di un sistema di
sicurezza (autenticazione, integrità e riservatezza). Per il momento l’attenzione
è rivolta ad un’utenza di soli medici, si prevede comunque che, una volta
avviato il servizio, anche i pazienti possano disporre di una propria smart card.
La prima decisione che si deve prendere riguarda il tipo di smart card da
adottare. La scelta ricade su due possibili alternative: adottare una carta di
impiego nazionale (come la CIE51); oppure adottare una soluzione propria. La
prima scelta sembrerebbe più vantaggiosa, considerando che, in breve tempo,
tutti saranno in possesso della carta di identità elettronica; inoltre c’è anche il
vantaggio, non da poco, di poter usare una sola carta per più servizi. Seguire
questa strada, però, si è rivelato presto difficoltoso a causa del fatto che la CIE
non è ancora disponibile in tutti i comuni, inoltre c’è una mancanza di
divulgazione di materiale, sia tecnico che pratico, relativo al suo funzionamento.
Non rimane quindi che adottare una soluzione propria che preveda l’impiego di
una smart card specifica per il servizio offerto.
51
Carta di Identità Elettronica.
110
Realizzazione del progetto
Come si è detto, l’utenza prevista, sia attuale che futura, per questo
progetto coinvolge sia i medici che i pazienti. Un campo di impiego così vasto
richiede una particolare attenzione alla possibilità di utilizzo delle tecnologie
informatiche proposte da parte di personale non specializzato. Si è cercato
quindi di improntare il progetto verso la semplicità d’uso, continuando
comunque a garantire tutti i servizi e i requisiti di sicurezza previsti. Si è scelto
allora di “partire da zero” e seguire tutti i passi necessari alla realizzazione
dell’infrastruttura per la firma digitale. Si prevede quindi che un utente (che si
tratti, indifferentemente, di un medico o di un paziente) si procuri una smart card
vuota, che dovrà essere inizializzata e resa utilizzabile per le operazioni di firma
digitale.
Il progetto, quindi, si compone di due parti principali:
•
Inizializzazione: è la fase in cui la smart card è resa operabile. Si deve
dotare la scheda di una coppia di chiavi e di un certificato a chiave
pubblica (nel formato X.509). Più precisamente vengono create, al suo
interno, la coppia di chiavi asimmetriche e la richiesta di certificato da
inviare alla Certification Authority. Quest’ultima firmerà un certificato
X.509 che poi sarà memorizzato all’interno della smart card.
•
Firma: è la fase in cui si realizzano le operazioni legate alla firma digitale
del documento elettronico. In particolare sarà possibile: cifrare il
documento originale per ottenere la firma; decifrare un documento
firmato; verificare la firma per testare l’integrità del documento. Il
software di firma riceverà in ingresso direttamente il digest del
documento originale, si dovrà quindi occupare di cifrarlo con la chiave
privata presente nella smart card e restituire un oggetto che contenga il
documento cifrato ed il certificato a chiave pubblica (che contiene la
chiave di decifratura). Il fatto di avere come input un digest rende il
software di firma utilizzabile con qualunque tipo di documento e, di
conseguenza, in qualsiasi contesto.
111
Capitolo 5
5.1.2 Applicazione all’ambito sanitario
Questo lavoro trova applicazione ad un altro progetto nato anch’esso
dalla collaborazione tra l’Università Politecnica delle Marche e la ASUR Marche
zona 7 di Ancona riguardante la delocalizzazione della refertazione diagnostica.
Tale progetto, denominato MirO, si pone l’obiettivo di fornire un prodotto
flessibile in grado di implementare un servizio di refertazione asincrono: cioè
capace di separare, sia da un punto di vista temporale che spaziale,
l’esecuzione di un esame dalla refertazione dello stesso. Lo scopo è quello di
creare un’applicazione software completa in grado di gestire l’intero processo di
telerefertazione e di teleconsulto.
Figura 53. Posizione del progetto MiRo nel processo di telerefertazione e teleconsulto.
Tale progetto intende realizzare una piattaforma orientata ai servizi che
abbia le caratteristiche di flessibilità e semplicità. La sua architettura infatti è
basata su standard diffusi e riconosciuti, come Internet, in modo da creare le
basi per facilitare le applicazioni sia in ambito sanitario a livello di personale
medico, che, in un prossimo futuro, direttamente ai cittadini.
MiRo si basa sul concetto di evento. L’effettuazione di un esame presso
un laboratorio (qualsiasi, di una qualunque struttura ospedaliera) e la
112
Realizzazione del progetto
conseguente archiviazione del dato in forma digitale genera ciò che viene
chiamato evento. L’evento, in realtà, non è il dato clinico vero e proprio, ma
rappresenta una sorta di meta-dato-clinico del dato digitale prelevato in
laboratorio. Esso consiste in una serie di informazioni che riguardano: l’unità
erogante il dato, la data e l’ora dell’esame, la struttura che lo ha prodotto, il
codice impegnativa, il link da dove si può scaricare il dato, lo stato e altro
ancora.
Ogni evento viene immagazzinato all’interno di un apposito raccoglitore,
definito repository, che costituisce il core del sistema e che contiene la
definizione del legame tra evento ed esame. Qualsiasi esame che può essere
memorizzato in forma digitale può essere associato ad un evento, dotando
quindi il progetto delle caratteristiche di flessibilità ed adattabilità.
In figura è mostrata l’architettura generale di MiRo dove si notano i tre
attori principali del sistema: Repository; Laboratories; Doctors.
Figura 54. Architettura generale del progetto MiRo.
Il cuore del sistema è rappresentato dal Repository centrale offerto da
un’azienda o da un ente erogante (vedi ASUR), il quale si impegna nel corretto
funzionamento dell’intero sistema di refertazione e nella manutenzione dello
stesso.
113
Capitolo 5
A destra del repository troviamo il laboratorio, cioè la struttura che
usufruisce del servizio per generare gli eventi dovuti all’acquisizione dei dati
digitali di un esame clinico.
A sinistra del repository si trova colui che scrive il referto, ossia il medico
o un’equipe di medici specializzati, i quali pubblicano il proprio referto
autenticandolo con la propria firma digitale.
Proprio in quest’ultima parte si va a collocare il progetto di firma digitale
che garantisce all’intero sistema le caratteristiche di: autenticazione d’identità;
riservatezza dei dati trasmessi; integrità dei dati; non ripudio della
comunicazione. Tutte queste proprietà sono alla base di un sistema sicuro e
sono raggiunte tramite l’impiego delle tecniche di crittografia asimmetrica, delle
infrastrutture a chiave pubblica e delle smart card.
5.2
Implementazione
Verranno ora descritti gli aspetti pratici del lavoro svolto, a cominciare da
un elenco degli strumenti che sono stati necessari per la sua realizzazione, per
poi andare più in dettaglio sul software che è stato prodotto. Si è voluto
analizzare meglio anche il provider di sicurezza IAIK (già introdotto nella
sezione dedicata alle smart card52) in quanto elemento base per l’accesso alla
scheda.
5.2.1 Strumenti utilizzati
Gli strumenti software impiegati nel progetto sono:
•
Java 1.4.2 Standard Edition: è il kit di sviluppo Java;
•
Eclipse 3.1: editor per il software Java;
•
Provider IAIK: fornisce le funzioni crittografiche e l’interfaccia con la
smart card;
52
Si veda il paragrafo § 4.7.5.
114
Realizzazione del progetto
•
OpenSSL 0.9.8: impiegato come Certification Authority temporanea per
la creazione dei certificati X.509.
Per quanto riguarda l’hardware:
•
Tutti i programmi sopra enunciati sono stati installati su di un Celeron
con clock a 650 MHz, memoria RAM da 320 MB e sistema operativo
Windows 2000 Professional.
•
Il lettore di smart card è un GemPC410 della GemPlus con collegamento
seriale alla porta RS232.
•
Le smart card sono delle GemPlus GPK16 da 16KB.
5.2.2 Installazione del Provider IAIK
Il Provider di sicurezza IAIK, sviluppato dalla “University of Technology”
austriaca di Graz, è un software che fornisce un insieme di funzioni
crittografiche, utilizzabili mediante le API standard JCE, ed un Wrapper che
implementa il modulo PKCS#11 per interfacciare le smart card53. E’ un
elemento essenziale necessario in tutte e tre le componenti software che
verranno presentate, per questo si è ritenuto opportuno dedicargli particolare
attenzione. L’installazione delle due parti del provider avviene in modo separato
ed anche il loro utilizzo è diverso (come vedremo più avanti descrivendo il
software di firma).
La JCE fornita dal provider IAIK si installa molto semplicemente da
programma inserendo la seguente riga di codice:
Security.addProvider(new IAIK());
L’installazione del modulo PKCS#11 invece prevede due possibili
alternative: una installazione statica ed una dinamica. Andremo ora a vedere
brevemente i due procedimenti e le ragioni che hanno condotto a scegliere
prima l’una poi l’altra versione.
53
Per informazioni più dettagliate si veda il paragrafo § 4.7 PKCS#11 e §4.7.5 Provider di sicurezza
IAIK.
115
Capitolo 5
L’installazione statica prevede di aggiungere le seguenti librerie esterne
al progetto:
•
iaikPkcs11Provider.jar: contiene le classi che costituiscono il provider;
•
iaikPkcs11Wrapper.jar: contiene le classi che costituiscono il wrapper;
•
iaik_jce.jar: contiene le funzioni crittografiche;
•
iaik_jce_full.jar: contiene alcune funzioni crittografiche aggiuntive (in
realtà questa libreria è opzionale).
Bisogna poi impostare le proprietà del provider aggiungendo i file
“IAIKPkcs11.properties” e “IAIKPkcs11Global.properties” (contenuti all’interno
del pacchetto “iaikPkcs11Provider.jar”) in una gerarchia di directory del tipo
“iaik/pkcs/pkcs11/provider/” da inserire all’interno del classpath del progetto. Il
primo file dovrà essere modificato andando a scegliere la corretta libreria DLL
per il dispositivo di lettura che si sta utilizzando. Nel nostro caso il dispositivo è
un GemPlus e la libreria è “gclib.dll” (fornita con il CD di installazione del
lettore). Il secondo file invece deve essere anch’esso modificato aggiungendo la
seguente riga:
providerInstance.1=iaik/pkcs/pkcs11/provider/IAIKPkcs11.properties
che indica alla prima istanza del provider di cercare le proprietà necessarie sul
file “IAIKPkcs11.properties”.
Si deve poi modificare il file “java.security” del Java Runtime
Environment aggiungendo l’istanza del provider nel seguente modo:
security.provider.6=iaik.pkcs.pkcs11.provider.IAIKPkcs11
Infine, per richiamare il provider da programma, basta scrivere la
seguente riga di codice:
pkcs11Provider = IAIKPkcs11.getProviderInstance(1);
L’installazione dinamica necessita l’importazione delle stesse librerie del
caso precedente, ma le proprietà del provider vengono impostate al runtime
direttamente dal programma con il seguente codice:
Properties providerProperties = new Properties();
providerProperties.put("PKCS11_NATIVE_MODULE", "gclib.dll");
pkcs11Provider = new IAIKPkcs11(providerProperties);
Security.addProvider(pkcs11Provider);
116
Realizzazione del progetto
Inizialmente si è scelto di eseguire una installazione statica del provider
per motivi di robustezza, in quanto tutte le configurazioni impostate
staticamente
hanno
sempre
priorità
maggiore
di
quelle
impostate
dinamicamente. Questa soluzione però pone molti limiti alla possibilità di
interagire con diversi dispositivi hardware, in quanto, per ognuno di essi,
bisognerebbe creare una istanza dedicata del provider con il relativo file di
proprietà che seleziona la libreria DLL corretta.
Si è preferito allora adottare l’opzione dinamica che assegna la libreria
DLL al runtime, in questo modo si è più predisposti verso l’interoperabilità.
Anche se, attualmente, il software prodotto è in grado di gestire un solo tipo di
lettore, uno sviluppo futuro potrebbe eseguire al runtime sia il riconoscimento
dell’hardware che l’assegnazione dell’apposita libreria.
Sono state considerate anche soluzioni alternative al provider IAIK, che
presenta delle limitazioni di utilizzo. Una di queste è Bouncy Castle54. Si tratta di
un provider di sicurezza completamente gratuito capace di fornire tutte le
funzioni crittografiche necessarie. Non è stato impiegato in questo progetto in
quanto non implementa il modulo PKCS#11 per comunicare con le smart card.
Una sua applicazione potrebbe riguardare la Certification Authority per la
generazione dei certificati X.509. Una alternativa possibile, invece, sembra
essere il provider della SUN fornito in dotazione con le ultime versioni del
pacchetto Java. Questo infatti è gratuito (si tratta di software open source) ed
implementa il modulo PKCS#11.
5.2.3 Software prodotto
Il software sviluppato nel presente lavoro si compone di tre parti distinte:
•
Software di inizializzazione: si occupa di creare la coppia di chiavi e la
richiesta di certificato sulla smart card e, successivamente, di inserire il
certificato X.509 all’interno della scheda.
54
www.bouncycastle.org
117
Capitolo 5
•
Software di firma: esegue le operazioni di cifratura necessarie per
realizzare la firma digitale.
•
Tool di gestione della smart card: è uno strumento di uso generico
capace di leggere e scrivere la smart card e gestire il keystore della
scheda.
Andremo ora ad analizzare questi programmi descrivendone il
funzionamento e riportando anche alcuni esempi. Per maggior chiarezza si può
fare riferimento al codice riportato in appendice.
Software di inizializzazione
Si è già discusso, nella descrizione generale del progetto, sulla scelta
che è stata fatta di partire da smart card vuote e renderle utilizzabili per le
operazioni di firma. Il software di inizializzazione ha proprio questo compito, ed
in particolare si occupa di generare la coppia di chiavi e la richiesta di certificato
all’interno della smart card, inviare la richiesta alla Certification Authority e
registrare il certificato X.509, generato dalla CA, sulla smart card.
Lo schema di funzionamento è il seguente:
Generazione
chiavi RSA
Alias
Generazione
PKCS10 CSR
Invio CSR
alla CA
CA off-line
Inserimento
su Smart Card
Invio cert.
X.509
Generazione
certificato
Figura 55. Schema di funzionamento del software di inizializzazione.
118
Realizzazione del progetto
Si parte da un Alias che è una semplice stringa di caratteri che identifica
univocamente il possessore della smart card.
Si genera poi la coppia di chiavi RSA. Questa operazione avviene
all’interno della smart card servendosi del provider IAIK per accedere ad essa
ed alle sue funzioni. Si è utilizzato il metodo “KeyPairGenerator” del package
“java.security” assegnando ad una sua istanza l’algoritmo RSA ed il nome del
provider IAIK:
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA",
pkcs11Provider.getName());
Poi si sono elencate le specifiche delle chiavi pubblica e privata, in
particolare si è resa la chiave privata “sensitive” e “unextractable” (in modo che
non possa mai essere rivelata al di fuori della scheda, né in chiaro né in forma
criptata) e si è scelta una lunghezza pari a 1024 bit. In questa fase si è utilizzato
l’alias per assegnare la “label” alle chiavi. Tramite queste specifiche si è
inizializzata l’istanza del precedente metodo di generazione e si è creata la
coppia di chiavi:
keyPairGen.initialize(keyPairSpec);
KeyPair keyPair = keyPairGen.generateKeyPair();
Viene poi creata la richiesta di certificato nel formato standard PKCS#10.
Anche questa operazione è eseguita all’interno della smart card, poiché la
richiesta dovrà essere firmata con la chiave privata. Il metodo utilizzato,
“CertificaRequest”, fa parte delle librerie del provider IAIK ed è impiegato in
questo modo:
iaik.pkcs.pkcs10.CertificateRequest request =
new iaik.pkcs.pkcs10.CertificateRequest(keyPair.getPublic(), name);
Riceve come parametri la chiave pubblica e “name”, che rappresenta il
distinguished name secondo lo standard X.500. Tale richiesta è stata poi
firmata con la chiave privata, impiegando l’algoritmo di hashing SHA-1:
request.sign(iaik.asn1.structures.AlgorithmID.sha1WithRSAEncryption,
keyPair.getPrivate(), pkcs11Provider.getName());
La richiesta così ottenuta viene codificata in BASE 64 (che serve a
rappresentare una sequenza di byte in caratteri ASCII) ed inviata alla
Certification Authority. Quest’ultima ha il compito di firmarla e creare un
certificato valido nello standard X.509. All’interno di esso ci saranno quindi due
119
Capitolo 5
certificati a chiave pubblica: uno relativo al possessore della card e firmato dalla
CA; l’altro relativo alla CA stessa ed autofirmato. Questo procedimento è stato
messo in pratica servendosi del software OpenSSL. Il certificato è ottenuto nel
formato PEM (Privacy-Enhanced Mail) che è una versione stampabile dello
standard PKCS#7.
L’ultima operazione riguarda la memorizzazione del certificato all’interno
della smart card. Si tratta di aggiungere un elemento “key entry” al key store
della scheda, con il seguente metodo:
tokenKeyStore.setKeyEntry("alias", priK, null, chain);
in cui “alias” è l’identificativo del possessore della scheda, “priK” è la chiave
privata generata precedentemente, “null” è la password del key store, “chain” è
la catena di certificazione estratta dal file PEM restituito dalla CA. Poiché viene
utilizzata la chiave privata, anche questa operazione deve essere svolta
all’interno della scheda servendosi del provider IAIK.
A questo punto nella smart card sono presenti: la chiave privata ed il
certificato a chiave pubblica relativi all’alias scelto. Quindi la scheda è ora
utilizzabile per le operazioni di firma digitale.
E’ importante sottolineare ancora una volta il fatto che tutte le operazioni
che richiedono l’impiego della chiave privata vengono eseguite dentro la smart
card. I metodi Java che necessitano di queste operazioni delegano al provider
IAIK il compito di eseguirle, in quanto è l’unico che può avere accesso alla
smart card. Per questo motivo bisogna sempre specificare il nome del provider
nella creazione dell’istanza di un metodo crittografico.
Riportiamo ora alcuni esempi per dare un’idea pratica di quanto descritto.
Proponiamo in particolare la stampa della catena di certificazione:
La catena presenta 2 certificati
1° elemento della catena:
Version: 0
Serial number: 18
Signature algorithm: sha1WithRSAEncryption (1.2.840.113549.1.1.5)
Issuer:
[email protected],CN=JTelemed,OU=Soft,O=JTelemed,L=Ancona,ST=An,C=IT
Valid not before: Fri Feb 03 11:00:23 CET 2006
not after: Sun Nov 23 11:00:23 CET 2008
Subject: CN=nome,OU=ou,O=o,L=l,ST=st,C=it
SunJSSE RSA public key:
120
Realizzazione del progetto
public exponent:
010001
modulus:
b64c5f2e 547e0f70 d869824e 29a655da f6143851 35f1a722 b4e500cf
be692586 b4dff5d9 7852a5b1 eaec11d4 241e4a0d f3af694e 20b64805
4248165e 12e43371 31f20f32 eda154b1 dca9cab7 6b92680d 18fd0c96
9161a793 ebc2bd8a 7f081c41 16ada19a fd5b5bad 521fb1aa b36807cd
Certificate Fingerprint (MD5) :
DD:01:3B:4B:9B:C0:37:F3:92:9B:F7:24:27:4F:F4:8A
Certificate Fingerprint (SHA-1):
CD:C0:43:7F:F7:EC:DC:E2:D1:AB:BE:7E:EC:66:81:5D:93:F1:27:DC
2° elemento della catena:
Version: 0
Serial number: 1140969833
Signature algorithm: sha1WithRSAEncryption (1.2.840.113549.1.1.5)
Issuer: CN=JTelemed,OU=Soft,O=JTelemed,L=Ancona,ST=An,C=IT
Valid not before: Sun Feb 26 17:03:53 CET 2006
not after: Sat May 27 18:03:53 CEST 2006
Subject: CN=JTelemed,OU=Soft,O=JTelemed,L=Ancona,ST=An,C=IT
SunJSSE RSA public key:
public exponent:
010001
modulus:
c911967d 40261662 2698b72c 322d0051 ba4e46f7 ca354315 1a41f447
b922c953 3f3e199d 16fa2736 0b87087b 1c89ca87 ccb8938e 9cbbfc22
7d05b2bd d6a1b0bd b659565e 9185af24 c06b1047 d79e632b 8dfef1b9
8108c2de 5b04c493 771240de fbeadec7 3a9d2217 255eda4e ad64f838
Certificate Fingerprint (MD5) :
AF:73:A5:82:CB:66:BF:91:5A:2D:BC:2F:09:8A:22:3D
Certificate Fingerprint (SHA-1):
5051471c
2170d913
6c9efc60
17f36601
80fd2058
65a9e773
d1a23fdd
05027f1d
1F:2C:64:91:B2:54:14:27:6B:1E:27:41:A4:BC:42:79:5C:C8:A2:9A
Si può notare che il primo certificato ha come subject il DN
(Distinguished Name) del possessore della smart card, e come issuer il DN
della CA, mentre il secondo certificato è autofirmato e infatti i due campi
indicano la stessa CA.
Questa stessa catena di certificati è memorizzata su file in formato
codificato e si presenta nel seguente modo:
-----BEGIN CERTIFICATE----MIICQzCCAawCARIwDQYJKoZIhvcNAQEFBQAwgYUxCzAJBgNVBAYTAklUMQswCQYD
VQQIEwJBbjEPMA0GA1UEBxMGQW5jb25hMREwDwYDVQQKEwhKVGVsZW1lZDENMAsG
A1UECxMEU29mdDERMA8GA1UEAxMISlRlbGVtZWQxIzAhBgkqhkiG9w0BCQEWFGp0
ZWxlbWVkQGp0ZWxlbWVkLml0MB4XDTA2MDIwMzEwMDAyM1oXDTA4MTEyMzEwMDAy
M1owTjELMAkGA1UEBhMCaXQxCzAJBgNVBAgTAnN0MQowCAYDVQQHEwFsMQowCAYD
VQQKEwFvMQswCQYDVQQLEwJvdTENMAsGA1UEAxMEbm9tZTCBnzANBgkqhkiG9w0B
AQEFAAOBjQAwgYkCgYEAtkxfLlR+D3DYaYJOKaZV2vYUOFE18acitOUAz1BRRxy+
aSWGtN/12XhSpbHq7BHUJB5KDfOvaU4gtkgFIXDZE0JIFl4S5DNxMfIPMu2hVLHc
qcq3a5JoDRj9DJZsnvxgkWGnk+vCvYp/CBxBFq2hmv1bW61SH7Gqs2gHzRfzZgEC
AwEAATANBgkqhkiG9w0BAQUFAAOBgQAnFmV86Cj7XU1M+iYINgq1A/FMnXDM/BZP
3LmKQ/rSdAJ+WjZH4gimrO3s4728Y01y6nCTX0fE5+V3lsbrJ7aIjTlHJCZUU5BH
qXtJXmxoSrI9YG/TPMnrsDnFn9M3J0gEb6s7rbU8SQMWn99pBsIF58r1lWaQ4pSC
d5NRUIoRGA==
-----END CERTIFICATE---------BEGIN CERTIFICATE-----
121
Capitolo 5
MIICMjCCAZsCBEQB0WkwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCSVQxCzAJ
BgNVBAgTAkFuMQ8wDQYDVQQHEwZBbmNvbmExETAPBgNVBAoTCEpUZWxlbWVkMQ0w
CwYDVQQLEwRTb2Z0MREwDwYDVQQDEwhKVGVsZW1lZDAeFw0wNjAyMjYxNjAzNTNa
Fw0wNjA1MjcxNjAzNTNaMGAxCzAJBgNVBAYTAklUMQswCQYDVQQIEwJBbjEPMA0G
A1UEBxMGQW5jb25hMREwDwYDVQQKEwhKVGVsZW1lZDENMAsGA1UECxMEU29mdDER
MA8GA1UEAxMISlRlbGVtZWQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMkR
ln1AJhZiJpi3LDItAFG6Tkb3yjVDFRpB9EeA/SBYuSLJUz8+GZ0W+ic2C4cIexyJ
yofMuJOOnLv8ImWp53N9BbK91qGwvbZZVl6Rha8kwGsQR9eeYyuN/vG50aI/3YEI
wt5bBMSTdxJA3vvq3sc6nSIXJV7aTq1k+DgFAn8dAgMBAAEwDQYJKoZIhvcNAQEF
BQADgYEAef9V/kN/CBQEDn5o5Zd0/vsZy62Rdg3/Snn8oL9ew5Fv/gvOZrdecd0o
LyV/quW+XqmmjPY+YcLHtupUJJpEfhAm06GImcojTt+3jCtjAb0iSocyAfOVIcWb
ylgaNlmzaZPnuctITxh0FXDl7BfK7qzyQ0UJkg3ApCRSqeHIUqc=
-----END CERTIFICATE-----
Software di firma
Il software di firma si compone principalmente di due classi:
•
Firma.java: è la classe che si occupa di eseguire le funzioni
crittografiche relative alle operazioni di firma digitale.
•
DigestFirmato.java: è una classe che rappresenta il messaggio firmato
e contiene due variabili: la firma (sottoforma di array di byte) ed il
certificato X.509. Inoltre questa classe prevede anche due metodi
(serializza e deserializza) che consentono il salvataggio su file ed il
recupero dei due oggetti in forma serializzata.
Il cuore di questo programma è la classe “Firma” che si compone di
diversi metodi, tra i quali i più importanti sono:
public DigestFirmato cifra(byte[] digest)
che riceve come parametro il digest sottoforma di array di byte, lo invia alla
smart card per la cifratura e ritorna una istanza dell’oggetto DigestFirmato;
public byte[] decifra(DigestFirmato df)
riceve come parametro una istanza di DigestFirmato, ne estrae il messaggio
cifrato e il certificato X.509 ed esegue la decifratura. Ritorna l’array di byte
risultato della decifratura;
public void compara(byte arr1[], byte arr2[])
riceve due array di byte come parametri che rappresentano il digest originale e
quello ricavato dalla decifratura. Ne esegue il confronto per verificare che il
messaggio non sia stato modificato.
122
Realizzazione del progetto
Questi metodi richiamano a loro volta altri metodi che si occupano, ad
esempio, di verificare la presenza della smart card, richiedere il PIN di
autenticazione per eseguire il login, verificare la validità temporale e le
condizioni di uso del certificato, accedere alle chiavi pubblica e privata.
Anche in questo caso andremo a commentare le più importanti righe di
codice, in particolare quelle relative alle operazioni di cifratura e decifratura. In
ambedue i casi è stato utilizzato il metodo “Cipher” della libreria “javax.crypto”.
La cifratura necessita l’impiego della chiave privata, bisogna quindi
specificare il modulo PKCS#11 del provider IAIK nell’istanza di cifratura:
Cipher c = Cipher.getInstance("RSA/ECB/PKCS1Padding",
pkcs11Provider.getName());
Il primo parametro specifica l’algoritmo di cifratura (RSA), il tipo di cifratura a
blocchi (ECB) ed il tipo di riempimento (PKCS1Padding).
In seguito si inizializza Cipher nella modalità di cifratura assegnando anche la
chiave privata:
c.init(Cipher.ENCRYPT_MODE, priK);
Poi si esegue l’effettiva cifratura:
cifrato = c.doFinal(digest);
Una volta realizzata la firma si crea l’istanza dell’oggetto DigestFirmato
assegnando sia la firma che il certificato:
DigestFirmato df = new DigestFirmato(cifrato, x509);
Durante la decifratura si compiono le stesse operazioni, ma è importante
notare una differenza nel modo in cui viene creata l’istanza di Cipher. In questo
caso non è richiesto l’impiego della chiave privata in quanto la decifratura
avviene con la chiave pubblica. Inoltre tale chiave è estratta dal certificato
recuperato dall’oggetto DigestFirmato, quindi, in realtà, non è necessaria
neanche la smart card55. Per questo nell’istanziazione non si specifica il modulo
PKCS#11 del provider IAIK, ma quella parte che fornisce solo la JCE e che è
chiamata “IAIK”:
Cipher c = Cipher.getInstance("RSA/ECB/PKCS1Padding", "IAIK");
55
Come in effetti dovrebbe essere. Si ricordi che il messaggio firmato è inviato su una rete pubblica e può
raggiungere qualsiasi parte del mondo, e chi riceve il messaggio non può sicuramente disporre della
stessa smart card di colui che lo ha inviato.
123
Capitolo 5
Ovviamente il modo di decifratura deve adottare le stesse proprietà impiegate
nella cifratura (RSA/ECB/PKCS1Padding), altrimenti si incorrerebbe in un
errore.
In questa spiegazione è stato tralasciato il dettaglio di come viene gestita
la chiave privata. Sappiamo già che il suo utilizzo è delegato esclusivamente al
provider IAIK. Vogliamo ora precisare il fatto che, nell’operazione di firma, viene
scelta la prima chiave trovata nel key store, senza selezionare un alias
specifico. E’ stata scelta questa soluzione in quanto si prevede che nella
scheda sia presente solo una coppia di chiavi. Sviluppi futuri potrebbero
richiedere che una smart card contenga più coppie di chiavi, risulterebbe allora
necessaria la richiesta dell’alias.
Nella realizzazione di questo software, in realtà, è stata impiegata anche
un’altra classe: Start.java. Questa serve a simulare il programma esterno che
richiama i metodi delle classi “Firma” e “DigestFirmato”. Questa classe crea
inizialmente un digest di esempio da una immagine presente su disco, poi
richiama i metodi delle due classi precedentemente descritte per eseguire tutte
le operazioni necessarie.
Per eseguire la firma, allora, si scrive:
Firma firma = new Firma();
DigestFirmato df = firma.cifra(digest);
Per salvare la firma e il certificato su file:
df.serializza("c:\\fileTesi\\FirmaSerialized");
Quando invece si vuole decifrare un messaggio firmato bisogna prima
leggere il file ricevuto:
DigestFirmato df = new
DigestFirmato().deserializza("c:\\fileTesi\\FirmaSerialized");
poi si esegue la decifratura:
Firma firma = new Firma();
byte[] decifrato = firma.decifra(df);
Infine, per verificare che il messaggio sia integro, si confronta il digest
iniziale con quello appena ricavato:
firma.compara(decifrato, digest);
124
Realizzazione del progetto
Tool di gestione della smart card
Questo tool è uno strumento di uso generico che permette di eseguire
sulla smart card alcune operazioni che potrebbero essere utili in termini di
gestione, controllo e mantenimento del dispositivo. E’ dotato di una interfaccia a
riga di comando, quindi permette di interagire direttamente con l’utente.
L’utente, in questo caso, potrebbe essere l’amministratore del sistema oppure
un tecnico specializzato che deve accedere alla smart card, ad esempio, per
verificare se la procedura di inizializzazione è avvenuta correttamente, oppure
in seguito a malfunzionamenti.
Verrà ora proposta la stampa a schermo del menù principale di questo
tool e saranno brevemente discusse tutte le operazioni consentite.
IAIK JCE Provider for PKCS#11 operating with slot "GemPC410 0" of
module "PKCS#11 Cryptoki" from PKCS#11 library "gclib.dll"
Smart Card inserita.
Scegli l'operazione che vuoi eseguire:
1. Leggi il contenuto della scheda
2. Scrivi un oggetto sulla scheda
3. Cancella un oggetto dalla scheda
4. Inserisci una key entry da un altro key store
5. Elimina una key entry dal key store della scheda
->
La prima riga mostra alcune informazioni sul provider IAIK relative al
lettore attualmente collegato e alla libreria cui fa riferimento. In seguito viene
fatto un controllo per verificare che la smart card sia inserita, e quindi si
elencano le operazioni possibili. Come si può vedere è possibile leggere,
scrivere o cancellare gli oggetti della scheda e gestire il key store.
Selezionando l’opzione 1 si esegue la lettura della smart card. Durante la
procedura l’utente viene interrogato per indicare se vuole cercare un oggetto in
particolare (fornendo la sua label), oppure se vuole leggere tutto il contenuto
della scheda. Si richiede inoltre l’autenticazione tramite PIN per poter accedere
alla parte privata della memoria. In caso di mancata autenticazione sarà
possibile leggere solo il contenuto pubblico. Di seguito viene mostrato il video
relativo all’esecuzione della lettura della smart card impiegata nel presente
lavoro.
125
Capitolo 5
---------------SESSION INFO----------------State: Read-Only User Session
Device Error: 0x3039000
Read/Write Session: false
Serial Session: true
-----------END OF SESSION INFO-------------Trovati 3 oggetti.
Oggetto 1:
Object Class: <Attribute not present>
--------------------------------------------Oggetto 2:
Object Class: Certificate
Token: true
Private: false
Modifiable: true
Label: alias
Certificate Type: X.509 Public Key
Trusted: <Attribute not present>
Subject (DER, hex):
304e310b3009060355040613026974310b3009060355040813027374310a3008060355
040713016c310a3008060355040a13016f310b3009060355040b13026f75310d300b06
0355040313046e6f6d65
ID (hex): 0d7591bf774bb2432f047dac969aba268d2ad2b5
Issuer (DER, hex):
308185310b3009060355040613024954310b300906035504081302416e310f300d0603
5504071306416e636f6e613111300f060355040a13084a54656c656d6564310d300b06
0355040b1304536f66743111300f060355040313084a54656c656d6564312330210609
2a864886f70d01090116146a74656c656d6564406a74656c656d65642e6974
Serial Number (DER, hex): 12
Value (BER, hex):
30820243308201ac020112300d06092a864886f70d0101050500308185310b30090603
55040613024954310b300906035504081302416e310f300d06035504071306416e636f
6e613111300f060355040a13084a54656c656d6564310d300b060355040b1304536f66
743111300f060355040313084a54656c656d65643123302106092a864886f70d010901
16146a74656c656d6564406a74656c656d65642e6974301e170d303630323033313030
3032335a170d3038313132333130303032335a304e310b300906035504061302697431
0b3009060355040813027374310a3008060355040713016c310a3008060355040a1301
6f310b3009060355040b13026f75310d300b060355040313046e6f6d6530819f300d06
092a864886f70d010101050003818d0030818902818100b64c5f2e547e0f70d869824e
29a655daf614385135f1a722b4e500cf5051471cbe692586b4dff5d97852a5b1eaec11
d4241e4a0df3af694e20b648052170d9134248165e12e4337131f20f32eda154b1dca9
cab76b92680d18fd0c966c9efc609161a793ebc2bd8a7f081c4116ada19afd5b5bad52
1fb1aab36807cd17f366010203010001300d06092a864886f70d010105050003818100
2716657ce828fb5d4d4cfa2608360ab503f14c9d70ccfc164fdcb98a43fad274027e5a
3647e208a6acedece3bdbc634d72ea70935f47c4e7e57796c6eb27b6888d3947242654
539047a97b495e6c684ab23d606fd33cc9ebb039c59fd3372748046fab3badb53c4903
169fdf6906c205e7caf5956690e29482779351508a1118
--------------------------------------------Oggetto 3:
Object Class: Private Key
Token: true
Private: true
Modifiable: true
Label: alias
Key Type: RSA
ID: 0d7591bf774bb2432f047dac969aba268d2ad2b5
Start Date: <NULL_PTR>
End Date: <NULL_PTR>
Derive: false
Local: false
126
Realizzazione del progetto
Key Generation Mechanism: <Attribute not present>
Subject (DER, hex): <NULL_PTR>
Sensitive: true
Secondary Authentication: <Attribute not present>
Secondary Authentication PIN Flags: <Attribute not present>
Decrypt: true
Sign: true
Sign Recover: false
Unwrap: true
Extractable: false
Always Sensitive: true
Never Extractable: true
Modulus (hex):
b64c5f2e547e0f70d869824e29a655daf614385135f1a722b4e500cf5051471cbe6925
86b4dff5d97852a5b1eaec11d4241e4a0df3af694e20b648052170d9134248165e12e4
337131f20f32eda154b1dca9cab76b92680d18fd0c966c9efc609161a793ebc2bd8a7f
081c4116ada19afd5b5bad521fb1aab36807cd17f36601
Public Exponent (hex): 010001
Private Exponent (hex): <Value is sensitive>
Prime 1 (hex): <Value is sensitive>
Prime 2 (hex): <Value is sensitive>
Exponent 1 (hex): <Value is sensitive>
Exponent 2 (hex): <Value is sensitive>
Coefficient (hex): <Value is sensitive>
--------------------------------------------Tralasciando le informazioni (comunque fornite durante l’esecuzione del
programma) relative al lettore e alla scheda stessa, vengono riportare le
informazioni sulla sessione creata, che è di tipo Read-Only, e sull’effettivo
contenuto della scheda. In questo caso è stato fornito il PIN di autenticazione,
quindi è possibile leggere sia il contenuto pubblico che quello privato. Si
possono distinguere gli oggetti “certificato” e “chiave” relativi allo stesso alias.
Da notare che nella chiave privata compaiono le informazioni impostate nella
fase di generazione (in particolare “sensitive” e “unextractable”), ma non sono
visibili le informazioni riservate (riguardanti gli esponenti).
Il primo oggetto elencato, di cui non è definita la classe di appartenenza,
è in realtà un oggetto che contiene informazioni relative alle chiavi appena
create, ma che servono più alla smart card stessa che non all’utente, per
questo non vengono esplicitate. Questo oggetto, comunque, viene sempre
creato ogni volta che si genera una nuova coppia di chiavi.
Le operazioni di scrittura e cancellazione sono molto simili a quella
appena descritta, quindi si eviterà di riportare delle schermate di esempio. La
differenza principale sta nel fatto che questa volta bisogna accedere alla
scheda con una sessione di tipo Read-Write, quindi è obbligatorio fornire il PIN
127
Capitolo 5
di autenticazione. Brevemente, durante la scrittura si dovranno fornire: il
percorso del file che si vuole copiare sulla scheda e la label che si vuole
assegnare a tale file. Durante la cancellazione, invece, si leggeranno gli oggetti
presenti nella scheda e, per ognuno, sarà chiesto di confermare la
cancellazione.
La quarta operazione consente di aggiungere un elemento al key store
interno della smart card importandolo da un key store esterno. Questa
operazione è servita nel corso dello sviluppo del software per eseguire alcune
prove. Il suo impiego è più didattico che altro. A livello pratico non ha senso
generare una chiave con un dispositivo esterno per poi inserirla sulla smart
card, in quanto cade fin dal principio la caratteristica di non poter conoscere la
chiave al di fuori della scheda. Potrebbe essere utilizzato come test per
verificare il funzionamento della scheda, evitando di dover generare una nuova
chiave e interrogare una CA per avere un nuovo certificato. Il suo
funzionamento viene descritto direttamente dalla stampa dell’esecuzione del
programma, che risulta sufficientemente autoesplicativa.
Scrivi il percorso del file in cui si trova il key store
->c:\fileTesi\.keystore
Immettere la passphrase del key store
->password
Il keystore contiene i seguenti alias:
alias
cacert
cakey
matteo
Quale alias vuoi inserire nella scheda?
->matteo
Se questo alias è protetto con una propria passphrase immetterla,
altrimenti premere INVIO
->
Inserisci il PIN della Smart Card:
->1234
chiave e certificato inseriti sulla scheda.
Infine l’operazione di eliminazione di un elemento del key store è del tutto
simile alla cancellazione di un comune oggetto dalla scheda. Verrà chiesto il
PIN di autenticazione e saranno stampati tutti gli elementi del key store,
consentendo all’utente la facoltà di scegliere, tra questi, quale eliminare.
128
Conclusioni e sviluppi futuri
Capitolo 6.
CONCLUSIONI E SVILUPPI FUTURI
129
Capitolo 6
In questo lavoro si è cercato di rendere disponibili le tecnologie
informatiche, relative al campo della sicurezza, al sistema della pubblica
amministrazione e, nello specifico, all’ambito sanitario. Lo scopo è quello di
realizzare un sistema informatico che consenta di migliorare la velocità e
l’efficienza dei servizi, migliorare la gestione degli archivi, ridurre le pratiche
burocratiche cercando di sostituire il documento cartaceo con il documento
elettronico. Tutto questo garantendo i requisiti di sicurezza previsti in un
sistema informatico, che riguardano: l’autenticazione d’identità; la segretezza
delle informazioni; l’integrità dei dati; il non ripudio di una comunicazione.
Dopo
una
prima
fase
necessaria
all’acquisizione
dei
concetti
fondamentali che tali tecnologie impiegano (come crittografia, infrastrutture a
chiave pubblica e smart card), ho iniziato ad informarmi su progetti già avviati
riguardanti l’utilizzo delle smart card nella pubblica amministrazione e non
solo56. Mi sono reso conto che già da qualche anno questa tecnologia sta
trovando un utilizzo sempre più ampio, e sono molte anche le nuove proposte di
progetto. Ho notato però che gran parte di questi progetti riguardano iniziative
personali (di un ente o di una azienda) e sono limitati ad un campo di azione
localizzato. Esistono in realtà anche dei progetti a livello nazionale (è il caso
della CIE57 e della CNS58), che però non sono ancora completamente avviati e
quindi in fase di sviluppo.
Con questo progetto si intende raggiungere un ampio numero di utenti
(che comprende sia medici che pazienti), è quindi necessario adottare una
carta che sia disponibile a tutti già da subito. Questo mi ha portato a scegliere la
soluzione di impiegare una smart card vuota (le smart card, ormai, si trovano
facilmente in commercio) e renderla utilizzabile per le operazioni di firma
digitale. Una prima fase del lavoro, quindi, prevede l’inizializzazione della carta,
che si effettua creando al suo interno una coppia di chiavi ed associando ad
essa un certificato a chiave pubblica. La seconda fase, invece, si occupa di
realizzare e verificare la firma digitale del documento elettronico.
56
Alcuni di questi progetti sono citati nella parte introduttiva della tesi.
Carta di Identità Elettronica.
58
Carta Nazionale dei Servizi.
57
130
Conclusioni e sviluppi futuri
Durante lo sviluppo del lavoro è stato spesso utile accedere al contenuto
della smart card per verificare la corretta esecuzione delle operazioni, questo
ha portato all’implementazione di uno strumento ad interfaccia testuale che
consente di leggere e scrivere il contenuto della scheda e permette inoltre di
gestire il suo key store.
Attualmente questo progetto è più improntato verso l’uso di queste
tecniche da parte dei medici, si prevede però, una volta avviata una fase
sperimentale, di ampliare l’utenza anche ai pazienti che usufruiscono dei servizi
offerti dalla struttura sanitaria.
In questo scenario si potrebbe considerare di nuovo l’idea di impiegare la
CIE che, si presume, possa essere disponibile a tutti i cittadini, con il vantaggio
di poter disporre di un’unica smart card per accedere a diversi servizi.
Alcune considerazioni tecniche riguardano invece l’interoperabilità tra
diverse smart card. Al momento è possibile gestire solo un tipo di scheda, ma il
software è strutturato in modo da poter interagire con un dispositivo diverso
semplicemente cambiando una libreria. Questa operazione viene eseguita in
modo dinamico al runtime, si può allora prevedere di farla precedere da un
software di riconoscimento del dispositivo che scelga l’opportuna libreria.
Inoltre la smart card è momentaneamente dotata di una sola coppia di
chiavi (che per l’impiego attuale è più che sufficiente). Uno sviluppo del sistema,
però, (ed in particolare l’eventuale impiego della CIE) potrebbe richiedere la
presenza di più coppie di chiavi, eventualmente anche per usi diversi. Sarebbe
allora richiesto di selezionare la chiave voluta (tramite assegnazione dell’alias)
e verificarne l’utilizzo (cosa che già avviene per la firma), prima di eseguire
l’operazione.
Un’ultima considerazione riguarda il provider di sicurezza IAIK il cui
utilizzo non è completamente gratuito. Si può allora pensare, in linea con la
logica open source, di adottare il provider SUN in dotazione con le ultime
versioni del pacchetto Java, che è del tutto gratuito. Un’altra alternativa
potrebbe essere l’implementazione di un provider proprio. Si tratterebbe di
riscrivere le funzioni base utilizzando i metodi nativi Java per interfacciarsi alla
libreria della smart card. Questa soluzione è stata già presa in considerazione
ed alcune funzioni del wrapper sono già state realizzate.
131
Capitolo 6
132
Codice Java
Appendice.
CODICE JAVA
133
Appendice
Inizializzazione.java
package smart_card;
import iaik.asn1.CodingException;
import iaik.pkcs.pkcs11.Module;
import iaik.pkcs.pkcs11.Session;
import iaik.pkcs.pkcs11.Slot;
import iaik.pkcs.pkcs11.Token;
import iaik.pkcs.pkcs11.TokenException;
import iaik.pkcs.pkcs11.objects.RSAPrivateKey;
import iaik.pkcs.pkcs11.objects.RSAPublicKey;
import iaik.pkcs.pkcs11.provider.IAIKPkcs11;
import iaik.pkcs.pkcs11.provider.TokenManager;
import
iaik.pkcs.pkcs11.provider.keypairgenerators.PKCS11KeyPairGenerationSpe
c;
import iaik.pkcs.pkcs11.provider.spec.PKCS11Spec;
import iaik.pkcs.pkcs11.wrapper.PKCS11Exception;
import iaik.security.provider.IAIK;
import iaik.utils.Util;
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
java.io.BufferedReader;
java.io.FileInputStream;
java.io.FileWriter;
java.io.IOException;
java.io.InputStreamReader;
java.security.InvalidAlgorithmParameterException;
java.security.InvalidKeyException;
java.security.KeyPair;
java.security.KeyPairGenerator;
java.security.KeyStore;
java.security.KeyStoreException;
java.security.NoSuchAlgorithmException;
java.security.NoSuchProviderException;
java.security.PrivateKey;
java.security.SecureRandom;
java.security.Security;
java.security.SignatureException;
java.security.UnrecoverableKeyException;
java.security.cert.CertificateException;
java.security.cert.CertificateFactory;
java.security.cert.X509Certificate;
java.util.Collection;
java.util.Enumeration;
java.util.Properties;
import sun.misc.BASE64Encoder;
/*
* Questa classe genera la coppia di chiavi RSA e la
* richiesta di certificato PKCS#10 all'interno della
* smart card e successivamente inserisce il certificato
* sul key store della scheda.
*/
public class Inizializzazione {
private IAIKPkcs11 pkcs11Provider;
private TokenManager tokenManager;
private Module module;
134
Codice Java
private Token token;
String prompt = new String();
/*
* Il costruttore si occupa di installare i provider necessari
* e richiama il metodo di verifica della SC.
*/
public Inizializzazione() {
prompt = "->";
Security.addProvider(new IAIK());
Properties providerProperties = new Properties();
providerProperties.put("PKCS11_NATIVE_MODULE",
"gclib.dll");
pkcs11Provider = new IAIKPkcs11(providerProperties);
Security.addProvider(pkcs11Provider);
System.out.println(pkcs11Provider.getInfo()+"\n");
checkToken();
}
/*
* Verifica che la SC sia inserita.
*/
private void checkToken() {
try {
tokenManager = pkcs11Provider.getTokenManager();
module = tokenManager.getModule();
Slot[] slots = module.getSlotList(
Module.SlotRequirement.TOKEN_PRESENT);
if (slots.length == 0) {
System.out.println("Smart Card non presente o non
valida!");
System.exit(0);
}
System.out.println("Smart Card inserita.\n");
token = slots[0].getToken();
} catch(TokenException te) {
System.err.println("Smart Card non presente o non
valida!\n" + te);
}
}
/*
* Verifica se la SC necessita di un login
* ed esegue il login.
*/
private void checkLogin(Session s) {
try {
if (token.getTokenInfo().isLoginRequired()) {
if
(token.getTokenInfo().isProtectedAuthenticationPath()) {
System.out.println("Inserisci il PIN nella tastiera del tuo lettore
Smart Card.");
s.login(Session.UserType.USER, null);
} else {
System.out.println("Inserisci il PIN della Smart Card:");
System.out.print(prompt);
BufferedReader input = new
BufferedReader(
new
InputStreamReader(System.in));
String userPINString = input.readLine();
135
Appendice
if (userPINString.length() > 0) {
try {
s.login(Session.UserType.USER, userPINString.toCharArray());
} catch(PKCS11Exception pkcs11e) {
System.out.println("PIN
errato!");
System.exit(0);
}
}
}
}
System.out.println("");
} catch (TokenException te) {
System.err.println("Errore di comunicazione con la scheda!\n" + te);
System.exit(0);
} catch (IOException ioe) {
System.err.println("Errore di lettura dell'input!\n" + ioe);
}
}
/*
* Gernera una coppia di chiavi sulla smart card, associandole
* all'alias dato.
*/
public KeyPair generateKeyPair(String alias)
throws NoSuchAlgorithmException,
NoSuchProviderException,
InvalidAlgorithmParameterException {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(
"RSA", pkcs11Provider.getName());
SecureRandom random = new SecureRandom();
byte[] seed = random.generateSeed(20);
//imposto le proprietà della chiave privata
RSAPrivateKey priK = new RSAPrivateKey();
priK.getSign().setBooleanValue(Boolean.TRUE);
priK.getToken().setBooleanValue(Boolean.TRUE);
priK.getPrivate().setBooleanValue(Boolean.TRUE);
priK.getSensitive().setBooleanValue(Boolean.TRUE);
priK.getExtractable().setBooleanValue(Boolean.FALSE);
priK.getLabel().setCharArrayValue(alias.toCharArray());
priK.getId().setByteArrayValue(seed);
//imposto le proprietà della chiave pubblica
RSAPublicKey pubK = new RSAPublicKey();
pubK.getModulusBits().setLongValue(new Long(1024));
byte[] publicExponentBytes = {0x01, 0x00, 0x01};
pubK.getPublicExponent().setByteArrayValue(publicExponentBytes);
pubK.getVerify().setBooleanValue(Boolean.TRUE);
pubK.getToken().setBooleanValue(Boolean.TRUE);
pubK.getPrivate().setBooleanValue(Boolean.FALSE);
pubK.getLabel().setCharArrayValue(alias.toCharArray());
PKCS11KeyPairGenerationSpec keyPairSpec =
new PKCS11KeyPairGenerationSpec(tokenManager, pubK,
priK,
PKCS11Spec.USE_READ_WRITE_SESSION, PKCS11Spec.USE_USER_SESSION);
keyPairGen.initialize(keyPairSpec);
KeyPair keyPair = keyPairGen.generateKeyPair();
return keyPair;
}
/*
136
Codice Java
* Chiama i metodi per generare la coppia di chiavi e
* la richiesta di certificato e gestisce le loro eccezioni.
*/
public byte[] getCertReq(String alias, String dn) {
byte[] certReq = null;
java.security.KeyPair keyPair;
try {
keyPair = generateKeyPair(alias);
System.out.println("\n[CHIAVE PRIVATA]\n" +
keyPair.getPrivate().toString());
System.out.println("\n[CHIAVE PUBBLICA]\n" +
keyPair.getPublic().toString());
certReq = PKCS10CertificateRequest(dn, keyPair);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
System.out.println("Algoritmo mancante!");
} catch (NoSuchProviderException e) {
e.printStackTrace();
System.out.println("Provider mancante!");
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
System.out.println("Parametro dell'algoritmo non valido!");
} catch (InvalidKeyException e) {
e.printStackTrace();
System.out.println("Chiave non valida!");
} catch (SignatureException e) {
e.printStackTrace();
System.out.println("Errore nella firma della richiesta!");
} catch (CodingException e) {
e.printStackTrace();
System.out.println("Codifica non valida!");
}
return certReq;
}
/*
* Genera una richiesta di certificato nel formato standard
* PKCS#10.
*/
public byte[] PKCS10CertificateRequest(String dn,
java.security.KeyPair keyPair)
throws InvalidKeyException,
NoSuchAlgorithmException,
SignatureException,
CodingException {
javax.security.auth.x500.X500Principal x500Principal =
new javax.security.auth.x500.X500Principal(dn);
System.out.print(x500Principal.toString() + "\n");
iaik.asn1.structures.Name name = new
iaik.asn1.structures.Name(
x500Principal.getEncoded());
System.out.println(name.toString(true) + "\n");
iaik.pkcs.pkcs10.CertificateRequest request =
new iaik.pkcs.pkcs10.CertificateRequest(
keyPair.getPublic(), name);
request.sign(iaik.asn1.structures.AlgorithmID.sha1WithRSAEncryption,ke
yPair.getPrivate(), pkcs11Provider.getName());
System.out.println("\n[RICHIESTA DI CERTIFICATO]\n" +
request.toString());
return request.toByteArray();
}
137
Appendice
CSR
/*
* Prende il file inviato dalla CA come risposta alla PKCS#10
* e ne ricava la catena di certificazione,
* poi aggiunge la key entry sulla SC.
*/
public void setX509Cert(String alias, String fileName)
throws CertificateException,
IOException,
KeyStoreException,
NoSuchAlgorithmException,
UnrecoverableKeyException {
//crea la catena di certificati (chain)
FileInputStream fis = new FileInputStream(fileName);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Collection coll = cf.generateCertificates(fis);
Object[] arr = coll.toArray();
iaik.x509.X509Certificate[] chain = new
iaik.x509.X509Certificate[coll.size()];
System.out.println("\nLa catena presenta " + coll.size() + "
certificati");
for (int j=0; j<coll.size(); j++) {
if (arr[j] instanceof X509Certificate) {
X509Certificate cert = (X509Certificate)
arr[j];
chain[j] = new iaik.x509.X509Certificate(cert.getEncoded());
System.out.println((j+1) + "° elemento della catena:\n" + chain[j]);
}
}
Util.arrangeCertificateChain(chain, false);
//inserisce la nuova key entry sulla Smart Card
KeyStore tokenKeyStore;
tokenKeyStore = KeyStore.getInstance("PKCS11KeyStore");
if (tokenKeyStore == null) throw
new NullPointerException("KeyStore is null");
tokenKeyStore.load(null, null);
System.out.println("Keystore caricato");
Enumeration e = tokenKeyStore.aliases();
while (e.hasMoreElements()) {
System.out.println("\t" + e.nextElement());
}
PrivateKey priK = (PrivateKey) tokenKeyStore.getKey("alias", null);
tokenKeyStore.setKeyEntry("alias", priK, null, chain);
System.out.println("certificato caricato sulla scheda.");
}
/*
* Stampa la catena di certificazione del dato alias
* da smart card.
*/
private void printChain(String alias) {
try {
KeyStore tokenKeyStore = KeyStore.getInstance("PKCS11KeyStore");
if (tokenKeyStore == null)
throw new NullPointerException("KeyStore is null");
tokenKeyStore.load(null, null);
java.security.cert.Certificate[] chain =
tokenKeyStore.getCertificateChain(alias);
for (int i = 0; i < chain.length; i++) {
138
Codice Java
System.out.println("[" + i + "° ELEMENTO DELLA CATENA]\n" + chain[i]);
}
System.out.println("[Verifica catena]");
if (chain.length > 1) {
for (int i = 0; i < (chain.length - 1); i++) {
chain[i].verify(chain[i +
1].getPublicKey());
}
System.out.println("Catena verificata");
}
else if (chain.length == 1) {
System.out.println("Un solo elemento, niente da verificare.");
}
else if (chain.length == 0) {
System.out.println("Catena non presente, controllare la carta per
l'alias " + alias);
}
} catch (InvalidKeyException e) {
e.printStackTrace();
System.out.println("Catena NON verificata");
} catch (CertificateException e) {
e.printStackTrace();
System.out.println("Catena NON verificata");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
System.out.println("Algoritmo mancante");
} catch (NoSuchProviderException e) {
e.printStackTrace();
System.out.println("Provider mancante");
} catch (SignatureException e) {
e.printStackTrace();
System.out.println("Catena NON verificata");
} catch (KeyStoreException e) {
e.printStackTrace();
System.out.println("Errore di comunicazione con la Smart Card!");
} catch (IOException e) {
e.printStackTrace();
System.out.println("Errore nel caricamento del keystore!");
}
}
/*
* Crea le richieste di certificato PKCS#10,
* le codifica in BASE64 e le salva sul file "alias.csr".
* Al suo interno richiama un metodo per la
* generazione della coppia di chiavi.
*/
private void genReq() {
byte[] csr = getCertReq("alias", "CN=nome,OU=ou,O=o,L=l,ST=st,C=it");
BASE64Encoder enc = new BASE64Encoder();
String richiesta = "-----BEGIN CERTIFICATE REQUEST-----\n".concat(
enc.encode(csr).concat("\n-----END CERTIFICATE REQUEST-----\n"));
System.out.println(richiesta + "\n");
System.out.println("Salvataggio della richiesta su
file...");
try {
FileWriter fw = new FileWriter("c:\\fileTesi\\alias.csr");
fw.write(richiesta);
fw.close();
} catch (IOException e) {
e.printStackTrace();
139
Appendice
System.out.println("Errore nel salvataggio della richiesta!");
}
System.out.println("Salvato.");
}
/*
* Imposta la catena di certificazione sulla smart card.
*/
private void setChain() {
try {
setX509Cert("alias", "c:\\fileTesi\\alias.pem");
} catch (CertificateException e) {
e.printStackTrace();
System.out.println("Certificato non valido!");
} catch (KeyStoreException e) {
e.printStackTrace();
System.out.println("keystore non valido!");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
System.out.println("Algoritmo non valido!");
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
System.out.println("Impossibile prelevare la
chiave!");
} catch (IOException e) {
e.printStackTrace();
System.out.println("Errore nel caricamento del keystore!");
}
printChain("alias");
}
public static void main(String[] args) {
Inizializzazione sc = new Inizializzazione();
try {
Session session = sc.token.openSession(
Token.SessionType.SERIAL_SESSION,
Token.SessionReadWriteBehavior.RW_SESSION, null, null);
sc.checkLogin(session);
//sc.genReq(); //genera la CSR
//sc.setChain(); //imposta il certificato sulla SC
session.closeSession();
sc.module.finalize(null);
} catch (TokenException e) {
e.printStackTrace();
System.out.println("Errore nell'apertura o nella chiusura della
sessione!");
}
}
}
140
Codice Java
Firma.java
package smart_card;
import iaik.pkcs.pkcs11.Module;
import iaik.pkcs.pkcs11.Session;
import iaik.pkcs.pkcs11.Slot;
import iaik.pkcs.pkcs11.Token;
import iaik.pkcs.pkcs11.TokenException;
import iaik.pkcs.pkcs11.provider.IAIKPkcs11;
import iaik.pkcs.pkcs11.provider.TokenManager;
import iaik.pkcs.pkcs11.wrapper.PKCS11Exception;
import iaik.security.provider.IAIK;
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
java.io.BufferedReader;
java.io.IOException;
java.io.InputStreamReader;
java.security.InvalidKeyException;
java.security.KeyStore;
java.security.KeyStoreException;
java.security.NoSuchAlgorithmException;
java.security.NoSuchProviderException;
java.security.PrivateKey;
java.security.PublicKey;
java.security.Security;
java.security.UnrecoverableKeyException;
java.security.cert.Certificate;
java.security.cert.CertificateException;
java.security.cert.CertificateExpiredException;
java.security.cert.CertificateNotYetValidException;
java.security.cert.X509Certificate;
java.util.Arrays;
java.util.Date;
java.util.Enumeration;
java.util.Properties;
import
import
import
import
javax.crypto.BadPaddingException;
javax.crypto.Cipher;
javax.crypto.IllegalBlockSizeException;
javax.crypto.NoSuchPaddingException;
/*
* Questa classe contiene i metodi necessari per
* eseguire la firma digitale, decifrarla e verificarla.
*/
public class Firma {
private IAIKPkcs11 pkcs11Provider;
private Module module;
private Token token;
private Session session;
private PrivateKey priK;
private PublicKey pubK;
private X509Certificate x509;
String prompt = new String();
/*
* Il costruttore si occupa di installare i provider necessari.
*/
public Firma() {
prompt = "->";
141
Appendice
Security.addProvider(new IAIK());
Properties providerProperties = new Properties();
providerProperties.put("PKCS11_NATIVE_MODULE",
"gclib.dll");
pkcs11Provider = new IAIKPkcs11(providerProperties);
Security.addProvider(pkcs11Provider);
System.out.println(pkcs11Provider.getInfo()+"\n");
}
/*
* Verifica se la Smart Card è inserita,
* chiama i metodi necessari ad eseguire la cifratura
* e ritorna una istanza di "DigestFirmato" che contiene
* il messaggio cifrato ed il certificato x509.
*/
public DigestFirmato cifra(byte[] digest) {
checkToken();
try {
session = token.openSession(Token.SessionType.SERIAL_SESSION,
Token.SessionReadWriteBehavior.RO_SESSION, null, null);
checkLogin();
} catch (TokenException te) {
System.err.println("Errore nell'apertura della sessione!\n" + te);
System.exit(0);
}
estraiChiavi(null);
byte[] cifrato = null;
if (verificaUsoFirma(x509)) {
cifrato = eseguiCifra(digest);
} else System.exit(0);
DigestFirmato df = new DigestFirmato(cifrato, x509);
try {
session.closeSession();
module.finalize(null);
} catch (TokenException te) {
System.err.println("Errore nella chiusura della sessione!\n" + te);
System.exit(0);
}
return df;
}
/*
* Riceve una istanza di "DigestFirmato" dalla quale
* recupera il messaggio cifrato e il certificato x509,
* poi chiama il metodo di decifratura e ritorna il
* messaggio decifrato come array di byte.
*/
public byte[] decifra(DigestFirmato df) {
byte[] ricevuto = df.getFirma();
pubK = df.getCert().getPublicKey();
return eseguiDecifra(ricevuto);
}
/*
* Verifica che la SC sia inserita.
*/
private void checkToken() {
try {
TokenManager tokenManager = pkcs11Provider.getTokenManager();
module = tokenManager.getModule();
Slot[] slots = module.getSlotList(
142
Codice Java
Module.SlotRequirement.TOKEN_PRESENT);
if (slots.length == 0) {
System.out.println("Smart Card non presente o non valida!");
System.exit(0);
}
System.out.println("Smart Card inserita.\n");
token = slots[0].getToken();
} catch(TokenException te) {
System.err.println("Smart Card non presente o non valida!\n" + te);
}
}
/*
* Verifica se la SC necessita di un login
* ed esegue il login.
*/
private void checkLogin() {
try {
if (token.getTokenInfo().isLoginRequired()) {
if
(token.getTokenInfo().isProtectedAuthenticationPath()) {
System.out.println("Inserisci il PIN nella tastiera del tuo lettore
Smart Card.");
session.login(Session.UserType.USER,
null);
} else {
System.out.println("Inserisci il PIN della Smart Card:");
System.out.print(prompt);
BufferedReader input = new
BufferedReader(
new
InputStreamReader(System.in));
String userPINString = input.readLine();
if (userPINString.length() > 0) {
try {
session.login(Session.UserType.USER, userPINString.toCharArray());
} catch(PKCS11Exception pkcs11e) {
System.out.println("PIN
errato!");
System.exit(0);
}
}
}
}
System.out.println("");
} catch (TokenException te) {
System.err.println("Errore di comunicazione con la scheda!\n" + te);
System.exit(0);
} catch (IOException ioe) {
System.err.println("Errore di lettura dell'input!\n" + ioe);
}
}
/*
* Preleva la chiave privata e il certificato
* della prima key entry che trova sulla smart card.
* Prende come parametro la password del key store.
*/
private void estraiChiavi(char[] pass) {
try {
143
Appendice
System.out.println("Prelevo le chiavi dalla Smart Card...");
KeyStore tokenKeyStore = KeyStore.getInstance("PKCS11KeyStore");
if (tokenKeyStore == null) throw
new NullPointerException("KeyStore non
trovato!");
tokenKeyStore.load(null, null);
if (tokenKeyStore.size() == 0) {
System.out.println("Il key store è vuoto!");
System.exit(0);
}
else {
Enumeration aliases = tokenKeyStore.aliases();
while (aliases.hasMoreElements()) {
String alias = aliases.nextElement().toString();
System.out.println(alias);
if (tokenKeyStore.isKeyEntry(alias)) {
priK = (PrivateKey) tokenKeyStore.getKey(alias, pass);
Certificate[] certs = tokenKeyStore.getCertificateChain(alias);
if (certs == null || certs.length == 0) {
x509 = (X509Certificate) tokenKeyStore.getCertificate(alias);
} else {
x509 = (X509Certificate)
certs[0];
}
break;
}
}
if (x509 == null) {
System.out.println("Certificato non trovato!");
System.exit(0);
} else verificaCert();
}
} catch (KeyStoreException kse) {
System.err.println("Errore nell'accesso al key store!\n" + kse);
System.exit(0);
} catch (CertificateException ce) {
System.err.println("Errore nel caricamento del key store!\n" + ce);
System.exit(0);
} catch (IOException ioe) {
System.err.println("Errore nel caricamento del key store!\n" + ioe);
System.exit(0);
} catch (NoSuchAlgorithmException nsae) {
System.err.println("Errore nell'estrazione della chiave privata:
algoritmo sconosciuto!\n" + nsae);
System.exit(0);
} catch (UnrecoverableKeyException uke) {
System.err.println("Errore nell'estrazione della chiave privata!\n" +
uke);
System.exit(0);
}
}
/*
* Verifica la validità temporale del certificato.
*/
private void verificaCert() {
Date data = new Date();
try {
x509.checkValidity(data);
} catch (CertificateExpiredException cee) {
144
Codice Java
System.err.println("Certificato scaduto!\n" + cee);
System.exit(0);
} catch (CertificateNotYetValidException cnyve) {
System.err.println("Certificato nona ancora valido!\n" + cnyve);
System.exit(0);
}
}
/*
* Esegue la cifratura del digest con l'algoritmo RSA.
* Tale operazione avviene all'interno della Smart Card,
* per questo è necessario assegnare il provider
"pkcs11provider".
*/
private byte[] eseguiCifra(byte[] digest) {
byte[] cifrato = null;
try {
System.out.println("\nCifratura in corso...");
Cipher c = Cipher.getInstance("RSA/ECB/PKCS1Padding",
pkcs11Provider.getName());
c.init(Cipher.ENCRYPT_MODE, priK);
cifrato = c.doFinal(digest);
System.out.println("...cifratura eseguita.");
} catch (NoSuchProviderException nspe) {
System.err.println("Errore nella cifratura: provider sconosciuto!\n" +
nspe);
System.exit(0);
} catch (NoSuchAlgorithmException nsae) {
System.err.println("Errore nella cifratura: algoritmo sconosciuto!\n"
+ nsae);
System.exit(0);
} catch (NoSuchPaddingException nspe) {
System.err.println("Errore nella cifratura: padding sconosciuto!\n" +
nspe);
System.exit(0);
} catch (InvalidKeyException ike) {
System.err.println("Errore nella cifratura: chiave privata non
valida!\n" + ike);
System.exit(0);
} catch (IllegalStateException ise) {
System.err.println("Errore nella cifratura: stato non valido!\n" +
ise);
System.exit(0);
} catch (IllegalBlockSizeException ibse) {
System.err.println("Errore nella cifratura: dimensione del blocco non
valida!\n" + ibse);
System.exit(0);
} catch (BadPaddingException bpe) {
System.err.println("Errore nella cifratura: problemi nel padding!\n" +
bpe);
System.exit(0);
}
return cifrato;
}
/*
* Decifra il messaggio ottenendo di nuovo il digest.
* Per la decifratura non è necessaria la Smart Card,
* infatti viene assegnato il provider "IAIK".
*/
145
Appendice
private byte[] eseguiDecifra(byte[] cifrato) {
byte[] decifrato = null;
try {
System.out.println("\nDecifratura in corso...");
Cipher c = Cipher.getInstance("RSA/ECB/PKCS1Padding", "IAIK");
c.init(Cipher.DECRYPT_MODE, pubK);
decifrato = c.doFinal(cifrato);
System.out.println("...decifratura eseguita.");
} catch (NoSuchProviderException nspe) {
System.err.println("Errore nella decifratura: provider sconosciuto!\n"
+ nspe);
System.exit(0);
} catch (NoSuchAlgorithmException nsae) {
System.err.println("Errore nella decifratura: algoritmo
sconosciuto!\n" + nsae);
System.exit(0);
} catch (NoSuchPaddingException nspe) {
System.err.println("Errore nella decifratura: padding sconosciuto!\n"
+ nspe);
System.exit(0);
} catch (InvalidKeyException ike) {
System.err.println("Errore nella decifratura: chiave privata non
valida!\n" + ike);
System.exit(0);
} catch (IllegalStateException ise) {
System.err.println("Errore nella decifratura: stato non valido!\n" +
ise);
System.exit(0);
} catch (IllegalBlockSizeException ibse) {
System.err.println("Errore nella decifratura: dimensione del blocco
non valida!\n" + ibse);
System.exit(0);
} catch (BadPaddingException bpe) {
System.err.println("Errore nella decifratura: problemi nel padding!\n"
+ bpe);
System.exit(0);
}
return decifrato;
}
/*
* Confronta il digest iniziale con quello ricavato dalla
* decifratura.
*/
public void compara(byte arr1[], byte arr2[]) {
if (arr1.length!=0 & arr2.length!=0) {
if (Arrays.equals(arr1, arr2)) System.out.println("\nI due digest
coincidono.");
else System.out.println("\nI digest sono diversi! Il messaggio è stato
modificato!");
}
else System.out.println("Uno dei due array è vuoto!");
}
/*
* Verifica che il certificato sia utilizzabile per le
operazioni
* di firma e cifratura.
*/
private boolean verificaUsoFirma(X509Certificate cert) {
System.out.println("Verifico l'utilizzo delle chiavi...");
146
Codice Java
}
}
boolean[] uso = cert.getKeyUsage();
if (uso == null || uso[0] || uso[3]) {
System.out.println("...operazione consentita.");
return true;
}
else {
System.out.println("...operazione non consentita!");
return false;
}
147
Appendice
DigestFirmato.java
package smart_card;
import
import
import
import
import
import
java.io.FileInputStream;
java.io.FileOutputStream;
java.io.IOException;
java.io.ObjectInputStream;
java.io.ObjectOutputStream;
java.security.cert.X509Certificate;
/*
* Questa classe rappresenta il documento firmato che
* viene inviato nella trasmissione.
*/
public class DigestFirmato {
byte[] firma = null;
X509Certificate x509cert;
public DigestFirmato() {
}
public DigestFirmato(byte[] cifrato, X509Certificate x509) {
this.firma = cifrato;
this.x509cert = x509;
}
public byte[] getFirma() {
return firma;
}
public X509Certificate getCert() {
return x509cert;
}
+ e);
/*
* Salva il messaggio cifrato e il certificato x509 su file
* in forma serializzata.
*/
public void serializza(String filename) {
try {
System.out.println("\nSerializzazione...");
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream(filename));
oos.writeObject(firma);
oos.writeObject(x509cert);
oos.close();
System.out.println("messaggio spedito.");
} catch(Exception e) {
System.err.println("Errore nella serializzazione!\n"
}
}
System.exit(0);
/*
* Recupera il messaggio cifrato e il certificato x509 da file
* e ritorna una istanza di "DigestFirmato".
*/
148
Codice Java
public DigestFirmato deserializza(String filename) {
DigestFirmato df = new DigestFirmato();
try {
System.out.println("\nDeserializzazione...");
ObjectInputStream ois = new ObjectInputStream(
new FileInputStream(filename));
df.firma = (byte[]) ois.readObject();
df.x509cert = (X509Certificate) ois.readObject();
System.out.println("messaggio ricevuto.");
ois.close();
} catch(IOException ioe) {
System.err.println("Errore nella deserializzazione!\n" + ioe);
System.exit(0);
} catch (ClassNotFoundException cnfe) {
System.err.println("Dato non valido!\n" + cnfe);
System.exit(0);
}
return df;
}
}
149
Appendice
Start.java
package smart_card;
import
import
import
import
import
import
java.io.ByteArrayOutputStream;
java.io.FileInputStream;
java.io.FileNotFoundException;
java.io.IOException;
java.security.MessageDigest;
java.security.NoSuchAlgorithmException;
/*
* Questa classe richiama i metodi di "Firma" e "DigestFirmato"
* per eseguire le operazioni di cifratura e decifratura.
*/
public class Start {
/*
* Crea un Message Digest da un file utilizzando
* l'algoritmo SHA-1
*/
public byte[] creaDigest(String fileName) {
byte[] digest = null;
try {
System.out.println("\nCreo il Message Digest dal file \"" + fileName +
"\"...");
FileInputStream fis = new FileInputStream(fileName);
ByteArrayOutputStream baos = new
ByteArrayOutputStream(256);
byte[] buffer = new byte[256];
int bytesRead;
while ((bytesRead = fis.read(buffer)) >= 0) {
baos.write(buffer, 0, bytesRead);
}
fis.close();
MessageDigest md = MessageDigest.getInstance("SHA1");
md.update(baos.toByteArray());
digest = md.digest();
} catch (FileNotFoundException fnfe) {
System.err.println("Errore nella creazione del Digest: file non
trovato!\n" + fnfe);
System.exit(0);
} catch (IOException ioe) {
System.err.println("Errore nella lettura del file!\n" + ioe);
System.exit(0);
} catch (NoSuchAlgorithmException nsae) {
System.err.println("Errore nella creazione del Digest: algoritmo
sconosciuto!\n" + nsae);
System.exit(0);
}
return digest;
}
public static void main(String[] args) {
Start start = new Start();
byte[] digest =
start.creaDigest("c:\\fileTesi\\immagine.jpg");
System.out.println("Digest:\n" + new String(digest));
150
Codice Java
Firma firma = new Firma();
//DigestFirmato df = firma.cifra(digest); //esegue la cifratura del
digest
//df.serializza("c:\\fileTesi\\FirmaSerialized"); //salva il digest
cifrato e il cert x509 su file
DigestFirmato df = new DigestFirmato().deserializza(
"c:\\fileTesi\\FirmaSerialized"); //recupera le informazioni dal file
byte[] decifrato = firma.decifra(df); //decifra il messaggio ottenendo
di nuovo il digest
firma.compara(decifrato, digest); //confronta i due digest
}
}
151
Appendice
SmartCardHandler.java
package smart_card;
import
import
import
import
import
import
import
import
import
import
import
iaik.pkcs.pkcs11.Module;
iaik.pkcs.pkcs11.Session;
iaik.pkcs.pkcs11.Slot;
iaik.pkcs.pkcs11.Token;
iaik.pkcs.pkcs11.TokenException;
iaik.pkcs.pkcs11.objects.Data;
iaik.pkcs.pkcs11.objects.Object;
iaik.pkcs.pkcs11.provider.IAIKPkcs11;
iaik.pkcs.pkcs11.provider.TokenManager;
iaik.pkcs.pkcs11.wrapper.PKCS11Exception;
iaik.security.provider.IAIK;
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
java.io.BufferedReader;
java.io.ByteArrayOutputStream;
java.io.FileInputStream;
java.io.FileNotFoundException;
java.io.IOException;
java.io.InputStream;
java.io.InputStreamReader;
java.security.KeyStore;
java.security.KeyStoreException;
java.security.PrivateKey;
java.security.Security;
java.security.cert.Certificate;
java.util.Arrays;
java.util.Enumeration;
java.util.Hashtable;
java.util.Properties;
/*
* Questo è un tool di gestione della Smart Card.
* E' dotato di una interfaccia testuale ed
* è in grado di leggere, scrivere e cancellare oggetti
* all'interno della Smart Card.
* Permette anche di gestire il key store della scheda
* aggiungendo entries provenienti da altri key store
* o cancellando quelle già presenti.
*/
public class SmartCardHandler {
private IAIKPkcs11 pkcs11Provider;
private Module module;
private Slot[] slots;
private Token token;
String prompt = new String();
/*
* Il costruttore si occupa di installare i provider
* necessari e chiama il metodo iniziale.
*/
public SmartCardHandler() {
prompt = "->";
Security.addProvider(new IAIK());
Properties providerProperties = new Properties();
providerProperties.put("PKCS11_NATIVE_MODULE",
"gclib.dll");
152
Codice Java
}
pkcs11Provider = new IAIKPkcs11(providerProperties);
Security.addProvider(pkcs11Provider);
System.out.println(pkcs11Provider.getInfo()+"\n");
checkToken();
mainFrame();
/*
* Verifica che la SC sia inserita.
* E' il primo metodo chiamato dal costruttore.
*/
private void checkToken() {
try {
TokenManager tokenManager = pkcs11Provider.getTokenManager();
module = tokenManager.getModule();
slots = module.getSlotList(
Module.SlotRequirement.TOKEN_PRESENT);
if (slots.length == 0) {
System.out.println("Smart Card non presente o non valida!");
System.exit(0);
}
System.out.println("Smart Card inserita.\n");
token = slots[0].getToken();
} catch(TokenException te) {
System.err.println("Smart Card non presente o non valida!\n" + te);
}
}
/*
* E' il menù principale in cui si sceglie l'operazione da
eseguire.
*/
private void mainFrame() {
BufferedReader in = new BufferedReader(
new InputStreamReader(System.in));
System.out.println("Scegli l'operazione che vuoi
eseguire:");
System.out.println("\t1. Leggi il contenuto della scheda");
System.out.println("\t2. Scrivi un oggetto sulla scheda");
System.out.println("\t3. Cancella un oggetto dalla
scheda");
System.out.println("\t4. Inserisci una key entry da un altro key
store");
System.out.println("\t5. Elimina una key entry dal key store della
scheda");
String op = new String();
try {
do {
System.out.print(prompt);
op = in.readLine();
} while (!(op.equals("1") || op.equals("2") || op.equals("3") ||
op.equals("4") || op.equals("5")));
switch (Integer.parseInt(op)) {
case 1:
preparaLettura();
break;
case 2:
preparaScrittura();
break;
case 3:
preparaCancella();
153
Appendice
break;
case 4:
preparaInserisci();
break;
case 5:
eliminaKeyEntry();
break;
}
} catch (IOException ioe) {
System.err.println("Errore di lettura dell'input da consolle!\n" +
ioe);
System.exit(0);
}
}
/*
* Raccoglie le informazioni necessarie per l'operazione
* di lettura dalla scheda.
*/
private void preparaLettura() throws IOException {
System.out.println("Scrivi il nome dell'oggetto che vuoi leggere.");
System.out.println("(premi INVIO per leggere tutto il contenuto della
scheda)");
System.out.print(prompt);
BufferedReader in = new BufferedReader(
new InputStreamReader(System.in));
String leggi = in.readLine();
leggiSC(leggi);
}
/*
* Raccoglie le informazioni necessarie per l'operazione
* di scrittura sulla scheda.
*/
private void preparaScrittura() throws IOException {
String[] scrivi = new String[2];
BufferedReader in = new BufferedReader(
new InputStreamReader(System.in));
do {
System.out.println("Scrivi il nome del file che vuoi copiare sulla
scheda");
System.out.print(prompt);
scrivi[0] = in.readLine();
} while(scrivi[0].equals(""));
do {
System.out.println("Scrivi la label che vuoi assegnare all'oggetto");
System.out.print(prompt);
scrivi[1] = in.readLine();
} while(scrivi[1].equals(""));
scriviSC(scrivi);
}
/*
* Raccoglie le informazioni necessarie per l'operazione
* di cancellazione di un oggetto dalla scheda.
*/
private void preparaCancella() throws IOException {
BufferedReader in = new BufferedReader(
new InputStreamReader(System.in));
System.out.println("Scrivi la label dell'oggetto che vuoi
cancellare");
154
Codice Java
System.out.println("(premi INVIO se vuoi visualizzare tutti gli
oggetti)");
System.out.print(prompt);
String canc = in.readLine();
cancellaSC(canc);
}
/*
* Raccoglie le informazioni necessarie per l'operazione
* di inserimento di una nuova key entry
* sul key store della scheda.
*/
public void preparaInserisci() throws IOException {
BufferedReader in = new BufferedReader(
new InputStreamReader(System.in));
String filename = new String();
do {
System.out.println("Scrivi il percorso del file in cui si trova il key
store");
System.out.print(prompt);
filename = in.readLine();
} while (filename.equals(""));
System.out.println("Immettere la passphrase del key
store");
System.out.print(prompt);
char[] pass = in.readLine().toCharArray();
KeyStore ks = caricaKeyStore(filename, pass);
String alias = new String();
while (true) {
do {
System.out.println("Quale alias vuoi inserire nella scheda?");
System.out.print(prompt);
alias = in.readLine();
} while (alias.equals(""));
if (verificaAlias(alias, ks)) break;
else System.out.println("Alias non valido!");
}
System.out.println("Se questo alias è protetto con una propria
passphrase immetterla, altrimenti premere INVIO");
System.out.print(prompt);
String answer = in.readLine();
if (!(answer.equals(""))) pass = answer.toCharArray();
inserisci(alias, ks, pass);
}
/*
* Carica il key store situato su disco all'indirizzo dato.
*/
private KeyStore caricaKeyStore(String filename, char[] pass) {
KeyStore ks = null;
try {
ks = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream fis = new FileInputStream(filename);
ks.load(fis, pass);
if (ks.size() != 0) {
String elenco[] = new String[ks.size()];
Enumeration e = ks.aliases();
for (int i=0; i<ks.size(); i++) {
elenco[i] = (String) e.nextElement();
}
Arrays.sort(elenco);
155
Appendice
System.out.println("Il keystore contiene i seguenti alias:");
for (int j=0; j<elenco.length; j++) {
System.out.println("\t" + elenco[j]);
}
}
else {
System.out.println("Il keystore è vuoto!");
}
} catch (FileNotFoundException fnfe) {
System.err.println("File non trovato!\n" + fnfe);
System.exit(0);
} catch (Exception e) {
System.err.println("Errore nel caricamento del key store!\n" + e);
System.exit(0);
}
return ks;
}
/*
* Inserisce la nuova key entry sulla Smart Card.
* L'alias, il key store e la password ricevuti
* si riferiscono al key store di origine (quello su disco).
*/
private void inserisci(String alias, KeyStore ks, char[] pass) {
try {
Session sess = openSession(1);
checkLogin(sess);
PrivateKey priK = (PrivateKey) ks.getKey(alias,
pass);
Certificate[] certs = ks.getCertificateChain(alias);
KeyStore tokenKeyStore = KeyStore.getInstance("PKCS11KeyStore");
if (tokenKeyStore == null) throw
new NullPointerException("KeyStore non
trovato!");
tokenKeyStore.load(null, null);
System.out.println("inserisco la key entry");
tokenKeyStore.setKeyEntry(alias, priK, null, certs);
System.out.println("chiave e certificato inseriti sulla scheda.");
closeSession(sess);
} catch (Exception e) {
System.err.println("Errore nell'operazione di inserimento!\n" + e);
System.exit(0);
}
}
/*
* Legge il contenuto del key store della scheda e
* chiede quale entry si vuole eliminare.
*/
public void eliminaKeyEntry() {
try {
Session sess = openSession(1);
checkLogin(sess);
KeyStore tokenKeyStore = KeyStore.getInstance("PKCS11KeyStore");
if (tokenKeyStore == null) throw
new NullPointerException("KeyStore non
trovato!");
tokenKeyStore.load(null, null);
if (tokenKeyStore.size() == 0) {
System.out.println("Il key store è vuoto!");
System.exit(0);
156
Codice Java
} else {
System.out.println("Il keystore contiene i seguenti elementi:");
Enumeration e = tokenKeyStore.aliases();
while (e.hasMoreElements()) {
System.out.println("\t" +
e.nextElement());
}
BufferedReader in = new BufferedReader(
new InputStreamReader(System.in));
String alias = new String();
while (true) {
do {
System.out.println("Quale entry
vuoi eliminare?");
System.out.println(prompt);
alias = in.readLine();
} while (alias.equals(""));
if (verificaAlias(alias, tokenKeyStore))
{
tokenKeyStore.deleteEntry(alias);
System.out.println("key entry
eliminata!");
break;
} else System.out.println("Alias non
valido!");
}
closeSession(sess);
module.finalize(null);
}
} catch (TokenException te) {
System.err.println("Errore nell'apertura o nella chiusura della
sessione!\n" + te);
System.exit(0);
} catch (Exception e) {
System.err.println("Errore nell'operazione di eliminazione!\n" + e);
System.exit(0);
}
}
/*
* Ritorna true se l'alias dato appartiene al dato key store.
*/
public boolean verificaAlias(String alias, KeyStore ks) {
boolean answer = false;
try {
Enumeration e = ks.aliases();
while (e.hasMoreElements()) {
if (alias.equals(e.nextElement())) {
answer = true;
break;
}
}
} catch (KeyStoreException kse) {
System.err.println("Errore nella lettura del key store!\n" + kse);
System.exit(0);
}
return answer;
}
/*
* Stampa a video il contenuto della Smart Card.
157
Appendice
* Il parametro "leggi" rappresenta la label dell'oggetto
* da leggere. Se è NULL viene letto tutto il
* contenuto della scheda.
*/
private void leggiSC(String leggi) {
try {
printSlotInfo(slots[0]);
printTokenInfo();
Session sess = openSession(0);
checkLogin(sess);
printSessionInfo(sess);
Object[] obj = readFromCard(leggi, sess);
if (obj.length > 0) {
System.out.println("\nTrovati " + obj.length + " oggetti.");
for (int i=0; i<obj.length; i++) {
System.out.println("Oggetto " + (i+1) +
": ");
System.out.println(obj[i]);
System.out.println("---------------------------------------------");
}
System.out.println("---------------------------------------------");
} else {
System.out.println("Nessun oggetto trovato sulla Smart Card.");
}
closeSession(sess);
module.finalize(null);
} catch (TokenException te) {
System.err.println("Errore in lettura: impossibile comunicare con la
scheda!\n" + te);
System.exit(0);
}
}
/*
* Esegue l'effettiva lettura della scheda.
*/
private Object[] readFromCard(String label, Session session)
throws TokenException {
Data data = new Data();
if (label.equals("")) {
data = null;
} else {
data.getLabel().setCharArrayValue(label.toCharArray());
}
session.findObjectsInit(data);
Object[] foundObjects = session.findObjects(20);
session.findObjectsFinal();
return foundObjects;
}
/*
* Scrive un oggetto sulla Smart Card.
* L'array "scrivi" contiene l'indirizzo del file
* di origine e la label da assegnare all'oggetto.
*/
private void scriviSC(String[] scrivi) {
try {
Session sess = openSession(1);
checkLogin(sess);
printSessionInfo(sess);
158
Codice Java
System.out.println("Lettura dal file sorgente...");
byte[] buffer = readFile(scrivi[0]);
System.out.println("Scrittura sulla Smart Card...");
writeToCard(scrivi[1], buffer, sess);
closeSession(sess);
module.finalize(null);
System.out.println("File copiato sulla scheda.");
} catch (TokenException te) {
System.err.println("Errore in scrittura: impossibile comunicare con la
scheda!\n" + te);
System.exit(0);
}
}
/*
* Cancella un oggetto dalla Smart Card.
* Il parametro "canc" contiene la label dell'oggetto
* che si vuole cancellare.
*/
private void cancellaSC(String canc) {
try {
Session sess = openSession(1);
checkLogin(sess);
printSessionInfo(sess);
Object[] obj = readFromCard(canc, sess);
if (obj.length > 0) {
for (int i=0; i<obj.length; i++) {
deleteObject(obj[i], sess);
}
}
closeSession(sess);
module.finalize(null);
} catch (TokenException te) {
System.err.println("Errore in cancellazione: impossibile comunicare
con la scheda!\n" + te);
System.exit(0);
} catch (IOException ioe) {
System.err.println("Errore di lettura dell'input da consolle!\n" +
ioe);
System.exit(0);
}
}
/*
* Esegue l'effettiva scrittura sulla scheda.
*/
private void writeToCard(String label, byte[] data, Session session)
throws TokenException {
Data dataObjectTemplate = new Data();
dataObjectTemplate.getLabel().setCharArrayValue(label.toCharArra
y());
dataObjectTemplate.getValue().setByteArrayValue(data);
dataObjectTemplate.getToken().setBooleanValue(Boolean.TRUE);
session.createObject(dataObjectTemplate);
}
/*
* Legge da disco il file che dovrà essere
* copiato sulla scheda.
*/
159
Appendice
private byte[] readFile(String filename) {
byte[] data = null;
try {
InputStream dataInputStream = new
FileInputStream(filename);
ByteArrayOutputStream bufferStream = new ByteArrayOutputStream(256);
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = dataInputStream.read(buffer)) >=
0) {
bufferStream.write(buffer, 0, bytesRead);
}
dataInputStream.close();
data = bufferStream.toByteArray();
bufferStream.close();
} catch (FileNotFoundException fnfe) {
System.err.println("File non trovato!\n" + fnfe);
System.exit(0);
} catch (IOException ioe) {
System.err.println("Errore nella lettura del file!\n" + ioe);
System.exit(0);
}
return data;
}
/*
* Esegue l'effettiva cancellazione dell'oggetto
* dalla Smart Card.
*/
private void deleteObject(Object obj, Session session)
throws TokenException, IOException {
BufferedReader in = new BufferedReader(
new InputStreamReader(System.in));
Hashtable objectHandleToObject = new Hashtable(1);
long objectHandle = obj.getObjectHandle();
objectHandleToObject.put(new Long(objectHandle), obj);
Long selectedObjectHandle = new Long(
Long.toString(obj.getObjectHandle()));
Object selectedObject = (Object)
objectHandleToObject.get(selectedObjectHandle);
System.out.println("\nOggetto:");
System.out.println(obj);
String answer;
do {
System.out.println("Sei sicuro di voler CANCELLARE questo oggetto?
[yes/no] ");
System.out.print(prompt);
answer = in.readLine();
} while(!(answer.equalsIgnoreCase("yes") ||
answer.equalsIgnoreCase("no")));
if (answer.equalsIgnoreCase("yes")) {
session.destroyObject(selectedObject);
System.out.println("Oggetto eliminato!");
}
}
/*
* Verifica se la SC necessita di un login
* ed esegue il login.
*/
private void checkLogin(Session s) {
160
Codice Java
try {
if (token.getTokenInfo().isLoginRequired()) {
if
(token.getTokenInfo().isProtectedAuthenticationPath()) {
System.out.println("Inserisci il PIN nella tastiera del tuo lettore
Smart Card.");
s.login(Session.UserType.USER, null);
} else {
System.out.println("Inserisci il PIN della Smart Card:");
System.out.print(prompt);
BufferedReader input = new
BufferedReader(
new
InputStreamReader(System.in));
String userPINString = input.readLine();
if (userPINString.length() > 0) {
try {
s.login(Session.UserType.USER, userPINString.toCharArray());
} catch(PKCS11Exception pkcs11e) {
System.out.println("PIN
errato!");
System.exit(0);
}
}
}
}
System.out.println("");
} catch (TokenException te) {
System.err.println("Errore di comunicazione con la scheda!\n" + te);
System.exit(0);
} catch (IOException ioe) {
System.err.println("Errore di lettura dell'input!\n"
+ ioe);
}
}
/*
* Apre una sessione con la Smart Card.
* Il parametro "tipo" è un intero che determina il tipo
* di sesione da aprire:
* 0 = read only; 1 = read write.
*/
private Session openSession(int tipo) {
Session sess = null;
try {
switch(tipo) {
case 0:
sess = token.openSession(Token.SessionType.SERIAL_SESSION,
Token.SessionReadWriteBehavior.RO_SESSION, null, null);
break;
case 1:
sess = token.openSession(Token.SessionType.SERIAL_SESSION,
Token.SessionReadWriteBehavior.RW_SESSION, null, null);
break;
}
} catch (TokenException te) {
System.err.println("Errore nell'apertura della sessione!\n" + te);
System.exit(0);
}
return sess;
}
161
Appendice
/*
* Chiude la sessione.
*/
private void closeSession(Session session) {
try {
session.closeSession();
} catch (TokenException te) {
System.err.println("Errore nella chiusura della sessione!\n" + te);
System.exit(0);
}
}
/*
* Stampa a schermo le informazioni sulla sessione.
*/
private void printSessionInfo(Session session) throws
TokenException {
System.out.println("---------------SESSION INFO----------------");
System.out.println(session.getSessionInfo());
System.out.println("-----------END OF SESSION INFO----------");
}
--");
--");
--");
--");
/*
* Stampa a schermo le informazioni sul lettore.
*/
private void printSlotInfo(Slot slot) throws TokenException {
System.out.println("---------------SLOT INFO--------------System.out.println(slot.getSlotInfo());
System.out.println("-------------END OF SLOT INFO---------}
/*
* Stampa a schermo le informazioni sulla Smart Card.
*/
private void printTokenInfo() throws TokenException {
System.out.println("---------------TOKEN INFO-------------System.out.println(token.getTokenInfo());
System.out.println("-------------END OF TOKEN INFO--------}
public static void main(String[] args) {
SmartCardHandler prova = new SmartCardHandler();
}
}
162
Bibliografia
Bibliografia
Bruce Heckel “Thinking in Java Second Edition”, President, MindView, Inc. pubblicato
da “Prentice Hall PTR”, anno di pubblicazione 2000.
Claudio De Sio Cesari “Il linguaggio Object Oriented Java Seconda Edizione”,
www.claudiodesio.com
Massimiliano Tarquini “Java mattone dopo mattone” versione 0.1.8, anno di
pubblicazione 2001, www.java-net.tv
Franco Guidi Polanco “GoF’s Design Patterns in Java”, Politecnico di Torino, anno di
pubblicazione 2002, www.cim.polito.it
Scott Oaks “Java Security Second Edition”, pubblicato da “O’Reilly”.
Jonathan Knudsen “ Java Cryptography, Enigna of Estoeric Nothingness”, pubblicato
da “O’Reilly”, anno di pubblicazione 1998.
“Java Card System Protection Profile Collection”, versione 1.0b pubblicato da “Sun
Microsystem, Inc”, anno di pubblicazione 2003.
Kris Jamsa “Hacker Proof, Sicurezza in rete Seconda Edizione”, pubblicato da
“McGraw-Hill”, anno di pubblicazione 2002.
Bruce Schneider “Applied Cryptography Second Edition: protocols, algorithms and
source code in C”, pubblicato da John Wiley & Sons, Inc.
W. Rankl, W. Effing “Smart Card Handbook”, pubblicato da John Wiley & Sons, anno
di pubblicazione 2000.
“ISO/IEC Chip Card Standards”, www.iso.org, www.ansi.org
163
Bibliografia
“ISO/IEC 7816 Part 4: Interindustry command for interchange”,
www.ttfn.net/techno/smartcards/iso7816_4.html
RSA Laboratories “Standard PKCS”, www.rsasecurity.com/rsalabs
“PKCS#1: RSA Cryptography Standard”, versione 2.1, pubblicato da “RSA
Laboratories”, anno di pubblicazione 2002.
“PKCS#7: Cryptographic Message Syntax Standard”, versione 1.5, pubblicato da “RSA
Laboratories”, anno di pubblicazione 1993.
“PKCS#10: Certification Request Syntax Standard”, versione 1.7, pubblicato da “RSA
Laboratories”, anno di pubblicazione 2000.
“PKCS#11: Cryptographic Token Interface Standard”, versione 2.20, pubblicato da
“RSA Laboratories”, anno di pubblicazione 2004.
Klaus Finkenzeller “RFID Handbook: Fundamentals and Applications in Contactless
Smart Card and Identification, Second Edition”, pubblicato da John Wiley & Sons,
anno di pubblicazione 2003.
“DPR 10 novembre 1997 n.513, Legge Bassanini”,
www.icosaedro.it/crittografia/aspetti-giuridici.html, www.card.infocamere.it,
www.cnipa.gov.it
IBM “Open Card Framework, Fourth Edition”, anno di pubblicazione 1999.
Pravir Chandra, Matt Messier, John Viega “Network Security with OpenSSL”,
pubblicato da O’Reilly, anno di pubblicazione 2002.
164
Ringraziamenti
E’ giunto il momento tanto atteso! Scrivere questa pagina vuol dire, per me,
aver raggiunto un traguardo molto importante. Una tappa che, sicuramente, segnerà
un cambiamento nella mia vita. Posso dire, in tutta onestà, che la salita è stata dura e
sofferta, ma che, proprio per questo, la gioia di raggiungere la vetta è tanto grande.
Adesso, voltandomi indietro, sembra che questi anni siano volati, eppure di cose
ne sono successe tante! Ho trascorso momenti bellissimi e momenti difficili, che ho
avuto la fortuna di condividere con persone a me molto care e che rimarranno sempre in
me come parte di una esperienza indimenticabile.
I miei ringraziamenti sono rivolti in primo luogo ai miei genitori, per la loro
infinita pazienza che hanno dimostrato di avere nei momenti per me più critici di
questi anni di studi. Ma grazie soprattutto per il loro continuo sostegno in tutte le
scelte che hanno caratterizzato la mia vita, per aver sempre creduto in me, per i loro
consigli e per avermi trasmesso quei valori fondamentali che sono ora alla base del mio
modo di essere e del mio carattere. Un grazie particolare anche ai miei fratelli per tutte
le esperienze vissute e i momenti trascorsi insieme.
Un doveroso ringraziamento va ai professori Aldo Franco Dragoni e Paolo
Puliti dell’Università Politecnica delle Marche e all’ing. Giuseppe Giampieri della
ASUR 7 di Ancona che mi hanno offerto questa opportunità e mi hanno aiutato a
realizzarla.
Infine, non di certo per importanza, grazie a tutti i miei amici: a cominciare da
quelli più cari, con i quali sono cresciuto e che mi conoscono ormai da sempre; a quelli
che mi hanno accompagnato durante questa avventura universitaria e con i quali ho
condiviso sia momenti di studio che di svago; al gruppo dell’Irlanda, con i quali ho
trascorso un periodo fondamentale della mia vita. Grazie anche a tutti gli amici che,
purtroppo, ho perso di vista, ma che hanno comunque segnato la mia adolescenza.