Cerca nel blog

Visualizzazione post con etichetta java. Mostra tutti i post
Visualizzazione post con etichetta java. Mostra tutti i post

lunedì 11 ottobre 2010


Abbiamo già parlato in un altro articolo dell'architettura della crittografia nel linguaggio Java.
Oggi proponiamo un esempio di come poter ottenere un Message Digest da un  testo in chiaro.



import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Main {

    public static void main(String[] args) {

        try {
            byte[] testoChiaro = "This is a test!".getBytes("UTF8");
            MessageDigest md = MessageDigest.getInstance("MD5");
            //visualizzo il provider utilizzato
            System.out.println("Provider:\n"+md.getProvider().getInfo());
            //cifro il messaggio
            md.update(testoChiaro);
            System.out.println("Message Digest:\n" + new String(md.digest(), "UTF8"));
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }

    }
}

mercoledì 6 ottobre 2010

JCA-Java Criptography Architecture

Abbiamo già parlato di crittografia per quanto riguarda il linguaggio Java.
Ora parleremo di JCA, il framework di base per la crittografia, è costruito intorno alla J2SA(Java 2 Security Architecture).
Si basa sui principi della Criptography Service Provider Architecture:
  • indipendenza dell'implementazione(Algorithm indipendences)
  • interoperabilità
  • estendibilità
L'indipendenza dell'implementazione o Algorithm indipendences utilizza classi astratte di tipo "engines" che dichiarono le funzionalità di un dato tipo di algoritmo crittografico, impiega poi classi "provider" che implementano un certo insieme di funzionalità crittografiche per un Criptographic Service Provider(CSP).

In genere un'applicazione crittografica può richiedere genericamente un'implementazione di un dato algoritmo senza curarsi di quale provider lo fornisca, infatti una volta installati possono coesistere uno o più CSP anche di differenti produttori, il provider di default si chiama SUN ed è integrato nel JDK.
In Pratica:
  • Engine class: definiscea crypto service in an absract class senza implementazione
  • Service provider interface: provvede ad una crypto interface dell'applicazione via "engine"
Cryptographic service provider: ogni classe "engine" ha una corrispondente SPI che definisce esattamente un crypto method implementato da CSP. 

Principali engine class:
  • KEY: defisce le funzionalità condivise da chivi "opache"
  • KEY SPEC:definisce una chiave di tipo trasparente
  • KeyFactory:prende una chiave di tipo KEY "opaca" o "trasparente"
  • KeyPairGenerator:genera una coppia di chiavi assimentriche
  • AlgorithmParameters: gestisce i parametri di un algoritmo
  • AlgorithmParametersGenerator:genera i set di parametri di un algoritmo
  • MessageDigest:calcola l'hash di dati specifici
  • SecureRandom:genera numeri causali o pseudo casuali
  • Signature:appone e verifica la firma digitale
  • CertificateFactory:crea e revoca certificati di chiavi pubbliche
  • KeyStore:crea e gestisce un database(Keystore) di chiavi e certificati sicuri.
Il provider SUN include:un'implementazione dell'algoritmo DSA (Digital Signature Algorithm), un algoritmo MD5 e SHA-1 di MessageDigest, un KeyPairGenerator per DSA, AlgorithmParameter ed AlgorithmParameterGenerator per DSA, un KeyFactory per DSA, un CertificateFactory  per certificati X.509 e per CRLs, un'implementazione del KeyStore proprietario JKS.

Le estensioni JCE(Java Cryptographic Extension) e JSSE(Java Secure Sockects extension) implementano ed estendono le tecniche  crittografiche definite dalla JCA fornendo CSP alternativi a SUN.
Invece i restanti set di package offrono funzionalità di sicurezza aggiuntive e sono quindi complementari alla JCA.
  • JAAS:servizi di autenticazione, amministrazione e autorizzazione
  • CertPath:gestione dei certificati e catene di certificati
  • JGSS:meccanismi di comunicazione generici e specifici per beyberos v5

JCE
Java Cryptographic Extension
La JCE ha il compito di fornire  un'implementazione completa delle funzionalità di cifratura e decifratura dichiarate dalla JCA.
JCE offre supporto:
  • cifrari simmetrici a blocco e a flusso
  • cifrari asimmetrici
  • cifrari con password
applicazioni su:
  • Data
  • I/O streams
  • Serializable Object
in meccanismi quali:
  • MAC(Message Authentication Code)
  • KeyGenerator/KeyAgreement
JCA-Message Digest
Java Criptography Architecture offre la classe "engine" MessageDigest astratta che provvede a fare da design per offrire la funzionalità di cifratura di messaggi sicuri con algoritmo SHA-1 o MD5, questo messaggio criptato è detto: Message Digest o semplicemente indicato con MD.
Un message digest è un messaggio in chiaro di lunghezza variabile tradotto in un messaggio "sicuro" di lunghezza fissa.
Un MD ha due proprietà:
  1. se x->h(x), e y ed x sono diversi, non si può avere h(y)=h(x)
  2. non si possono avere collisioni 
Ad esempio in Internet è utilizzato MD5-128 bit che non garantisce nulla per quanto riguarda la collisione.
Le API Java sono:
  • MessageDigest.getInstance("MD5")  per ottenere un MD
  • .update(plaintext) per calcolare MD con il testo in chiaro
  • .digest() per leggere il message digest

JCA-Message Authentication Code(MAC)
MACs usa una chiave per preservare l'integrità del messaggio.JCA supporta gli algoritmi:
  • HMAC/SHA-1
  • HMAC/MD5
Le API Java sono:
  • KeyGenerator.getInstance("HMACMD5") e .generateKey() per generare la chiave
  • Mac.getInstance("HMACMD5") crea un oggetto MAC
  • .init(plaintext) e .doFinal() inizializza un MAC object
  • .update(plaintext) e .doFinal() calcolano il MAC object con testo in chiaro




lunedì 4 ottobre 2010

Java Cryptography

Il linguaggio Java divide la sicurezza in due livelli:
  • un livello basso di sicurezza JVM Layer:garbage collection,class file verification, etc.
  • un livello alto di sicurezza Application Layer:sandbox, security policy, security APIs, etc.
Fino a JDK 1.4 esistevono package esterni per creare applicazioni sicure:
  • JCE (Java Cryptography Extension)
  • JSSE (Java Secure Socket Extension)
  • JAAS (Java Authentication and Authorization Service)
Dalle versioni successive a JDK 1.4 sono state aggiunte due nuove funzionalità:
  • JGSS (Java General Security Service)
  • CertPath API (Java Certificate Path API)

JVM Layer



JVM Layer
JVM Layer: Java Virtual Machine
  • è responsabile dell'indipendenza della piattaforma
  • è responsabile della macchina astratta
  • ha un set di istruzioni
  • può manipolare la memoria a runtime
  • non interpreta il codice Java ma il bytecode
  • il bytecode è memorizzato nei class file
JVM Layer: Class file structure
Il class file è composto da:
  • da una "magic" costant OxCAFEBABE
  •  version number
  • Access flag
  • "costant pool"
  • Informazioni sulla classe corrente(nome, superclasse, etc.)
  • Informazioni a riguardo i metodi e le proprietà di una classe
  • Informazioni di Debbugging

JVM Layer: The Class File Verification
  • Verifica di base della struttura della classe
  • Verifica base del "looks" delle:
    referenze di classe
    referenze dei campi
    referenze sei simboli
  • Verifica del bytecode
  • Verifica effettiva:
    referenze di classi
    accesso e modifica dei campi e metodi chiamati

Application Layer
Application Layer:Class verification
  •  Il class loader carica le classi su richiesta
  • Riduce la memoria usata
  • Enforces type-safety alongside the JVM
  • Migliora il tempo di risposta del sistema
  • Istanze di classe caricate:
    Primordial/bootstrap class loader
    System class loader
    Application class loader
  • Il class loader è chiamato è chiamato dalla JVM
  • Il class loader è responsabile di caricare le classi e di dargli un namespace
  • Associa le classi caricate ad un dominio di protezione
Protection domain
  • associa i permessi alla classe per quanto riguarda le locazioni, i certificati, etc.
  • è definito dalla security policy
  • la security policy di default si riferisce al system-wide policy ed implementa la policy di default per la sandbox 
  • policy addizionali sono user-defined
  • si possono avere una o più policy security
  • tutte le referenze alla security policy sono specificate nel security property file localizzato nella directory di installazione del JDK(o JRE)

    mercoledì 7 luglio 2010

    Thread Java

    Il linguaggio Java supporta i Thread mettendo a disposizione degli sviluppatori
    la classe Thread oppure è possibile implementare l'interfaccia Runnable.
    Nel caso si decide di utilizzare la classe Thread per far si che il thread esegua quelle che si vuole bisogna fare l'override del metodo run(), un modo alternativo per implementare i threads è quello di creare una classe che implementa
    l'interfaccia Runnable e definire quindi il metodo run(), poi si deve passare come parametro un'istanza di tale classe al costruttore della classe Thread.
    In entrambi i modi di implementare i thread il corpo del thread stesso risiede nel metodo run().


    LifeCycle

     

    Come si può notare dalla figura i thread si possono trovare in quattro diversi stati
    1. Nuovo
    2. Eseguibile(o runnable)
    3. Bloccato
    4. Concluso
    Ora vediamo cosa significano i quattro stati in cui un thread si può trovare.
    • Nuovo:il thread è in questo stato quando grazie all'operatore new si crea un nuovo thread per esempio new Thread(t) dove t è un oggetto di una classe che implementa l'interfaccia Runnable.
    • Runnable:dopo aver chiamato il metodo start() il thread si trova nello stato eseguibile(o runnable), anche se effettivamente non sia detto che questo sia in esecuzione magari perchè il sistema operativo non l'abbia ancora schedulato. Quindi ci si deve ricordare che quando un thread è nello stato runnable non è detto che esso sia davvero in esecuzione.
    • Bloccato:un thread si può trovare nello stato bloccato quando:




      • Il thread è sospeso da una chiamata del metodo sleep()
      • Il thread è bloccato nell'attesa di completamento di un richiesta di I/O
      • Il thread tenta di ottenere l'accesso(lock) ad una risorsa condivisa detenuta da un altro thread
      • Il thread attende che si verifichi una particolare condizione
      Quando un thread è bloccato rilascia la CPU, e il sistema operativo può quindi schedulare un altro thread pronto per essere eseguito.
      Il thread sospeso ritorna nello stato runnable solo quando la condizione che l'ha portato nello stato bloccato cessa di esistere quindi:




      • Quando i millisecondi indicati nella chiamata del metodo sleep() sono terminati
      • Quando si conclude l'operazione di I/O richiesta
      • Quando riesce ad ottenere il lock alla risorsa condivisa
      • Quando la condizione che aspettava si è verifica
      Quindi un thread bloccato può ritornare nello stato eseguibile solo ripercorrendo lo stesso percorso che l'ha portato nello stato bloccato.
    • Concluso:un thread può concludersi perchè il codice del metodo run() viene eseguito tutto e quindi il metodo stesso termina, oppure perchè un'eccezione non catturata termina il metodo run(). Per interrompere un thread si può utilizzare il metodo stop(), mentre per verificare se un thread è nello stato eseguibile o bloccato si può utilizzare il metodo isAlive() che ritorna il valore true se il thread è appunto eseguibile o bloccato, mentre ritorna il valore false se il thread non è ancora runnable o concluso.


    Proprietà dei thread

    • Priorità dei thread:Nel linguaggio Java ogni thread ha una priorità è possibile aumentare o diminuire questa priorità utilizzando il metodo setPriority(int newPriority), si può impostare la priorità con un valore compreso tra MIN_PRIORITY(definito come 1 nella class Thread) e MAX_PRIORITY(definito come 10 nella class Thread). Tuttavia si deve tener conto che la priorità dei thread è molto legata al sistema operativo, quindi la priorità viene mappata rispetto ai livelli di priorità del sistema operativo ospite, questi livelli possono essere diversi da quelli definiti dal linguaggio Java si dovrebbe evitare quindi di strutturare programmi che funzionano con la priorità dei thread.
    • Thread demoni:un thread può essere trasformato in un demone chiamando il metodo setDaemon(true) un thread di questo tipo ha lo scopo di servire altri thread.
    • Gruppi di thread:il linguaggio Java permette di classificare i thread di uno stesso programma in gruppi, ciò è possibile grazie alla classe ThreadGroup.
      Esempio:




      ...

      String nomeGrupp="pippo";

      ThreadGroup g=new ThreadGroup(nomeGruppo);

      Thread t=new Thread(g,"nomeThread");

      ...
    Vediamo alcuni semplici esempi di thread:


    public class ExampleThread extends Thread {

         public ExampleThread(String name) {

           super(name);

         }

         public void run() {

           for (int i = 0; i < 100000; i++) {

             System.out.println(this.getName()+" "+i+" volte");

           }

         }



         public static void main(String[] args) {

           ExampleThread t = new ExampleThread("ExampleThread");

           t.start();

           for (int i = 0;i<1000000;i++)

             System.out.println("Main "+i+" volte");

          }

         }



    Vediamo invece ora l'implementazione di Runnable


    public class ExampleRunnableThread implements Runnable {
         public void run() {

           for (int i = 0; i < 100000; i++) {

              System.out.println(Thread.currentThread().getName() + " " + i + " volte");

           }

         }


         public static void main(String[] args) {

           ExampleRunnableThread r = new ExampleRunnableThread();

           Thread t=new Thread(r);

           t.setName("ExampleRunnable thread");

           t.start();

           for (int i = 0;i<1000000;i++)

             System.out.println("Main "+i+" volte");

         }

         }


    I due esempi illustrati dovrebbero mostrarvi come la CPU per un certo periodo esegue il thread main e per un certo intervallo l'altro thread con un'alternanza dei due thread.

    martedì 6 luglio 2010

    La riflessione in Java

    La riflessione Java è uno strumento potente, per scrivere programmi che possono elaborare dinamicamente il codice Java. Un programma è riflessivo se è in grado di analizzare le funzionalità delle classi. La riflessione Java è uno strumento utilizzato sopratutto da coloro che realizzano strumenti per lo sviluppo. Iniziamo la nostra navigazione all'interno delle classi che la libreria standard Java ci mette a disposizione per utilizzare questo potente strumento.


    Le classi che permettono di utilizzare la riflessione sono:
    • Class
    • Constructor
    • Field
    • Method

    Class
    Quando un programma è in esecuzione il sistema runtime di Java mantiene il tipo in runtime degli oggetti. Questa informazione è utilizzata dalla Java Virtual Machine per la selezione del metodo corretto. Per accedere a questa informazione si utilizza il metodo getClass() della classe Object che restituisce un'oggetto della classe Class.
    Un esempio di come ottenere il tipo a runtime di un oggetto:


    import java.util.LinkedList;

    import java.util.List;

    public class Riflessione {

       public static void main(String[] arg){

         try {

          List<String> l = new LinkedList<String>();

          Class c = l.getClass();

          System.out.println(c);

          String name = "java.util.ArrayList";

          Class cl = Class.forName(name);

          System.out.println(cl);

         }

         catch (ClassNotFoundException ex) {

          System.out.println(ex.getMessage());

         }

       }

    }


    Dal codice si può notare che oltre ad utilizzare il metodo getClass() della classe Object per ottenere un oggetto della classe Class, si può utilizzare anche il metodo statico forName() della classe Class passando a tale metodo una stringa che deve essere un nome valido di una classe o di una interfaccia, altrimenti il metodo genera un'eccezione verificata ClassNotFoundException. Un altro metodo molto utile della classe Class è newIstance(), questo metodo utilizzato in combinazione con il metodo forName() permette di creare un ogetto dal nome contenuto nella stringa che si passa al metodo forName()


    String name = "java.util.Date";

    Object o=Class.forName(name).newInstance();


    I due metodi utilizzati in combinazione come nell'esempio precedente possono generare due eccezioni verificate InstantiationException e IllegalAccessException.

    Field,Method e Constructor
    Le classi Field,Method e Constructor sono tutte classi che fanno parte del pacchetto java.lang.reflect queste classi descrivono ripettivamente i campi, i metodi e i costruttori di una classe.

    La classe Field ha un metodo getType() che ritorna anch'esso un oggetto della classe Class relativo al tipo del campo che descrive. La classe Method ha alcuni metodi utilissimi tra i quali getName() che ritorna un oggetto di tipo String che descrive il nome del metodo, il metodo getParameterTypes()

    che ritorna un array di oggetti ancora una volta di tipo Class che rappresenta il tipo dei parametri formali inseriti nel vettore secondo l'ordine in cui sono scritti nella signature del metodo, l'array può avere un numero di elementi uguale a 0, in questo caso significa che il metodo rispettivo non ha parametri.Il metodo getReturnType() ritorna un oggetto di tipo Class che rappresenta il tipo di ritorno del metodo. Il metodo getExceptionTypes() ritorna anch'esso un array di tipo Class e contiene tutte le eccezioni che il metodo specifica nella clausola throws, la dimensione di questo array può essere 0 se il metodo non specifica eccezioni.
    La classe Constructor specifica tra i metodi anch'essa il metodo getParameterTypes() ma in questo caso gli elementi dell'array che ritorna il metodo, identificano i parametri che il relativo costruttore richiede, naturalmente questo array di ritorno può avere 0 elementi.
    Tutte le classi descritte specificano un metodo getModifiers() questo metodo restituisce un intero con un insieme di bit di stato posti ad on/off per indicare i modificatori utilizzati per il rispettivo metodo, campo o costruttore a cui il metodo è applicato. I metodi della classe Class getFields(),getMethods() e getConstructors() ritornano rispettivamente array dei campi, dei metodi e dei costruttori pubblici e tutti i membri pubblici della superclasse, metre i metodi getDeclaredFields(),get DeclaredMethods() e getDeclaredConstructors() restituiscono array costitutiti da tutti gli attributi, metodi e costruttori dichiarati nella classe, anche i membri privati e protetti, ma non i membri della superclasse.