Abstract
Con questo articolo si intende affrontare la problematica dell'Url-Crypting dei dati all'interno di Web Application, che operano su Web Server basati su una Java VM 1.3.x o precedenti. Tale problematica si presenta in un differente contesto di utlizzo rispetto alla sola codifica/decodifica delle informazioni.
Data di stesura: 27/09/2002
Data di pubblicazione:
28/09/2002
Ultima modifica: 04/04/2006
Nel panorama del mondo del software si sta assistendo ad un notevole incremento di applicazioni che hanno l'esigenza di trattare informazioni riservate: tali informazioni devono essere trasmesse attraverso un URL di internet o protocolli SOAP-like nell'ambito delle tecnologie legate ai Web Service.
Conseguenza di ciò è la sempre più pressante esigenza di sicurezza delle trasmissioni: il processo di personalizzazione delle procedure di codifica e decodifica dei dati, onde proteggerli da un eventuale hacking, introduce uno strato di software all'interno delle applicazioni che implementa le regole di sicurezza decise in fase di analisi del business.
L'obiettivo di questo articolo è di illustrare come risolvere una tale problematica all'interno della tecnologia J2EE con VM versione 1.3.x tenuto conto delle problematiche di codifica/decodifica all'interno del protocollo HTTP.
Nella ver. 1.3.x della Java VM, le librerie per il crypting dei dati sono da considerarsi come Plug-In e soggette a controllo da parte delle istituzioni governative americane, che ne vietano l'utilizzo al di fuori dell'ambito geografico USA o Canadese.
La soluzione ad un tale problema consiste nella possibilità di poter utilizzare una particolare libreria, J2EE compliant, chiamata Cryptix 3.1.
Il prodotto in questione è realizzato da una organizzazione internazionale dedita all'open-source e si presenta come una valida alternativa alla J.C.A.(Java Crypting API).
Di seguito viene mostrato un breve esempio, ove vengono riassunte in poche righe di codice le istruzioni fondamentali per il Crypting ed il Decrypting dei dati realizzati con Cryptix 3.1.
KeyGenerator keygen = KeyGenerator.getInstance("DES");
SecureRandom random = new SecureRandom();
keygen.initialize(random);
String c_inform = "Informazioni da criptare";
String d_inform = "Informazioni da decriptare";
Key key = keygen.generateKey();
Cipher cipherIn = Cipher.getInstance("DES");
// Istruzioni per il Crypting
cipherIn.initCrypt(key);
byte[] crypted = cipherIn.doFinal(c_inform);
// Istruzioni per il Decrypting
cipherIn.initDecrypt(key);
byte[] decrypted = cipherIn.doFinal(d_inform);
Eseguendo la serie di statement presentati nell'esempio di cui sopra otteniamo uno stream di byte che siamo in grado di trasferire attraverso il protocollo HTTP. È al momento della trasmissione che, volendo utilizzare il comando GET, ci accorgiamo che qualcosa non è andata a buon fine! Vediamo cosa è accaduto.
Nell'operazione di Crypting avviene il mascheramento delle informazioni e la chiave generata utilizza caratteri particolari quale ad esempio "l'invio". Questi elementi non sono previsti nella specifica W3C per l'URL. È evidente che questi caratteri non sono eliminabili in quanto condizionano anche la dimensione del messaggio da trasmette!
Esistono diverse soluzioni ad un problema di tal genere. In questo articolo ne esamineremo due, osservandone pregi e difetti:
Utilizzo delle utilità di URL encoding;
Passaggio delle informazioni ottenute utilizzando un sistema di scambio diretto dei bytes.
Utilizzo delle utilità di URL encoding
Utilizzando la Classe URLEncoder che appartiene al package java.net si ha il vantaggio della notevole semplicità d'uso, ovvero la codifica in un formato URL-compatibile è ottenuta con la semplice invocazione di un metodo statico:
String value = new String (crypted);
String encodedValue = URLEncoder.encode(value);
Lo svantaggio di quest'approccio è dovuto al meccanismo stesso di codifica adottato nella classe URLEncoder; questo prevede:
I gruppi di caratteri ASCII compresi tra "a" e "z", tra "A" e "Z", tra "0" e "9", ed inoltre i caratteri ".", "-", "*", "_" rimangono gli stessi;
Il carattere speciale " " è convertito in "+";
Tutti gli altri caratteri sono convertiti in un formato speciale.
Scambio diretto dei bytes
Utilizzando la seconda modalità al contrario si ottiene il risultato voluto, senza alcuna controindicazione dal punto di vista della codifica delle informazioni. Il difetto principale consiste nella presenza di codice leggermente più complesso, come segue:
cipherIn.initCrypt(key);
byte[] crypted = cipherIn.doFinal(c_inform);
StringBuffer buffer = new StringBuffer();
for (int index = 0; index < crypted.length; index++) {
buffer.append("par=").append(
String.ValueOf(new Byte(crypted[index]))).append("&");
}
Adottando nel punto di ricezione una decodifica analoga è possibile una trasmissione completa ed efficace:
java.util.Enumeration parameters = request.getParameterNames();
java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream();
String actualValue = null;
String key;
while (parameters.hasMoreElements()) {
key = String.valueOf(parameters.nextElement());
if (key.startWidth("par")) {
actualValue = String.valueOf(request.getParameter(key));
out.write(new Byte(actualValue).intValue());
}
}
byte[] receivedData = out.toByteArray();
Conclusioni
La tematica del crypting e, in generale, delle sicurezza è oramai un elemento preponderante nello sviluppo di software per l'impresa: la realizzazione opportuna di codice è un compito importante ed a volte complesso. Fortunatamente sul mercato si affacciano sempre più componenti di business e librerie che facilitano il compito dello sviluppatore così come mostrato in questo articolo. Il passo immediatamente successivo sarà la standardizzazione ed anche su questa problematica Java ha intrapreso la giusta strada i cui primi risultati saranno evidenti con le nuove release 1.4.1 e 1.4.2 del J.D.K. Tutto questo nell'attesa di Tiger (Java 3).
La specifica per le URL (RFC 1738 - Dicembre 1994) pone un problema dato che limita i caratteri leciti ad un sottoinsieme del set dei caratteri US-ASCII e precisamente:
"...solo elementi alfanumerici [0-9,a-z,A-Z], i caratteri speciali [$-_.+!*'(),] e i caratteri usati per scopi riservati possono essere usati non codificati in un URL..."
HTML d'altro canto permette l'intero range di valori ISO_LATIN (ISO-8859-1) e HTML 4.x espande questa possibilità all'intero set UNICODE. Nel caso di caratteri non ISO-8859-1 non possono essere usati in URL ma, dovranno essere codificati.
Riassumendo, i caratteri che necessitano di encoding sono:
caratteri ASCII di controllo: sono compresi i caratteri ISO-8859-1 da 00 a 1F (0-31 decimale) e 7F (127 decimale);
caratteri non ASCII: sono compresi i caratteri da 80 a FF (128-255 decimale);
L'URL encoding di un carattere consiste di un simbolo "%" seguito da una rappresentazione, a due cifre, in esadecimale (case-insensitive) dell'elemento ISO-Latin per il dato carattere.
Esempio: SPAZIO = 32 (decimale) = 20 (hex) = %20 (encoded)
Java e l'URL encoding
L'algoritmo di codifica e decodifica di una sequenza alfanumerica è demandata a due classi del package java.net: java.net.URLEncoder e java.net.URLDecoder che presentano rispettivamente i metodi statici encode() e decode(). Sfortunatamente il comportamento di questi elementi non è corretto sino alla versione J.D.K. 1.3.x portando ad un encoding non compatibile con le specifiche W3C. La problematica è stata affrontata e fixata solo nel J.D.K. 1.4.x dove i precedenti metodi sono stati deprecati a favore di nuovi che non risentono più della dipendeza dall'encoding della specifica piattaforma.
Informazioni sull'autore
Nicola Pepè, laureatosi presso il Politecnico di Milano in Ingegneria delle Telecomunicazioni, è attualmente responsabile di Progetto e Senior Teacher in relazione alla piattaforma J2EE per la ObjectWay S.p.A. ; l'attività di training interessa anche la configurazione ed amministrazione di alcuni tra i più diffusi Application Server in commercio tra i quali BEA WEBLOGIC. Ha contribuito alla realizzazione di numerose applicazioni in ambito Finanziario e Geofisico; è stato correlatore presso la Java Conference 2002 di Milano sul tema: "Web Service on Demand".