Home   |   Archivio   |   Chi siamo   |   Contatti
Giovanni Puliti
Le applet firmate
Come firmare archivi JAR con certificati digitali per superare le restrizioni
di
Giovanni Puliti
Il processo di firma delle Applet, è da sempre avvolto da un certo mistero. Molti sanno che è una delle possibilità per sfuggire alle limitazioni di un Security Manager a volte un po' stretto, ma pochi sanno realmente cosa fare per ottenere piena libertà sul client. Vediamo in questo articolo come firmare un archivio JAR utilizzando i certificati digitali.

Introduzione

La possibilità di inserire un programma all'interno di una pagina HTML e poterlo eseguire da un qualsiasi client in giro per il mondo è sicuramente una delle caratteristiche più affascinanti di Java, caratteristica che ha contribuito in parte all'enorme successo iniziale di questo linguaggio. In molti infatti, appena avvicinatisi a Java hanno visto nelle Applet lo strumento per risolvere la maggior parte dei problemi di computazione distribuita.

In effetti quello che si può fare con questo tipo particolare di programmi è estremamente interessante, anche se spesso l'approccio con cui ci si avvicina a tali oggetti non è quello corretto.

Spesso infatti mi arrivano mail di neofiti alle prime armi i quali, dopo essersi scontrati con un soggetto piuttosto scontroso (il Security Manager del browser) finiscono per considerare le limitazioni delle Applet come un impedimento terribile, piuttosto che un corretto modo di vedere le cose per garantire un buon livello di sicurezza.

Ricordo infatti che questo tipo di programmi non può né leggere né scrivere in locale (cioè sulla macchina client dove viene eseguito), non può scrivere sul server dal quale è stata scaricata (vi può solo leggere informazioni) e non può collegarsi con server remoti differenti da quello di provenienza (il controllo avviene a livello di IP).

Non entreremo in questa sede nel merito se tali limitazioni siano giuste o sbagliate (ovviamente sono giuste), limitandomi a dire che nel mio caso i benefici di cui ho potuto godere in merito a gestione della sicurezza, mi hanno fatto risparmiare un sacco di lavoro. Per chi avesse qualche dubbio, rimando alla lettura del riquadro 1 ("Quando è necessario firmare una Applet?"), dove è riportato un breve riassunto su quello che è possibile fare con una Applet e come utilizzare a proprio favore quelle che possono sembrare delle insormontabili limitazioni.

Aggirare il Security Manager

Abbiamo detto che di fatto una Applet ha una operatività molto ristretta e che tale operatività è stata volutamente progettata per precisi motivazioni legate alla sicurezza; è anche vero però in certi casi potrebbe essere vantaggioso, se non addirittura necessario, permettere una maggiore libertà. Ad esempio, proprio di recente mi sono ritrovato in una situazione una applicazione Java basata su client e server, era necessario scaricare una grossa quantità di dati dal client al server, operazione che per ottimizzare le prestazioni poteva essere facilitata grazie al salvataggio di dati in locale, al fine di effettuare una sorta di cache in locale, scrivendo delle informazioni su disco.

Questo rilassamento dei vincoli di sicurezza sono possibili in Java grazie ad un meccanismo piuttosto sofisticato basato sulla firma digitale ed i certificati elettronici.

Per poter comprendere i vari punti che affronteremo nel corso dell'articolo è bene fare un po' di ripasso: ovviamente non potremo riprendere in mano tutti i concetti necessari e per questo consiglio di consultare le pubblicazioni riportate nella bibliografia (in particolare [crit] e [sec]), dove vengono affrontati i concetti base legati a chiavi, firme elettroniche e certificazioni.

Senza entrare troppo nello specifico, visto che non basterebbe lo spazio, vediamo quale è il processo di base per rendere una Applet più libera di agire. Di fatto tale trasformazione consiste nel rendere l'Applet stessa "fidata" (trusted), in modo che il browser ne riconosca la non pericolosità e ne permetta maggiore autonomia. Questa trasformazione è possibile attaccando un certificato elettronico basato su chiave asimmetrica che certifichi l'origine dell'Applet: è come se dicessimo al browser "attenzione questa Applet viene da un sito remoto di cui io mi fido, falle fare quello che vuole".

In realtà il concetto di "fare quello che vuole" è un tantino più complesso, e dipende molto dalla versione del JDK della JVM che esegue l'Applet. Seguendo l'evoluzione storica di Java, abbiamo il modello presente nel JDK 1.0 in cui non era prevista la possibilità di modificare il controllo sulle Applet, cosa che invece è stata introdotta con la versione 1.1.

In questo caso (JDK 1.1), come è abbondantemente spiegato in [sec], il modello di gestione della sicurezza prevede un sistema ON/OFF: o massima sicurezza (l'Applet non può fare niente), o nessuna sicurezza (nessuna restrizione, massima operatività). Questo sistema ovviamente risulta essere alquanto inadatto in un mondo sempre più interconnesso, e di fatti con la versione 1.2 siamo passati ad una gestione più sofisticata. Adesso infatti è possibile decidere che una certa Applet, proveniente da un certo sito, può effettuare solo determinate operazioni (ad esempio leggere ma non scrivere su file), che potranno essere differenti dai permessi concessi ad un'altra proveniente da un sito differente.

Questo modello, piuttosto articolato, che per molti aspetti assomiglia ad una gestione degli utenti/gruppi alla Unix, è estremamente utile dato che permette la massima flessibilità senza abbassare la guardia più del dovuto (vedi [secu12]).

Il processo di firma

Dopo questa introduzione, passiamo a vedere come firmare digitalmente una Applet, in modo da renderla trusted. Il processo si basa sulla generazione di opportune chiavi crittografiche asimmetriche (pubblica e privata) con le quali "marchiare" l'Applet.

Quando si dispone di una coppia di chiavi asimmetriche possiamo utilizzarle in due modi: per crittare o per decrittare. Supponiamo che si abbia un certo documento (file, sequenza di byte, o altro) e di firmarlo con la propria chiave privata: allora in questo caso tutti coloro che possiedono la mia chiave pubblica (che può essere distribuita liberamente proprio perché pubblica), potranno decrittare il documento ed avere la certezza assoluta sulla identità del mittente.

Viceversa se qualcuno critta un documento con la mia chiave pubblica, allora avrà la garanzia che solo io (che sono in possesso della chiave privata corrispondente) potrò leggere quel documento.

Ovviamente tutto questo, per quanto molto bello e tecnologicamente all'avanguardia, ha un problema di fondo, problema che di fatto spesso ne ostacola l'utilizzabilità: chi può garantire infatti che la mia chiave pubblica sia proprio la mia, e non ad esempio quella di un impostore che tenti di spacciarsi per me? Attualmente la soluzione a tale problema è ricorrere ad enti di certificazione che, dopo accurati controlli, provvedono a garantire l'identità delle persone/società con un processo a dire il vero per niente moderno ed innovativo (ricorda molto la trafila che si deve fare per avere un documento di riconoscimento dal nostro stato).

Gli aspetti legati alla gestione della sicurezza sono molto interessanti, e di fatto si basano su una continua ricerca di soluzioni tecnologicamente innovative, anche se (concludendo con una battuta di un mio caro amico esperto di queste cose) spesso il sistema tradizionale basato sul fascino di qualche bella spia che usa il suo fascino per concupire il responsabile della sicurezza, possono dare risultati a più buon prezzo.

Dopo questa divagazione vediamo quindi cosa è necessario fare per firmare una Applet: sono riportati qui di seguito i passi da effettuare nel caso di utilizzi i tool crittografici presenti nel JDK.

Figura 1
Figura 1

Creazione e compilazione della Applet

Questo processo è quello standard al quale siamo abituati, basato sulla stesura del codice e sulla successiva compilazione. Si noti che (come mostrato nell'esempio allegato AppletWrite.java) che in realtà non è necessario introdurre nessuna particolarità a livello di codice, dato che tutto avviene esternamente alla Applet. Nel nostro caso possiamo scrivere da riga di comando

javac myapplet.java

ottenendo il corrispettivo file myapplet.class.

Creazione dell'archivio JAR

Dopo aver compilato ed risolto tutti i problemi, dobbiamo "impacchettare" tutti i file che compongono l'Applet in un archivio JAR (che ricordo essere un particolare formato simile allo zip, si veda [jdkzip] per maggiori informazioni). Possiamo scrivere ad esempio

jar -cvf myapplet.jar myapplet.class *.gif

ottenendo un archivio contenente tutte le risorse necessarie per l'esecuzione della Applet stessa, come ad esempio immagini, suoni, file di vario tipo.

Creazione delle chiavi asimmetriche

Si deve adesso creare la coppia di chiavi asimmetriche necessarie per la firma del JAR e della successiva certificazione. Per fare ciò si utilizza il tool Keytool, il quale permette di svolgere molte operazioni (si veda il riquadro "Il keyTool"): in questo caso per mezzo dell'opzione -genkey si può generare una coppia di chiavi identificata attraverso l'alias signapplet. Tale alias, sarà utilizzato insieme alla password kpi135, specificata con l'opzione -keypass, per poter accedere alla chiave privata in successive invocazioni dei tools di security. La coppia di chiavi generata viene quindi memorizzata in un database appropriato, il keystore, di nome mystore, dando luogo ad un file del nome del keystore nella stessa directory in cui è stato invocato il tool. Per motivi di sicurezza, al fine di impedire che chiunque possa accedere alle chiavi appena prodotte, tale archivio è protetto con password (in questo caso abcd00).

Infine, dato che verrà generato un certificato associato alle chiavi (vedi oltre), per mezzo dell'opzione -dname e "cn=cbapplet", è possibile specificare un X.500 Distinguished Name (con common name cbapplet) per identificare un istanza del certificato X.509.

Figura 2
Figura 2
keytool -genkey -alias signapplet -keystore mystore -keypass kpi135 -dname "cn=cnapplet" -storepass abcd00

Firma del JAR

Ora che abbiamo creato il JAR e le chiavi, possiamo firmarlo, per mezzo del jarsigner; ad esempio possiamo scrivere

jarsigner -keystore mystore -storepass abcd00 -keypass kpi135 -signedjar smyapplet.jar myapplet.jar signapplet

comando grazie al quale diciamo quale file deve essere firmato (myapplet.jar), il nome del file prodotto (smyapplet.jar), dove prendere le chiavi (mystore), e le password per poter accedere a tali chiavi (kpi135) e all'archivio (abcd00). Il parametro signapplet serve per creare un alias, utile in seguito.

Esportazione del certificato

keytool -export -keystore mystore -storepass abcd00 -alias signapplet -file signapplet.cer

Con questo comando preleviamo il certificato dal keystore e lo copiamo in un file; a tal proposito è bene ricordare che quando generiamo una coppia di chiavi con il tool keytool di fatto creiamo le chiavi, ma anche il certificato digitale associato. Le chiavi sono composte da quella privata che è solo una chiave, e da quella pubblica alla quale è associato un certificato. Il certificato invece è composto da una serie di informazioni relative al proprietari, e dalla chiave pubblica stessa. È per questo, ripensando anche a quanto detto poco sopra che un certificato ed una chiave pubblica li possiamo pensare come una cosa sola.

Nella figura 1 è raffigurata la finestra che Windows 2000 mostra quando si prova ad aprire tale file: la lunga stringa senza senso rappresenta la firma, ovvero la chiave pubblica.

Installazione di Applet fidate

A questo punto abbiamo completato le operazioni necessarie per firmare l'Applet e renderla fidata. Come si può notare, in nessun punto è comparso una qualche riferimento sul che cosa tale Applet possa fare, e sul come farla funzionare sul client. Fino a questo punto infatti le si è semplicemente assegnato l'etichetta di riconoscimento, in modo che ne sia univocamente identificata la provenienza.

Resta quindi da definire un qualche meccanismo per mezzo del quale specificare il suo raggio d'azione. Nel caso del JDK 1.1 questo è molto semplice, dato che il browser abbassa completamente la guardia, ma se si dispone di una JVM Java 2 (o per mezzo dell'appletviewer o grazie al Java Plug-in), è possibile definire qualcosa di più raffinato.

Questo processo lo possiamo suddividere in due fasi: per prima cosa dobbiamo importare ed installare il certificato prodotto al passo precedente. Questa operazione viene eseguita più o meno automaticamente dal browser (se si utilizza il browser), mentre deve essere eseguita a mano se si utilizza l'appletviewer. Ovviamente la seconda possibilità è più interessante, e per questo è quella che vedremo.

Sempre da riga di comando dobbiamo immettere il comando:

keytool -import -alias csignapplet -file signapplet.cer -keystore cmystore -storepass abcdef

che permette l'installazione del certificato nel db locale (ogni ambiente ha un suo archivio, il browser, l'appletviewer-JDK, il sistema operativo).

Creazione del file di policy sul client

A questo punto si deve mappare le associazioni Applet certificata - operazioni permesse: tale associazione deve essere effettuata sul client per mezzo del cosiddetto file di policy.

Si tratta di un banalissimo file di testo come quello riportato qui di seguito (è il file allegato Write.jp)

keystore "file://D|cmystore", "JKS";

grant codeBase "file://D|" {
  permission java.io.FilePermission "<<ALL FILES>>", "read, write, delete, execute";
};

il cui significato credo sia piuttosto chiaro.

Dato che la sintassi e la struttura del file sono molto importanti, in genere non si edita tale file direttamente a mano, ma si utilizza un tool apposito messo a disposizione all'interno del JDK, il PolicyTool (alla faccia della fantasia e della suspence).

Alla inizializzazione tale strumento va a cercare nella directory utente il file .java.policy, che di fatto rappresenta il file di policy di default l'utente in questione. Per sapere quale sia la propria home directory si può utilizzare il piccolo programmino di esempio allegato (Env.java) il quale mostra tutte le variabili d'ambiente settate al momento.

Alternativamente possiamo creare il nostro file di policy per mezzo dell'opzione file->new. In questo caso è necessario scegliere il nome del file ed il keystore a cui fare riferimento: in questo caso per non fare confusione chiamiamo clientmystore, per differenziarlo dall'altro che aveva funzionalità server (o meglio di sviluppo).

Se di clicca sul pulsante add entry possiamo specificare il codebase di provenienza della Applet ed il firmatario che ne garantisce il funzionamento corretto. Entrambi i campi sono opzionali, dato che è possibile offrire libertà d'azione a tutte le Applet provenienti da un certo sito (quindi omettendo quindi il nome di chi ha firmato) ed a tutte le Applet provenienti da qualsiasi Host remoto (omettendo in questo caso il CodeBase).

Infine cliccando su AddPermission possiamo specificare il tipo di permesso (da AllPermission, a FilePermission NetPermission o simili), il tipo di operazioni: ad esempio nel caso di FilePermission possiamo decidere se permetter solo la lettura, solo la scrittura, solo l'esecuzione o una combinazione di queste.

Figura 3
Figura 3

Conclusioni

Come si è potuto vedere il processo di certificazione di una Applet, sebbene sia piuttosto semplice, si compone di una serie di passi piuttosto importanti, che nascondono dietro aspetti del tutto non trascurabili. IN particolare tutta la gestione della sicurezza, degli aspetti legati a chiavi asimmetriche e certificati digitali, sono argomenti piuttosto corposi, per i quali si raccomanda un minimo di padronanza, o perlomeno di conoscenza dei punti più importanti.

Da notare che la certificazione della Applet avviene al momento della sua creazione, e che non è niente di più che una assegnazione di un nome ufficiale. Il vero punto importante è la creazione del file di policy: è importante infatti non tanto da un punto di vista tecnico, quanto piuttosto da quello organizzativo. Dato infatti che una Applet invade la privacy e la sicurezza del client, è questo decide quanto cosa e come l'Applet può eseguire. Se questa impostazione può portare ad una minore automazione (si richiede sempre una serie di operazioni sul client), è in ogni caso indispensabile per permettere la massima sicurezza.

Si tenga presente infine che, come raccomandato nel primo riquadro, la firma dell'Applet raramente è realmente necessario, e che per quanto possibile è sempre meglio evitare.

Una nota sugli esempi allegati: a parte i file WriteApplet.java ed Env.java, gli altri sono di fatto i certificati e le chiavi prodotte durante l'esecuzione dei comandi che abbiamo analizzato qui. Chi seguisse tutti i passi riportati probabilmente dovrebbe ritrovarsi con lo stesso materiale.

Bibliografia

  • [secu1.2] "Il nuovo modello di sicurezza del JDK 1.2" di Giovanni Puliti - MokaByte 17, www.mokabyte.it/0399
  • [cript] "Java Criptography" di Knudsen - Ed. O'Reilly
  • [sec] "Java Security" di Scott Oaks - Ed. O'Reilly
  • [jdkzip] "I package del JDK: java.util.jar/zip" www.mokabyte.it/packages
MokaByte® è un marchio registrato da MokaByte s.r.l. 
Java®, Jini® e tutti i nomi derivati sono marchi registrati da Sun Microsystems.
Tutti i diritti riservati. E' vietata la riproduzione anche parziale.
Per comunicazioni inviare una mail a info@mokabyte.it