Ecco come integrare i servizi di sinekarta in qualsiasi software!


Come vi ho spiegato nello scorso articolo, con la versione 2.0 sinekarta è stato APERTO; i servizi che mette a disposizione sono utilizzabili da qualsiasi software.

Questo articolo vuole spiegare, tramite esempi, come integrare alcuni (tra i diversi) servizi di sinekarta.

Prima di continuare a leggere è importante sapere alcune cose :

  1. Se non hai un background informatico probabilmente non capirai un gran che di questo articolo (nel caso forse ti basterà  sapere che si può fare ed è facile)
  2. Gli esempi di codice inseriti in questo articolo sono scritti in Java, probabilmente sul wiki di progetto, in futuro, sarà  possibile reperire esempi in altri linguaggi.
  3. I servizi REST esposti da sinekarta sono realizzati in duplice versione : con input/output in formato JSON e con input/output in formato XML; questo esempio usa il formato JSON
  4. Sul repository SVN di progetto potete trovare i sorgenti di questo articolo e di altri client di esempio

Quello che andremo a realizzare tramite questo esempio è un programma che prende un documento (già  inserito nel repository Alfresco), lo converte in PDF/A ed applica la firma digitale di un utente.

Per poter eseguire questo codice senza errori avete quindi bisogno di :

  • Alfresco 3.4d (o superiore) correttamente installato
  • Sinekarta 2.0 beta (o superiore) correttamente installato e configurato
  • Un IDE per lo sviluppo (es. Eclipse) su cui installare gli esempi di sinekarta (potete scaricarli da questo repository SVN : https://sinekarta.svn.sourceforge.net/svnroot/sinekarta/trunk/SinekartaAlfrescoClient; il sorgente di questo articolo è la classe java org.sinekarta.alfresco.webscripts.TestDigitalSignature)
  • Un lettore di smart card correttamente installato e funzionante con relativa smart card di firma digital (in alternativa potete utilizzare un token USB)

Come prima cosa è necessario convertire il documento prescelto in PDF/A. Come sapete questo formato non prevede macro istruzioni nè codice eseguibile, compatibilmente con la normativa Italiana in materia :

 // step 1 : conversione in PDF/A
 // operazione lato server
 ...
 HttpPost httppost = new HttpPost(DOCUMENT_TO_PDFA);
 // prima di tutto, il documento va convertito in PDF/A
 // la action lavora sul documento stesso, quindi se non si
 // vuole perdere l'originale è opportuno lavorare su una copia
 String req = "{"nodeRefs":""+nodeRefId+""}";
 ByteArrayEntity body = new ByteArrayEntity(req.getBytes());
 httppost.setEntity(body);
 HttpResponse response = httpclient.execute(targetHost, httppost,
                                            localcontext);
 HttpEntity entityResp = response.getEntity();
 InputStream is = entityResp.getContent();
 JSONObject inputJson=null;
 try {
 inputJson = JSONObject.fromObject(new String(loadResponse(is),
                                   ENCODING));
 } catch (UnsupportedEncodingException e) {
 // not possible
 }
 System.out.println(inputJson);
 EntityUtils.consume(entityResp);

Sono stati volutamente omesse alcune righe di codice, quelle più insignificanti dal punto di vista di sinekarta.

Il servizio prende un elenco di nodeRef separti tramite il carattere “,” (virgola). Ogni singolo nodeRef è una stringa simile a questa : workspace://SpacesStore/87350b02-32ab-4787-98d0-3daa1c0b7b01. Questo servizio lavora direttamente sul documento indicato, quindi, se non volete perdere l’orignale, sarà  meglio che lavoriate su una copia.

Piccola nota tecnica, il servizio di trasformazione in PDF/A di sinekarta è basato su open office, ma non è in conflitto con tutti i servizi di trasformazione messi a disposizione da Alfresco.

Ora che abbiamo un documento PDF/A è necessario eseguire 5 diversi step per l’applicazione della firma digitale. In particolare dovremo eseguire 3 step lato server e 2 step lato client. Se non avete idea del perchè parli di due diversi strati applicativi, andatevi a rileggere questo articolo.

Sia che lo abbiate letto, o che non lo abbiate fatto, ve lo riassumo in due parole : la comunicazione con la smart card è un’attività  che DEVE essere fatta dal client, l’applicazione della firma al documento PDF/A è un’attività  che viene fatta lato server.

Il secondo passo da eseguire è l’inizializzazione dell’algoritmo di firma digitale sui PDF/A :

 // step 2 : inizializzazione procedura di firma
 // operazione lato server
 ...
 HttpPost httppost = new HttpPost(DIGITAL_SIGNATURE_INIT);
 // bisogna ora inizializzare la procedura di firma digitale per
 // ottenere l'handle
 // l'handle ricevuto va poi passato alle chiamate successive
 // nessun documento viene modificato in questa fase
 // devo passare l'handle di una directory parent comune
 // di tutti i documenti che andrà a firmare
 String req = "{"nodeRef":""+parentNodeRefId+""}";
 ByteArrayEntity body = new ByteArrayEntity(req.getBytes());
 httppost.setEntity(body);
 HttpResponse response = httpclient.execute(targetHost, httppost,
                                        localcontext);
 HttpEntity entityResp = response.getEntity();
 InputStream is = entityResp.getContent();
 JSONObject inputJson=null;
 try {
 inputJson = JSONObject.fromObject(new String(loadResponse(is),
                                       ENCODING));
 } catch (UnsupportedEncodingException e) {
 // not possible
 }
 System.out.println(inputJson);
 // imposto l'handle per la prima volta, viene sempre ripassato
 // alle chiamate successive
 digitalSignatureArea = inputJson.getString("digitalSignatureArea");
 EntityUtils.consume(entityResp);

Eseguita questa attività  (lato server) abbiamo inizializzato l’algoritmo di firma. Abbiamo passato come parametro il nodeRef dello space parent del documento che andrè  firmato e riceviamo come risultato un handle (digitalSignatureArea) che dovremo salvare e ripassare alle chiamate successive.

Ora che abbiamo inizializzato l’algoritmo, è necessario eseguire la prima operazione lato client, dobbiamo scegliere il certificato da utilizzare :

 // step 3 : l'handle va passato al client di firma
 // (che parla con il lettore di smart card) per
 // eseguire la scelta del certificato
 // operazione lato client
 // il DRIVER ed il PIN dipendono dall'utente, li dovrebbe digitare lui
 // sinekarta espone un webscript che lista i driver definiti lato server
 // parto dal presupposto che ci sia solo un certificato caricato nella
 // smart card, uso il primo per la firma
 SinekartaDigitalSignatureClient client =
            new SinekartaDigitalSignatureClient(digitalSignatureArea);
            // importante : passare l'handle ricevuto in init
 client.setDriver(DRIVER);
 client.setPin(PIN);
 client.start();
 // contatta il lettore di smart card per ottenere la lista
 // dei certificati
 Map<X509Certificate, String> list = client.certificateList();
 // importante, aggiornare l'handle per ripassarlo
 // al server per la vase successiva
 digitalSignatureArea = (String)list.values().toArray()[0];
 client.close();

Il client di firma è attualmente disponibile solo in java, se qualche bravo sviluppatore volesse crearne una versione in un linguaggio diverso, è bene accetto. In caso dobbiate implementare un client web, il client è disponibile anche sottoforma di applet.

Al client vanno passati due parametri importanti : il driver da utilizzare per accedere alla smart card (leggi qui per saperne di più) ed il PIN per accedere ai servizi della carta.

L’handle ritornato dalla fase di inizializzazione (step 2) viene passato al client di firma che restituisce un elenco di certificati. A ciascun certificato è associato il nuovo handle che dovrà essere passato avanti.

L’utente dovrà  scegliere tra i certificati restitutiti (list.values().toArray()) quello che intende utilizzare, per semplicità  l’esempio prende il primo.

Una volta scelto il certificato è necessario chiamare un secondo servizio sinekarta lato server che calcola l’impronta del documento :

 // step 4 : preparo i dati di firma per il/i documento/i da firmare
 // questo step può essere ripetuto tante volte, quanti sono i
 // diversi motivi di firma
 // ogni chiamata può contenere diversi documenti, verranno tutti
 // firmati con lo stesso motivo (descrizione) di firma
 // operazione lato server
 ...
 HttpPost httppost = new HttpPost(DIGITAL_SIGNATURE_PREPARE_AND_ADD);
 // per ciascun documento (o elenco di documenti a parità  di descrizione)
 // devono essere calcolati i dati di firma
 // importante : l'handle restituito dal client di firma va ripassato
 // non vengono modificati documenti in questa fase
 String req = "{" +
 ""digitalSignatureArea" : ""+digitalSignatureArea+"", " +
 ""signDescription" : ""+descrizioneMotivoFirma+"", " +
 ""signLocation" : ""+localitaFirma+"", " +
 ""nodeRefs":""+nodeRefId+""" +
 "}";
 ByteArrayEntity body = new ByteArrayEntity(req.getBytes());
 httppost.setEntity(body);
 HttpResponse response = httpclient.execute(targetHost, httppost,
                                                     localcontext);
 HttpEntity entityResp = response.getEntity();
 InputStream is = entityResp.getContent();
 JSONObject inputJson=null;
 try {
 inputJson = JSONObject.fromObject(new String(loadResponse(is),
                                               ENCODING));
 } catch (UnsupportedEncodingException e) {
 // not possible
 }
 System.out.println(inputJson);
 // il server ha processato i dati di firma, recupero il nuovo
 // handle da passare al client
 digitalSignatureArea = inputJson.getString("digitalSignatureArea");
 EntityUtils.consume(entityResp);

In questa seconda chiamata server devono essere indicati alcuni dati importanti : prima di tutto l’handle che ci è stato restitutito dal client nella fase di scelta del certificato (digitalSignatureArea). Poi devono essere passati due dati descrittivi che indicano la descrizione del motivo di firma e la località  in cui viene apposta la firma (signDescription, signLocation). Alla fine viene passato l’elenco (separato da “,”) dei nodeRef che devono essere digitalmente firmati. Anche in questo caso il formato dei nodeRef deve essere tipo questo : workspace://SpacesStore/87350b02-32ab-4787-98d0-3daa1c0b7b01

Ciascun documento indicato deve essere un PDF/A.

Anche in questo caso il servizio di sinekarta torna l’handle modificato che deve essere passato alla fase successiva.

L’impronta calcolata deve essere digitalmente firmata, deve quindi essere calcolata la firma digitale :

 // step 5 : l'handle va passato al client di firma
 // (che parla con il lettore di smart card)
 // per eseguire la vera e propria firma
 // operazione lato client
 SinekartaDigitalSignatureClient client =
           new SinekartaDigitalSignatureClient(digitalSignatureArea);
           // attenzione : gli passo l'handle ricevuto dalla fase 4
 client.start();
 // è importante aggiornare l'handle con i dati ricevuti dal client
 digitalSignatureArea = client.executeDigitalSignature(null);
// potrei passargli un listener che mi avvisa dell'avanzamento,
// ma per questo test è inutile
 client.close();

Anche in questo caso è necessario passare al client l’handle che verrà  restituito modificato per la fase successiva.

Come ultimo passo è necessario applicare la firma digitale al documento PDF/A, ecco come :

 // step 6 : chiudo e applico la firma a tutti i documenti;
 // da eseguire una sola volta alla fine del processo
 // operazione lato server
 ...
 HttpPost httppost = new HttpPost(DIGITAL_SIGNATURE_APPLY);
 // devo passare l'handle ricevuto dal client
 // devo passare l'handle di una directory parent comune
 // di tutti i documenti che andrà a firmare
 // i documenti vengono aggiornati solo in questa fase.
 // la procedura lasciata a metà  non modifica i documenti
 // PDF precedentemente creati
 String req = "{" +
 ""digitalSignatureArea" : ""+digitalSignatureArea+"", " +
 ""nodeRef":""+parentNodeRefId+""" +
 "}";
 ByteArrayEntity body = new ByteArrayEntity(req.getBytes());
 httppost.setEntity(body);
 HttpResponse response = httpclient.execute(targetHost, httppost,
                                                  localcontext);
 HttpEntity entityResp = response.getEntity();
 InputStream is = entityResp.getContent();
 JSONObject inputJson=null;
 try {
 inputJson = JSONObject.fromObject(new String(loadResponse(is),
                                              ENCODING));
 } catch (UnsupportedEncodingException e) {
 // not possible
 }
 System.out.println(inputJson);
 EntityUtils.consume(entityResp);

Il servizio riceve in input l’handle (digitalSignatureArea) che ci siamo portati dietro dall’inizio e il nodeRef dello space parent del documento che abbiamo firmato; lo stesso che abbiamo passato al momento dell’inizializzazione (step 2).

Se le 5 (+1) fasi si sono completate correttamente, abbiamo applicato correttamente la firma digitale al nostro documento.

Ora potete divertirvi anche in autonomia ad utilizzare i servizi di sinekarta.

Sinekarta espone diversi servizi, tutti in modalità  simili a quelle esposte in questo articolo. Più avanti esploreremo altri servizi.

Annunci

Pubblicata la versione 2.0 beta di sinekarta


I più attenti di voi avranno notato che ieri è stata pubblicata la nuova versione di sinekarta.

Questa nuova versione introduce così tante nuove funzionalità  che abbiamo deciso di fare un salto anche con la numerazione, passando alla versione 2.0.

Ma quali sono queste nuove funzioni?

Prima i tutto abbiamo APERTO sinekarta!

Una funzionalità  che, ad oggi, pochi (nessuno?) software di firma digitale e conservazione sostitutiva hanno, riguarda la possibilità  di essere utilizzati, oltre che da esseri umani, anche da altri software.

Sfruttando alcune caratteristiche di Alfresco (i famosi webscript) abbiamo realizzato delle API (sottoforma di servizi REST) per applicare la firma digitale e la marca temporale. Queste API sono completamente slegate dal client Alfresco, possono essere quindi utilizzate da qualsiasi software per accedere ai servizi che sinekarta mette a disposizione.

Non solo, essendo REST uno standard (di fatto) basato su XML (o json) e su HTTP(s), è possibile accedere ai servizi di sinekarta anche tramite applicazioni scritte in linguaggi diversi da Java.

Su questo argomento tornerò la prossima settimana con un articolo che guida passo passo lo sviluppatore alla scrittura di un client.

La seconda importante innovazione introdotta in sinekarta riguarda Share.

Per chi non lo sapesse Share è il client di Alfresco di nuova generazione. Sinekarta era, fino a ieri, implementato  per essere utilizzato esclusivamente tramite l’interfaccia explorer di Alfresco. L’implementazione di Share ce l’hanno chiesta molti utenti, non era più possibile aspettare oltre.

L’ultima importante funzione (che sarà rilasciata con la versione 2.0 RC1) riguarda il file delle impronte per l’agenzia delle entrate.

La produzione di questo file mancava in sinekarta rendendo, di fatto, lo strumento inadeguato alla conservazione dei documenti fiscali. Dai primi di Dicembre sarà  possibile produrre questo file.

In aggiunta a questi tre principali filoni abbiamo realizzato diverse funzionalità  minori.

Abbiamo creato un’azione per permettere lo spostamento di uno o più documenti già  presenti in Alfresco dentro l’archivio sinekarta; un’altra azione permette di firmare digitalmete e marcare temporalmente un generico documento, indipendentemente dalla conservazione che ne verrà  fatta. Abbiamo eliminato javasign, strumento che, in passato, ci ha generato così tanti problemi e grattacapi.

Insomma, ina vera e propria rivoluzione all’insegna dell’usabilità.

Per chi volesse approfondire è disponibile, come sempre, la roadmap che descrive il percorso che seguiremo nei rilasci di questa versione 2.0 : http://sourceforge.net/apps/trac/sinekarta/roadmap

Vorrei chiudere l’articolo dando ufficialmente il benvenuto a Nicola Savino che si è recentemente unito al progetto sinekarta.

Nicola è un esperto a livello nazionale, uno dei professionisti più attivi nell’ambito della conservazione sostitutiva; le sue competenze e conoscienze aggiungeranno qualità  a sinekarta, permettendone una crescita più robusta e rapida.

Nicola è anche owner del gruppo linked-in Conservazione Sostitutiva e Fatturazione Elettronica, uno dei gruppi più interessanti e ricco di interventi che trattano questo argomento.

Buon lavoro Nicola!

Chi mi dice che la firma digitale e la marca temporale apposte da sinekarta siano validi?


Spesso le aziende che scoprono (o a cui viene proposto) sinekarta si chiedono come fare a fidarsi della qualità  di un progetto open source.

In particolare desiderano maggiori garanzie riguardo l’apposizione della firma digitale e della marca temporale apposte da sinekarta.

Il processo di conservazione sostitutiva è completamente basato su queste due fondamenta, se questi algoritmi non fossero applicati correttamente o se non rispettassero le regole dell’attuale normativa tutto il processo di conservazione sarebbe nullo.

Per sapere se i documenti digitalmente firmati (e/o temporalmente marcati) sono validi vi proponiamo due strumenti forniti da altrettante importanti entità , una di livello nazionale ed una di livello internazionale.

Il primo strumento che potete utilizzare per verificare i documenti prodotti da sinekarta è il plugin per la firma digitale dell’Acrobat Reader, lo potete scaricare a questo indirizo : http://www.adobe.com/it/security/italiandigsig.html

Questo strumento è prodotto da Adobe, l’azienda che, quasi vent’anni fa, ha creato lo standard PDF e che, nel 2005, ha creato il formato PDF/A (PDF for Archive).

L’altro strumento che potete usare è prodotto da InfoCert. InfoCert è una delle aziende che, in Italia, è più attiva su questi temi.

E’ un Ente Certificatore (Certification Ahtority), è uno dei leader di mercato per i processi di Conservazione Sostitutiva e per i servizi di Posta Elettronica Certificata (PEC).

Insomma, InfoCert è uno dei punti di riferimento per la firma digitale e per la marca temporale in Italia.

Un servizio che InfoCert mette a disposizione gratuitamente permette la verifica delle firme digitale e/o delle marche temporale apposte ai documenti.

Il bello è che questo servizio non richiede installazione di software: è possibile utilizzarlo direttamente on-line tramite questo sito internet : https://www.firma.infocert.it/utenti/verifica.php

Questi strumenti non valgono solo per sinekarta, servono a validare qualsiasi documento prodotto con qualsiasi strumento.

Bene, se vi troverete nella condizione di dover dimostrare la bontà  di sinekarta, ora avrete l’aiuto di due aziende leader nei propri settori.