Firma digitale: firmiamo un documento PDF/A


Prima di tutto un doveroso GRAZIE a Giuseppe, che, tramite la discussione sul gruppo Il Mercato Italiano del Lavoro di linkedin, mi ha aiutato fare chiarezza sulla differenza tra Carta Nazionale dei Servizi (CNS) e Firma Digitale.

Devo ammettere che non mi ero posto il problema, ero convinto che le due cose fossero una unica…

Invece non è cosi! La CNS è “una smart card per accedere ai servizi online della Pubblica Amministrazione su tutto il territorio nazionale”, questo è quanto indicato nel sito http://www.progettocns.it/. Di fatto la CNS è un contenitore nel quale possono essere “caricati” diversi servizi, tra i quali la firma digitale.

Un elenco di servizi abilitati all’utilizzo della CNS oggi attivati dalle Pubbliche Amministrazioni è disponibile sul Portale Nazionale del Cittadino (per ora non funziona, ma spero che nei prossimi giorni possa godere di miglior salute…).

Ma torniamo a noi ed ai nostri argomenti tecnici da smanettoni che tanto ci piacciono.

Nell’ultimo articolo abbiamo visto come utilizzare uno degli strumenti gratuiti trovati in rete per applicare la firma digitale ad un documento.

Non tutti sanno, però che, da un’anno a questa parte, è possibile firmare i documenti, oltre che nello scomodo formato p7m, anche in un più semplice PDF. Per chi volesse saperne di più, nel wiki di progetto trovate tutti i riferimenti del caso.

Messaggio per chi utilizza il noto software di infocert, lo sapevate che (parlo esclusivamente della versione gratuita) dike è in grado di verificare anche la firma di un documento PDF, oltre che di un p7m? Dike non sembra però in grado di produrre file PDF come risultato della firma.

Come è possibile firmare un PDF? In realtà è più semplice di quello che sembra, in rete si trovano diversi esempio, sia applicati alle realtà internazionali che applicate a quelle italiane. In particolare mi rifaccio (ma gaurda un po’) al software che abbiamo deciso di utilizzare per sinekarta : javasign.

Nel sito di javasign è presente una paginetta con un pezzo di codice java che permette di firmare un PDF, eccola : http://javasign.sourceforge.net/pdf.shtml

Ovviamente questo è stato il primo esempio che ho fatto girare sul mio PC al quale ho attaccato il lettore di smartcard nel quale ho inserito la mia carta nazionale dei servizi contenente la mia firma digitale…. fiuuuuuuu, sembrava una strofa della canzone di branduardi “alla fiera dell’est”

ecco il codice :

Security.addProvider(new BouncyCastleProvider());
String driver = “incryptoki2.dll”;
String KEY_LABEL = “DSPrivateKey#0”;
String PIN = “********”;
String SIGN_PIN = “000000”;
Calendar now = Calendar.getInstance();
Certificate[] certs = new Certificate[1];
// connessione al lettore smartcard per ottenere il certificato
SinekartaCryptokiGenerator p7genSC = new SinekartaCryptokiGenerator(driver, KEY_LABEL, PIN, SIGN_PIN);
certs[0] = p7genSC.getCertificate();
// documento in input
PdfReader reader = new PdfReader(PDF_PREFIX+PRIMO_PDF);
// documento in output
FileOutputStream fout = new FileOutputStream(PDF_PREFIX+”signed_”+PRIMO_PDF);
// inizio procedura di firma
PdfStamper stamper = PdfStamper.createSignature(reader, fout, ”);
// definisco i cirteri di visualizzazione della firma
PdfSignatureAppearance sap = stamper.getSignatureAppearance();
sap.setCrypto(null, certs, null,PdfSignatureAppearance.SELF_SIGNED);
sap.setReason(“Esempio di firma digitale applicata ad un documento PDF/A”);
sap.setLocation(“Italy”);
sap.setExternalDigest(new byte[128], new byte[20], “RSA”);
sap.setProvider(“sinekarta/javasign”);
sap.setSignDate(now);
sap.preClose();
PdfPKCS7 sig = sap.getSigStandard().getSigner();
// creo la firma del documento
byte[] content = streamToByteArray(sap.getRangeStream());
byte[] fingerprint = MessageDigest.getInstance(“SHA-1”, “BC”).digest(content);
byte[] signatureBytes = p7genSC.buildSignatureFromDigestedContent(fingerprint);
// appongo la firma al documento
sig.setExternalDigest(signatureBytes, null, “RSA”);
sig.setLocation(sap.getLocation());
sig.setReason(sap.getReason());
sig.setSignName(((X509Certificate)certs[0]).getSubjectX500Principal().getName());
sig.setSignDate(now);
// scrivo la firma e chiudo il PDF
PdfDictionary dic = new PdfDictionary();
dic.put(PdfName.CONTENTS, new PdfString(sig.getEncodedPKCS1()).setHexWriting(true));
sap.close(dic);

e questo è il risultato : signed_HelloWorld.pdf

E’ stato veramente molto facile… Ho anche provato a leggere il documento tramite dike, per verificare la firma digitale apposta, ovviamente la firma è valida!!!

Annunci

17 Responses to Firma digitale: firmiamo un documento PDF/A

  1. Stai facendo un gran lavoro, grazie. Anche se lo dovessero usare in pochi ne sarà comunque valsa la pena! Buona la dritta sulla firma in pdf.
    Francesco.

  2. Marco says:

    Ciao!

    Ottimo tutorial!

    Stavo però provando ad aggiungere le protezione contro la modifica abilitando solo la stampa:

    stamper.setEncryption(null, “********”.getBytes(), PdfWriter.ALLOW_PRINTING, true);

    Acrobat dice che la firma è ok, ma quando la verifico con dike mi dice che c’è un errore nel certificato X.509.

    Che tu sappia, tralascio qualcosa?

    Ciao e grazie!!!
    Marco

  3. Ciao Marco,
    prima IMPORTANTISSIMA notizia, questo codice non è più valido!!!! Ovvero, il codice, ovviamente, funziona ancora, ma la normativa è cambiata. La firma SHA-1 non è più valida, per essere valida la firma digitale deve essere applicata utilizzando l’algoritmo SHA-256.
    In questo articolo (http://localhost/2010/09/22/cambia-il-formato-della-firma-digitale-come-e-quando/) puoi trovare maggiori dettagli.
    Probabilmente dike ti dice che la firma non è valida proprio perchè è stato utilizzato l’algoritmo SHA-1 e non l’SHA-256.
    Ovvero, la firma è applicata bene, ma la firma digitale non è valida secondo la nostra normativa.
    Se hai problemi nell’utilizzo di sinekarta puoi scrivere sul nostro forum di progetto.
    Se invece il tuo problema è di utilizzare javasign per il tuo progetto software, ti devo dare una bruttissima notizia. Il progetto javasign è morto. I proprietari non lo manutengono più e non rispondono alle e-mail.
    Anche noi, con sinekarta, stiamo valutando di eliminarlo per passare ad un’altro progetto che stiamo valutando.
    Il progetto in questione è j4sign, l’autore è veramente molto preparato e disponibile a supportare gli utenti.

  4. Mutui Online says:

    Articolo interessante. In rete si trovano sempre le stesse cose ma su questo blog ci sono spunti utili.

  5. Alessandro says:

    Ciao, ci sono novità a rigurado ? anche la mia ditta deve aggiornare i propri programmi per la firma digitale e stiamo cercando una libreria che supporti lo sha256
    Questo j4sign è valido ? oppure altre librerie java a pagamento ?

  6. Se sei alla frutta puoi studiarti i sorgenti di sinekarta.
    Oppure contattare jenia software per una collaborazione / consulenza

  7. Alessandro says:

    grazie mille dell’informazione

  8. Alessandro says:

    scusa andrea, sto facendo qualche prova.. ma includendo le nuove librerie di sinekarta non dovrebbe essere ovviato il problema ?
    cioè non basta importare nel mio progetto le nuove lib e usare sempre il codice riportato in questo articolo (ovviamente cambiando l’algoritmo da sha1 a sha2) ?

  9. Federico says:

    dove posso trovare il jar che contiene questa classe SinekartaCryptokiGenerator?

  10. sinekarta è un progetto open source.
    I sorgenti sono liberamente scaricabili da sourceforge. Le indicazioni su come ottenere sorgenti ed eseguibili le potete trovare partendo dal sito di progetto : http://www.sinekarta.org

  11. Fiore says:

    Ciao, è un articolo molto interessante, peccato che non sono un esperto! Potresti spiegarmi in parole più semplici come usare JavaSign per apporre la firma digitale e magari dirmi se questa ha validità legale per il diritto d’autore? Grazie mille. Fiore.

  12. Ho scritto un articolo che descrive come sia possibile usare la firma digitale e la marca temporale per tutelare parzialmente il diritto d’autore : http://localhost/2011/02/09/la-marca-temporale-come-stratagemma-per-proteggere-dal-plagio-un-testo-inedito/

  13. Luca says:

    Ho letto alcuni articoli ed ho trovato il progetto molto interessante e valido.
    Sono in ambiente di test e la domanda mi sorge spontanea: c’è qualche modo per simulare un certificato e darlo in pasto a sinekarta bypassando card e lettore?
    In alternativa anche una creazione e poi esportazione su card in modo da non intaccare il workflow del software andrebbe bene.
    L’altra cosa che ho notato è un errore riguardo una libreria non presente (scegliendo driver che utilizza questa dll e clickando su carica certificati)
    “java.io.IOException : The specified module could not be found. incryptoki2.dll”
    La libreria mi verrà fornita con il rilascio della carta? E nel caso di autocreazione come sopra, come risolvo il problema?
    Grazie mille e complimenti

  14. Luca says:

    Ho trovato le librerie all’indirizzo
    http://postecert.poste.it/firmadigitale/download_libreriesmartcard.shtml

    Vista la predisposizione del software, non sarebbe corretto includerle nell’installazione del software sinekarta?

    è possibile utilizzare sinekarta con i certificati su chiavette usb?
    grazie

  15. Ciao Luca, benvenuto su questo blog.
    So che esistono dei simulatori di smartcard ma non sono un esperto e non so guidarti.
    L’errore che hai ottenuto è legato alla libreria che ti deve essere fornita con la smart card. Sinekarta non ne include volutamente.
    Sinekarta funziona anche con i token USB, basta dargli la libreria giusta.
    puoi procurarti la smart card alla camera di commercio, costa circa 25 euro. Oltre alla carta hai bisogno di un lettore : circa 10 euro. Il token invece ne costa 70.

  16. Nicola says:

    Salve, riguardo alla firma digitale del PDF, volevo sapere se c’è un metodo per poter firmare SOLO l’impronta del PDF lato client e poi lato server ricomporre l’impronta firmata e il PDF originale. Avrei bisogno di questo in quanto i file che devo firmare spesso sono molto pesanti (anche oltre i 100 mb) e trasportare il PDF dal server al client per la firma e poi rispedirlo sul server una volta firmato mi crea spesso dei problemi. Sarebbe molto più semplice firmare sul client solo l’impronta e ricomporre il tutto lato server

  17. E’ proprio quello che fa sinekarta.
    Il documento risiede sempre e solo sul DMS (alfresco).
    Sinekarta calcola (lato server) l’impronta del documento e la invia al browser.
    Sul browser l’applet di sinekarta calcola la firma dell’impronta ricevuta e risponde al server.
    Il server la applica al documento.
    Buona parte del lavoro svolto da sinekarta implementa questa funzionalità.

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...

%d blogger hanno fatto clic su Mi Piace per questo: