Istruzioni per firmare digitalmente (CAdES compatibile)

in ambiente Linux e Windows con OpenSSL e smartcard (per esperti o sviluppatori)

Novità:
Siamo lieti di annunciarvi che il 27/01/2019 gli sviluppatori di OpenSSL hanno approvato ed eseguito il commit nel ramo ufficiale (github.com/openssl/openssl) del nostro codice che integra in OpenSSL il supporto CAdES e il 7/9/2021 è stata finalmente rilasciata la versione stabile di OpenSSL 3.0 (vedi annuncio).

D'ora in poi, quindi, non ci sarà più bisogno di applicare la patch ma sarà sufficiente scaricare e compilare la versione ufficiale di OpenSSL 3, oppure installare le versioni più recenti delle distribuzioni Linux.
Ad esempio Ubuntu/Lubuntu/Xubuntu dalla versione 22.04, rilasciata ad aprile 2022, contiene la release 3.0.2 di OpenSSL.
Grazie a tutti coloro che hanno contribuito a questo risultato con test e consigli.

La vecchia pagina delle istruzioni su come firmare con OpenSSL (versioni 1.1 e 1.0) l'abbiamo spostata qui blia.it/firmadigitale/old.php.




Engine Pkcs11

Con la nuova versione dell'engine pkcs11 che stiamo sviluppando non ci sarà piú bisogno di installare OpenSC (né per pkcs11-tool né per l'engine pkcs11) per prelevare il certificato e gli ID e label dalla smart card, potremo fare tutto con OpenSSL. Nel caso invece volessimo usare OpenSC possiamo usare le istruzioni presenti in fondo alla pagina.

  1. Scarichiamo da qui: github.com/opensignature/openssl/archive/signonly-pkcs11-engine.zip i sorgenti e compiliamoli con:

    ./config --openssldir=/usr/local/ssl
    make
    make install

    Se la compilazione non ha dato errore eseguite openssl version che vi darà OpenSSL 3.0.0-dev xx XXX xxxx

  2. Creiamo un file di configurazione per openssl, ad esempio openssl.cnf in cui scriviamo
    openssl_conf = openssl_init
    [openssl_init]
    engines = engine_section
    [engine_section]
    pkcs11 = pkcs11_section
    [pkcs11_section]
    engine_id = pkcs11
    dynamic_path = /usr/local/ssl/engines/pkcs11.so
    MODULE_PATH = /usr/lib/libbit4xpki.so
    (ovviamente i percorsi dei file possono cambiare)

  3. Con openssl storeutl -engine pkcs11 'pkcs11:' avremo l'elenco delle coppie [chiave privata / chiave pubblica] presenti nella smart card. Scarichiamo il certificato corrispondente alla chiave privata con cui firmeremo: openssl storeutl -out certificato.pem -engine pkcs11 'pkcs11:type=cert;id=DS3' (DS3 è l'ID della chiave)

  4. creiamo un file con comandi bash, ad esempio firma.sh in cui mettiamo:
    OPENSSL_CONF=./openssl.cnf
    export OPENSSL_CONF
    openssl cms -nosmimecap -md sha256 -nodetach -binary -cades -stream -outform DER -sign -signer certificato.pem -inkey DS3 -keyform engine -in $1 -out $1.p7m -engine pkcs11
    (N.B. se si tratta di aggiungere una firma ad un documento precedentemente firmato, quindi nel caso di controfirma o firme multiple occorre sostituire la terza riga dello script con:
    openssl cms -nosmimecap -md sha256 -nodetach -binary -cades -stream -outform DER -resign -signer certificato.pem -inkey DS3 -keyform engine -inform der -in $1 -out $1.p7m -engine pkcs11 )

  5. siamo pronti per firmare: firma.sh miotesto.txt

  6. se vogliamo qualcosa di "grafico" possiamo usare il tool zenity e lo script sarà:
    export OPENSSL_CONF=./openssl.cnf
    if pin=$(zenity --forms --text "Inserisci il pin della smartcard" --width=300 \
    --title="Firma digitale by Blia.it" --add-password=PIN)
    then
    if file=$(zenity --file-selection)
    then
    openssl cms -nosmimecap -md sha256 -nodetach -binary -cades \
    -stream -outform DER -sign -signer certificato.pem -inkey \
    "pkcs11:id=DS3;type=private;pin-value=$pin" \
    -keyform engine -in $file -out $file.p7m -engine pkcs11
    zenity --info --width=600 --text="File firmato $file.p7m"
    fi
    fi

Su Windows la procedura di firma è molto simile.
  1. Su blia.it/firmadigitale/openssl.zip c'è il file zippato contenente l'eseguibile (con supporto CAdES) e le librerie .dll
    Su blia.it/firmadigitale/openssl3.2.zip l'ultima versione di OpenSSL (3.2), ancora non testato.

  2. Creiamo il solito file openssl.cnf dove inseriremo queste righe:
    openssl_conf = openssl_def
    [openssl_def]
    engines = engine_section
    [engine_section]
    pkcs11 = pkcs11_section
    [pkcs11_section]
    engine_id = pkcs11
    dynamic_path = pkcs11
    MODULE_PATH = bit4ipki
    p.s. non mettere l'estensione .dll, openssl l'aggiunge al file, quindi per l'engine pkcs11.dll inserire solo pkcs11 e cosí pure per bit4ipki

  3. nel file firma.cmd scriviamo:
    set OPENSSL_CONF=openssl.cnf
    openssl cms -nosmimecap -md sha256 -nodetach -binary -cades -stream -outform DER -sign -signer certificato.pem -inkey DS3 -keyform engine -in %1 -out %1.p7m -engine pkcs11

Driver PKCS#11

incryptoki2.dll (Incard)
bit4ipki.dll (Incard)
bit4opki.dll (Oberthur)
bit4xpki.dll (Incard e Oberthur)
bit4cpki.dll (HID)
bit4tpki.dll (HID)
OCSCryptoki.dll (Oberthur)
Cryptoki.dll (Oberthur)
asepkcs.dll (Athena)
SI_PKCS11.dll (Siemens)
CardOS_PKCS11.dll (Siemens)
cmP11.dll (CryptoVision)
cvP11_M4.dll (CryptoVision)
IpmPki32.dll (Siemens)
IPMpkiLC.dll (Siemens)
IpmPkiLU.dll (Siemens)
eTPKCS11.dll (SafeNet)
stPKCS11.dll (SafeNet)
inp11lib.dll (Incard)
opensc-pkcs11.dll (OpenSC)
SissP11.dll (Siemens)
aetpkss1.dll (Gemalto)
bit4p11.dll (Athena)
siecap11.dll (Siemens)

libbit4opki.so (Oberthur)
libbit4ipki.so (Incard)
libbit4xpki.so (Incard e Oberthur)
opensc-pkcs11.so (OpenSC)
libASEP11.so (Athena)
libeTPkcs11.so (SafeNet)
stPKCS11.so (SafeNet)
libsiecap11.so (Siemens)

libopensc.dylib (OpenSC)
libbit4xpki.dylib (Incard e Oberthur)
libbit4ipki.dylib (Incard)
libbit4opki.dylib (Oberthur)
libASEP11.dylib (Athena)
libeTPkcs11.dylib (SafeNet)
libaetpkss.dylib (Gemalto)
libOcsCryptoki.dylib (Oberthur)

Per riconoscere che tipo di carta avete guardate la forma del chip, qui di sotto i chip della carte più diffuse in Italia:

Chip Athena

Chip Incard

Chip Oberthur


Per dubbi, commenti e proposte potete usare l'email in fondo alla pagina. Altre istruzioni scritte da noi li potete trovare sul sito Saela.eu all'indirizzo: saela.eu/openssl. Istruzioni per potere firmare un PDF in modalità PAdES li trovate qui.

Prelevare il certificato tramite OpenSC (https://github.com/OpenSC)
Una volta compilato o scaricato il pacchetto OpenSC, ad esempio su Debian/Ubuntu apt install opensc
pkcs11-tool -O --module /usr/lib/x64-athena/libASEP11.so --login
Using slot 0 with a present token (0x0)
Logging in to "CNS#5...".
Please enter User PIN: 
Data object 655
  label:          'PDATA'
  application:    ''
  app_id:         
  flags:          
Certificate Object; type = X.509 cert
  label:      Firma-Digitale
  subject:    DN: C=IT, O=...
  ID:         12345678
Certificate Object; type = X.509 cert
  label:      CaRoot
  subject:    DN: C=IT, L=...
  ID:         7...
Certificate Object; type = X.509 cert
  label:      CNS0
  subject:    DN: C=IT, O=...
  ID:         4...
Public Key Object; RSA 2048 bits
  label:      Firma-Digitale
  ID:         12345678
  Usage:      encrypt, verify, wrap
  Access:     local
Public Key Object; RSA 1024 bits
  label:      CNS0
  ID:         4...
  Usage:      encrypt, verify
  Access:     local
Private Key Object; RSA 
  label:      Firma-Digitale
  ID:         12345678
  Usage:      decrypt, sign, unwrap
  Access:     sensitive, always sensitive, extractable, local
Private Key Object; RSA 
  label:      CNS0
  ID:         4...
  Usage:      decrypt, sign
  Access:     sensitive, always sensitive, never extractable, local
Prendiamo l'ID del certificato della Firma Digitale (nel nostro caso 12345678)
pkcs11-tool -r -y cert -d 12345678 --module /usr/lib/x64-athena/libASEP11.so --login -o certificato.der

Convertiamo il certificato dal formato DER al formato PEM
openssl x509 -inform der -in certificato.der > certificato.pem

A questo punto possiamo seguire la guida sopra saltando i punti 1) e 3)

lo staff di Blia.it


Blia.it NON utilizza cookie (v. informativa)
Per contattare la redazione di Blia.it potete scrivere a: info@blia.it (attenzione, blia.it non ha nessun rapporto con banche, scuole o altri enti/aziende, i cui indirizzi sono visualizzati al solo scopo di rendere un servizio agli utenti del sito)