quoll file p7m come gestirli

p7m firma digitale: come estrarre il contenuto

See the article in English

Firma digitale e file con estensione p7m

Vi sarà capitato di dover aprire un file con estensione p7m, ovvero quelli provenienti dalla PEC e firmati digitalmente.
Beh! a me è capitato qualche giorno fa.

Non avendo un software che gestisce direttamente il file ho perso un po’ di tempo ad estrarre sia il contenuto che le firme e verificarne la correttezza.

Quindi per non fare perdere altro tempo anche a voi (ma anche a me quando mi ricapiterà di nuovo) credo che un articolo sia necessario.

Cos’è il formato p7m

Il file p7m è un file di firma digitale nel formato CAdES (CMS Advanced Electronic Signatures) che è un’estensione del Cryptographic Message Syntax (CMS) che è basato a sua volta su PKCS#7.
Quindi il file p7m non è altro che un contenitore che incapsula sia il documento originale (non criptato) che la firma digitale personale e quella della catena della CA che ha rilasciato il certificato.
Andando per ordine nel file p7m troviamo:
– nei primi byte  l’header PKCS#7
– poi viene il nostro documento originale (non criptato)
– quindi l’hash di firma (che valida per legge il contenuto)
– il certificato digitale personale di chi ha firmato
– ed infine il certificato della CA

Estrazione del documento originale

Consideriamo il caso in cui il documento firmato sia un pdf (documento.pdf.p7m).

Il modo più semplice per visualizzare il pdf incapsulato nel documento.pdf.p7m è quello di aprirlo direttamente con un editor pdf come acroread o okular o evince dato che  l’header PKCS#7 dovrebbe essere di pochi byte e quindi, se rinominiamo il file con estensione pdf quasi sicuramente, i lettori standard riusciranno a visualizzare direttamente il file senza dover estrarre il contenuto (magari con qualche messaggio di errore durante l’apertura).
Per far le cose più precise possiamo provare ad editare il file .p7m con “vim” ed eliminare direttamente i primi byte (50 – 100) sino a %PDF-1 (naturalmente lasciando la stringa %PDF-1 come inizio file .pdf).
Dato che ci siamo proviamo ad estrarlo correttamente eliminando anche i byte successivi al fine pdf e cioè la stringa %%EOF.
A questo punto il documento pdf sarà estratto correttamente.

Per estrarlo con un unico comando, senza editarlo possiamo utilizzare il comando

perl -ne 's/^.*%PDF/%PDF/; print if /%PDF/../%%EOF/' documento.pdf.p7m >documento.pdf

oppure utilizziamo il comando openssl con il parametro smime per la verifica della firma (-verify)

openssl smime -verify -noverify -in documento.pdf.p7m -inform DER -out documento.pdf

Estrazione del certificato

Per estrarre il certificato digitale personale di chi ha firmato basta usare openssl con il comando

openssl pkcs7 -inform DER -in documento.pdf.p7m -print_certs -out cert.pem

il certificato è nel file cert.pem e se si vuole visualizzare in modo testuale basta il comando per i certificati x509

openssl x509 -in cert.pem -text -noout

Verifica della firma di tutto il documento

Per verificare la firma bisogna utilizzare il comando

openssl smime -in documento.pdf.p7m -inform DER -verify -out documento.pdf

mentre per verificare la validità del semplice certificato il comando è

openssl verify cert.pem

Naturalmente, provando così com’è, la verifica fallisce (“unable to load certificate“) perché non abbiamo i certificati di fiducia della CA.
Tali Certificate Authority sono state definite per legge italiana e sono registrati sul CNIPA, che dal dicembre 2009  è diventato DigitPA, come portafoglio di certificati XML e li ho trovati sullo stesso sito all’indirizzo  https://eidas.agid.gov.it/TL/TSL-IT.xml (che sostitusce il vecchio) .
Per far in modo che openssl li gestisca bisogna metterli nel suo formato quindi:

wget -O - https://eidas.agid.gov.it/TL/TSL-IT.xml | perl -ne 'if (/<X509Certificate>/) {
s/^\s+//; s/\s+$//;
s/<\/*X509Certificate>//g;
print "-----BEGIN CERTIFICATE-----\n";
while (length($_)>64) {
print substr($_,0,64)."\n";
$_=substr($_,64);
}
print $_."\n";
print "-----END CERTIFICATE-----\n";
}' >CA.pem

Per gli aggiornamenti allo script, per la versione solo bash o per quelle in php consultare https://github.com/eniocarboni/getTrustCAP7m

In tal modo abbiamo tutti i certificati presenti in un unico file CA.pem, purtroppo anche quelli che forse sono scaduti.
Anche se scaduti potremmo aver bisogno di verificare un file vecchio e quindi ci possono servire anche gli scaduti.

Adesso possiamo verificare il certificato con esito positivo con:

openssl verify -CAfile CA.pem cert.pem

ed il file p7m con il comando:

openssl smime -in documento.pdf.p7m -inform DER -verify -CAfile CA.pem -out documento.pdf

Naturalmente quest’ultimo comando oltreché verificare la validità della firma estrae anche il documento originale.

Collegamenti esterni:

CAdES vedere

CMS vedere

PKCS#7 vedere

Continua a leggere la seconda parte dell’articolo

88 pensieri su “p7m firma digitale: come estrarre il contenuto

    1. Ciao Antonio,
      direi che per creare un p7m dato il file pdf “documento.pdf” basta utilizzare il comando “smime”

      openssl smime -sign -outform DER -binary -md sha256 -in documento.pdf -out documento.pdf.p7m -signer your_priv_certs.crt.pem -inkey your_priv_certs.key.pem -noverify -nodetach
      

      Per l’ultima versione smime, spero anche compatibile con il CNIPA, credo che bisogna utilizzare “cms” al posto di “smime”:

      openssl cms -sign -outform DER -binary -md sha256 -in documento.pdf -out documento.pdf.p7m -signer your_priv_certs.crt.pem -inkey your_priv_certs.key.pem -noverify -nodetach
      

      Perché sia valido a livello legale dovresti controllare il file con qualche tool presente online e fare tutti i controlli possibili.

  1. Io invece ho una cartella zeppa di file in formato .p7m ed ho notato che la ricerca di una stringa di testo di windows non funziona; c’è qualcuno che può suggerire una soluzione?

    1. Ciao Andrea,
      non so bene come funzioni in windows ma non credo che riesca ad indicizzare direttamente i documenti presenti in file .p7m.
      Sotto Linux basta utilizzare un semplice script come questo:

      #! /bin/bash
      
      stringa_da_trovare=$1;
      
      for file in *.p7m; do
        trovato=$(openssl smime -verify -noverify -in "$file" -inform DER  2>/dev/null | pdftotext - - | grep  "$stringa_da_trovare")
        if [ $? == 0 ]; then
          IFS="\n"
          t=$(echo $trovato | sed 's/^/\t/g')
          echo -e "trovato in $file:\n$t"
          IFS=''
        fi
      done

      Supponiamo di salvarlo nel file find_in_p7m.sh nella stessa cartella dove sono i .p7m e supponendo sempre che i .p7m contengano pdf (per gli xml o altro bastano poche modifiche).
      Lanciamo il comando per rendere eseguibile lo script:

      chmod +x find_in_p7m.sh

      e poi supponiamo di dover cercare la stringa “fattura” basta lanciare il comando:

      ./find_in_p7m.sh "fattura"

      che restituisce sia i file .p7m trovati che il contenuto trovato.
      Credo che con powershell dovresti riuscire a far la stessa cosa sotto windows magari scaricandoti pdftotext da http://www.foolabs.com/xpdf/download.html e naturalmente avendo a disposizione openssl (http://gnuwin32.sourceforge.net/packages/openssl.htm)

  2. Buona sera, se volessi estrarre il contenuto pdf da un p7m in php come potrei fare? sul mio host il servizio exec di php non è abilitato e devo usare solo funzioni di php
    Grazie

    1. Ciao Fabio,
      purtroppo credo che in php la libreria OpenSSL (http://php.net/manual/en/ref.openssl.php) non permetta di usare “smime” per estrarre documenti nel formato CAdES (ma forse mi sbaglio e qualcuno mi correggerà).
      Potresti, comunque, provare ad estrarlo direttamente dal file .p7m come l’ho descritto nell’articolo ovvero aprendo il file, saltando tutti i caratteri sino a (ma escluso) %PDF-1 e poi predi tutto sino a %%EOF ed il resto lo tralasci.
      Non dovrebbe esser un operazione difficile (direi poche righe di codice).

      1. Grazie della risposta. Ho provato anche quello ma, soprattutto per i pdf/a, l’estrazione della stringa così come descritto non produce un pdf valido

        1. Ciao Fabio,
          è molto strano che per i pdf/a non funzioni dato che il pdf/a non è altro che un sottoinsieme del pdf dove vengono eliminate tutte le funzioni che non permettono l’archiviazione a lungo termine (ad esempio la crittografia con password del testo).
          Se hai un .pdf.p7m non personale che è possibile visionare prova a postare qui il link per poterlo verificare.

  3. Io ho provato a cancellare le righe che stanno prima di %PDF-1 e tutto ciò che sta dopo %%EOF ma il PDF che ottengo è vuoto. Ho provato anche a lanciare la riga di comando:

    perl -ne 's/^.*%PDF/%PDF/; print if /%PDF/../%%EOF/' documento.pdf.p7m >documento.pdf

    E ottengo comunque un PDF con una pagina sola e completamente bianca

    1. Ciao Roberto,
      Forse nel tuo pdf c’è un’altra stringa %%EOF, magari come commento. In tal caso prova con:

      perl -ne ‘s/^.*%PDF/%PDF/; print if /%PDF/../^%%EOF/’ documento.pdf.p7m >documento.pdf

      dove in tal caso considero che %%EOF deve stare ad inizio riga.
      Inoltre se il file pdf ha delle “modifiche incrementali” (incremental update) o revisioni queste vengono messe in coda aggiungendo i vari pezzi e terminando con un ulteriore %%EOF (ad esempio se il pdf firmato viene modificato e poi rifirmato nelle modifiche).
      In tal caso devi lasciare tutti i %%EOF esistenti sino all’ultimo ed il comando “perl” non funzionerà mentre “openssl” dovrebbe andar sempre bene.
      Fammi sapere se sei in uno di questi casi e se sei riuscito a risolvere.

      1. Ciao Enio,
        grazie innanzitutto della risposta. No anche con quella stringa non riesco, ottengo lo stesso PDF vuoto.

        Alla fine ho usato l’altro tuo suggerimento (openssl) ma ora volevo chiederti una cosa in più se la sai. Sarebbe possibile tramite Java far la stessa cosa usando (immagino) la libreria openssl? Ne sai qualcosa? In questa maniera potrei fare io un .jar al volo che funzionerebbe anche su Windows.

        Grazie e ciao.

  4. Caio Enio,
    bellissimo articolo! Mi hai aiutato a risolvere diverse grane (e a non usare Windows…)
    In questi giorni ho scoperto che mentre alla pubblica amministrazione piacciono molto i file .P7M, spesso all’estero usano firmare i documenti tenendo separati file e firma (che ho scoperto si possono ottenere senza l’opzione -nodetach, quindi generando una “clear signature”).
    Sai se esiste un modo, usando OpenSSL, per fare una sorta di “merging” tra il file e la sua firma (che come standard ha estensione .P7B) ottenendo un file .P7M?
    Complimenti ancora! Ciao.

  5. Ciao Enio,
    di recentissimo mi sono imbattuto nei problemi di firma digitale… e quindi in questo “fantastico” meccanismo messo in piedi dalla nostra PA.
    Sai dov’è possibile trovare la specifica del file P7M? Spero l’abbiano fatta open…
    Poi mi frulla un’altra idea, fatto 30 facciamo 31: chiaro il meccanismo con cui leggo e produco il file P7M con openSSL… ma come recupero la mia chiave privata imprigionata nella smart card che mi hanno dato? Sai se openSSL possa interfacciarsi ai lettori, oppure se c’è qualche tool che possa interaggire?

    Grazie mille e ottimo lavoro!
    Albe

    1. Da quello che ho capito io: usando il driver apposito per la tua smartcard si può estrarre il certificato (io ci sono riuscito) però poi non è possibile usare openssl per generare una CADES a meno di non usare una versione modificata con una patch che, al momento, non è stata accettata nel programma originale. I dettagli li trovi qui: http://www.blia.it/firmadigitale/index.php

  6. Io vorrei conoscere una applicazione che mi apre in serie, ovvero mi estrae immediatamente con un solo right-click da piu file selezionati, il file non firmato.
    Oltre al DIKE che ne apre uno solo ed uno alla volta, ognuno in una finestra separata, non esiste altro ?

    Grazie

  7. è possibile generalizzare gli scripts di estrazione in modo tale che agiscano in batch su più files?

    perl -ne ‘s/^.*%PDF/%PDF/; print if /%PDF/../%%EOF/’ documento.pdf.p7m >documento.pdf
    openssl smime -verify -noverify -in documento.pdf.p7m -inform DER -out documento.pdf

    grazie per l’ottimo articolo

    1. Grazie per i complimenti.
      Per elaborare in batch diversi file .pdf.p7m basta metterli in una directory e lanciare da lì la seguente riga di codice bash:

      for file in *.pdf.p7m; do pdfname=$(basename "$file" .p7m); openssl smime -verify -noverify -in "$file" -inform DER -out "$pdfname"; done 
      1. grazie per la cortese risposta
        anche io sono riuscito a mettere insieme qualcosa del genere (sintassi leggermente differente e meno compatta)

        ############
        for file in *.p7m
        do
        filename=”${file##*/}”
        filename_new=”${filename%.*}”
        openssl smime -verify -noverify -in “$filename” -inform DER -out “$filename_new”
        done

        ##########

  8. è possibile verificare la firma di un documento firmato digitalmente in formato PAdES (pdf) tramite uno script bash?

    grazie e complimenti ancora

  9. È possibile generare un file p7m a partire da un xml con PHP che sia validato dal sito https://postecert.poste.it/verificatore/ ?
    ho provato con:
    openssl_pkcs7_sign(
    __DIR__.’/prova.xml’,
    __DIR__.’/prova.p7m’,
    ‘file://’.__DIR__.’/XXX.pem’,
    [‘file://’.__DIR__.’/XXX.pem’,’123456′],
    array(“To” => “oscar@example.com”, “From: HQ “, “Subject” => “Eyes only”));

    pur creando il file p7m, il file non viene mai validato dal sistema delle poste.
    La PA vuole le fatture tramite sito, con un xml firmato in formato p7m.

    1. Credo che in questo modo riuscirai a firmare il doc xml in pkcs7 ma non ad incapsularlo in un CAdES per avere un p7m.
      Prova con:
      openssl cms -sign … come nel mio primo commento

  10. Ciao, ho approffitato della tua documentazione per farmi uno script che poi ho mutuato da Linux a Win, mentre l’apertura dei *.pdf.p7m o *.doc.p7m mi ha sempre funzionato bene, openssl da’ invece un errore sugli otd.p7m

    Un saluto

    1. Grazie Maurizio del file che mi hai girato.
      Dopo un attento controllo ho visto che il file è in formato pem invece che der quindi la cosa da fare in questa situazione è convertire il file in der.
      Per farlo basta il semplice comando openssl:

      openssl pkcs7 -outform der -in file-originale-pem.odt.p7m -out file-originale-der.odt.p7m

      A questo punto se tutto va bene usiamo il solito comando:

      openssl smime -verify -noverify -in file-originale-der.odt.p7m -out file-originale.odt
  11. Ciao enio, grazie per l’articolo.
    Io ho dei file xml in formato codificati p7m in cui l’xml è stato modificato con l’aggiunta “ciclica” di 4 caratteri di controllo.
    Mi sembra che siano sempre gli ultimi quattro presenti prima dell’inizio dell’xml
    ES: (i 4 caratteri sono ‚è)
    0€ *†H†÷
     €0€10
    `†He 0€ *†H†÷
     €$€‚è

    IT
    01234567890

    00001
    SDI10
    AAAAAA

    060601
    prova@mail.it

    IT
    01234567890

    Societa’ alpha S.r.l.
    ‚è

    Ne sai qualcosa?

    Grazie

    1. Ciao Andrea,
      all’interno dei .p7m ci può esser qualunque documento, il contenuto in genere dovrebbe esser conosciuto sia dal mittente che dal ricevente.
      Prova a chiedere spiegazioni al mittente del tuo messaggio dato che dovrebbe conoscere esattamente cosa ti manda per email.
      Grazie per i complimenti.

  12. Ciao Enio, grazie per l’ottima guida.

    Ciò che sto tentando di fare è estrarre l’allegato contenuto in un file “NomeFile.xml.p7m”.

    Il file xml è ovviamente una fattura elettronica, e c’è il tag “” con all’interno una stringa che a me pareva fosse codificata in base64.

    Quindi ciò che ho fatto è stato:
    · usare openssl per “estrarre” il contenuto “pulito” del file come da tuo esempio, esportandolo in “file.txt”
    · estrarre la sola parte contenuta tra i tag ” ….. ”
    · decodificare la stringa da base64 e provare a scrivere un file con estensione PDF

    Purtroppo mi restituisce un file PDF non valido.

    Ciò che non riesco a capire è in che algoritmo è codificato l’allegato …. mi sfugge qualcosa?

    Ti ringrazio per l’aiuto che vorrai darmi e ti auguro buon lavoro!

    Zak

  13. Buongiorno
    A me servirebbe un programma per windows per convertire un file .xml.p7m in .xml

    Non so usare gli script

  14. Ciao Enio,
    utilizzo openssl per estrarre il contenuto dei file p7m fatture elettroniche ottenendo il file xml originario.
    Il comando usato è:
    smime -verify -noverify -in “nomefile.p7m” -inform DER -out “NomeFile.xml”
    Tutto funziona correttamente, però mi capita su alcuni file p7m che il comando non va a buon fine restituendomi il seguente messaggio
    Error reading S/MIME message
    asn1 encoding routines:asn1_check_tlen
    asn1 encoding routines:asn1_item_ex_d2I
    error in smime
    Sapresti aiutarmi vedi che sei molto preparato su queste librerie.
    Grazie mille

      1. Ciao Enio e ciao Umberto, mi accodo al problema di Umberto per sapere se sono state trovate soluzioni.
        Sono nella sua stessa situazione, ho un fornitore che mi manda un p7m che restituisce gli stessi identici errori, ho provato a leggere l’articolo successivo ma non è in formato PEM, tra l’altro se apro il p7m con un editor di testi non ha neanche un header comprensibile, inizia subito con una serie di caratteri ‘MIIfDAYJKoZIhvcNAQcCoIIe/TCCHvkCAQExDzANBglghkgBZQMEAgEFADCCEI0G’

        Come possiamo capire quale sia il problema? Umberto tu hai risolto?

        Grazie mill

        1. Ciao Paolo,
          da quel che capisco il tuo p7m è in formato PEM ma manca la riga iniziale e finale perché openssl lo possa gestire come tale.
          Puoi provare quindi ad editare il file ed aggiungere in testa la riga
          -----BEGIN PKCS7-----
          ed in fondo
          -----END PKCS7-----
          oppure a convertirlo direttamente in DER standard tramite il comando
          openssl base64 -d -in tuofile.p7m -out tuofile-convertito-der.p7m
          Se il tuo file originale è un’unica riga lunga devi aggiungere il parametro “-A”
          openssl base64 -d -A -in tuofile.p7m -out tuofile-convertito-der.p7m
          Facci sapere se hai risolto

  15. Ciao Enio ti scrivo per risolvere qualche dubbio.
    Mi trovo sul mio gestionale in PHP (che risiede su server condiviso quindi non posso installare applicazioni a piacere) a recuperare le fatture passive da webservice di aruba.
    Tutto ok quando ricevo file XML normali (non firmati) li riesco a passare ad un parser integrato nelle funzioni PHP per attribuirgli un foglio di stile e visualizzarlo.
    Il problema si pone quando i file sono P7M. (ho trovato una funzione in PHP che funziona solo nell’80% delle volte…e si limita a rimuovere da testa e dalla coda la parte di firma, e all’interno del file rimuove i carattari NON utf8). Sfortunatamente nel 20% dei casi però i caratteri non UTF8, in una sequenza di combinazioni sfavorevoli, vengono passati come “buoni” e quindi il file XML estituito in realtà non è pulito e non posso vederlo con un parser di fogli di stile.
    Quindi ho letto di usare openssl che è più sicuro, ma tutti gli esempi che trovo in giro dicono di usare linea di comando per usare openssl. Non mi è permesso installare app esterne sul server.
    Volevo sapere se è possibile usare openssl tramite la libreria integrata di PHP e se si, hai a disposizione un esempio pratico per l’utilizzo.
    Magari che accetti tutti i file (sia XML che P7M) e riconosca da solo se debba elaborarlo oppure no.

    Grazie mille per l’aiuto

    1. anche io preferirei usare php puro, ad esempio con la libreria openssl, ma non ho ancora capito quale sia l’equivalente dei comandi verify.
      mi pare che la libreria openssl abbia problemi con i file in input e output.
      Dove file_get_contents funziona, openssl_pkcs7_verify dà errore sul file (system library:fopen:No such file or directory)

      vedi esempio:

      $str=file_get_contents(__DIR__.”/IT01394200362_5B4Iy.xml.p7m”);
      //echo $str;
      //this works

      openssl_pkcs7_verify(__DIR__.”/IT01394200362_5B4Iy.xml.p7m”,0);
      echo openssl_error_string();echo “\n”;

      //error:02001002:system library:fopen:No such file or directory
      //^^^^^^^^^^^^^^^^^^^^^^^^^^^
      //credo che l’errore sia già qui ma non capisco perchè openssl_pkcs7 non legga il file che file_get_contents legge

      openssl_pkcs7_verify(“./IT01394200362_5B4Iy.xml.p7m”,0,”./out1″);
      echo openssl_error_string();echo “\n”;
      //error:2006D080:BIO routines:BIO_new_file:no such file

      openssl_pkcs7_verify(“./IT01394200362_5B4Iy.xml.p7m”,0,”./out1.pem”, [],”ut.pem”,”./out2″);
      echo openssl_error_string();
      //error:0B084002:x509 certificate routines:X509_load_cert_crl_file:system lib

  16. Come sempre in rete avete scritto tantissime parole ed io che non sono interessato ai dati tecnici e volevo semplicemente aprire un p7m sono giorni che giro intorno e non riesco ad aprirlo e dato che è una e mail dell’agenzia delle entrate (x loro) mi avete tolto 1 anno di vita . Il dono della sintesi che fine ha fatto grazie per il tempo sottrattovi col presente commento.

    1. Ciao Saverio e grazie per il tuo messaggio anche se non interessato all’argomento.
      Se vuoi semplicemente aprire il file contenuto nel .p7m devi installarti un visualizzatore per i p7m (tutti i distributori di firma elettronica devono averne uno gratis).
      Potresti provarne uno qualunque tra quelli in commercio.
      Ad esempio l’Agenzia delle Entrate espone questa pagina con alcuni link per scaricare il software per i p7m.
      Inoltre puoi scaricarti il software Dike di Infocert o Aruba Sign di Aruba oppure verificare direttamente online la firma e scaricare il contenuto nel sito PosteCert.
      Spero ti sia di aiuto.

  17. uso questo comando per i file p7m ….
    openssl smime -in documento.xml.p7m -inform DER -verify -out documento.xml
    per il grosso dei file funziona per alcuni NO … eseguendo in una finestra dos ho il seguente errore :
    C:\D6\openssl>openssl smime -verify -noverify -inform PEM -in aaa.xml.P7M -inform DER -out aaa.xml
    Error reading S/MIME message
    332:error:0D0680A8:asn1 encoding routines:asn1_check_tlen:wrong tag:crypto\asn1\tasn_dec.c:1129:
    332:error:0D07803A:asn1 encoding routines:asn1_item_embed_d2i:nested asn1 error:crypto\asn1\tasn_dec.c:289:Type=PKCS7

    C:\D6\openssl>openssl smime -verify -noverify -inform DER -in aaa.xml.P7M -inform DER -out aaa.xml
    Error reading S/MIME message
    4556:error:0D0680A8:asn1 encoding routines:asn1_check_tlen:wrong tag:crypto\asn1\tasn_dec.c:1129:
    4556:error:0D07803A:asn1 encoding routines:asn1_item_embed_d2i:nested asn1 error:crypto\asn1\tasn_dec.c:289:Type=PKCS7

    come posso risolvere? cosa devo cambiare nel comando ….. ho provato DER-PEM ecc….

  18. Ciao, sto cercando da tempo, utilizzando solo codice php, di reperire il certificato da file .p7m , sono riuscito a farlo per quanto riguarda gli xml mentre per i pdf non riesco, hai qualche consiglio da darmi?

    grazie

  19. Buongiorno,
    vorrei sapere come visualizzare direttamente con un semplice doppio click il file non firmato senza dover aprire ad es. Dike go sign che mi costringe poi a cliccare su visualizza.
    O viceversa come accedere direttamente alla funzione visualizza all’interno del programma citato.
    Grazie

    1. Ciao Vincenzo,
      non esiste un modo semplicissimo per fare quello che chiedi ma, secondo me, la cosa migliore sarebbe scaricasi nella stessa directory dove sono le tue fatture in xml i file di conversione xsl di fatturaPA:

      Fattura PA versione 1.1
      Fattura PA versione 2.1

      A questo punto aprendo l’xml con un browser si dovrebbe aprire la fattura grafica ma purtroppo non è più così, con le ultime versioni dei browser, per problemi di sicurezza in apertura di file in locale.
      Per risolvere anche questo problema prova a scaricare ed installare il browser Firefox (https://www.mozilla.org/it/firefox/new/) e lanciarlo.

      – Nella barra in alto dove si inserisce l’indirizzo scrivi: about:config;
      – ti verrà chiesto con un tasto di “Accettare i rischi”;
      – nella parte in alto in ricerca scrivi: privacy.file_unique_origin
      – ti dovrebbe comparire il campo con tale nome sotto con il valore: true;
      – fai un doppio click sopra per farlo diventare: false;
      riavvia firefox.

      A questo punto Firefox dovrebbe visualizzare correttamente la fattura:

      – prova a cliccare con il tasto destro sulla fattura xml e
      – vai su “Apri con
      – qui se trovi direttamente Firefox cliccaci,
      – altrimenti clicca su “Scegli un’altra app“, poi
      altre app” fino a “Cerca un’altra app in questo PC
      – a questo punto dovresti avere il gestore dei file aperto sulla cartella “Programmi
      – clicca sulla cartella “Mozilla Firefox” e poi scegli “firefox” (o firefox.exe) e clicca sul tasto “Apri“.

      Se tutto è come volevi, alla prossima volta spunta “Usa sempre questa app per aprire i file .xml” cosicché con il doppio click sull’xml riesci ad aprire la fattura con Firefox.

      Si riesce a fare la stessa cosa con il browser Chrome anche se in maniere un pochino differente.

  20. Salve,
    riesco a usare il comando openssl in un’applicazione vb.net o è eseguibile solo da riga comandi?
    Grazie per l’aiuto

    1. Salve Paola, se non capisco male vorresti lanciare il comando openssl da uno script vb.
      Per farlo dovresti prima installare il comando openssl e poi usare qualcosa del tipo:
      process.start(“notepad.exe”)
      dove al posto di “notepad.exe” metti il percorso esatto di openssl.exe.
      Se invece volevi usare le api di openssl all’interno di un vb direi che la cosa non è fattibile se non con l’ausilio di librerie particolari.
      Spero di esser stato utile.

      1. grazie Enio, non intendevo le api. Sei stato utilissimo, sono riuscita ad usare il comando in una windows application e funziona bene al 97% dei casi circa. Ci sono degli xml che non riesce proprio a convertirli. Ecco il codice usato per trasformare un file P7M in un XML con lo stesso nome preceduto dal suffisso MAN:

        ‘ ‘dal formato P7M crea un file in formato XML
        Dim psiFileName As String = “openssl.exe”
        Dim ComandoOpenssl As String = “smime -verify -noverify -in ” & Cartella & NomeFileVersamento & “.” & Estensione
        ComandoOpenssl = ComandoOpenssl & ” -inform DER -out ” & Cartella & “MAN” & NomeFileVersamento
        Dim psi As New ProcessStartInfo
        psi.FileName = psiFileName
        psi.Arguments = ComandoOpenssl
        psi.RedirectStandardError = True
        psi.RedirectStandardOutput = True
        psi.CreateNoWindow = False
        psi.WindowStyle = ProcessWindowStyle.Hidden
        psi.UseShellExecute = False
        Try
        Process.Start(psi)
        Catch ex As Exception
        MessaggioErroreLocale = “errore in conversione in xml del file: ” & Cartella & NomeFileVersamento & Estensione
        ScriveLog(ValoreAmbienteTest, “ParerInvoiceLoading”, “ERROR”, “TrasformaP7M_XML”, MessaggioErroreLocale, ex.Message)
        End Try

        Nei casi citati il comando non restituisce errore, ma non crea il file XML.
        Potrebbero essere XML che sono criptati in modo diverso?
        Grazie d’anticipo Paola

        1. Ciao Paola, non sono un esperto di vbs ma direi che dovresti vedere l’output e l’error di openssl magari mettendo “psi.WindowStyle” diverso da “ProcessWindowStyle.Hidden”.
          Inoltre prova a farti visualizzare il codice di uscita di openssl visualizzando “psi.ExiCode”.
          Comunque per semplicità prova ad utilizzare il comando diretto openssl su una shell o prompt dei comandi.
          Naturalmente il tuo comando non funzionerà per molti .p7m, ad esempio per quelli che sono in formato PEM e non DER, per quelli che hanno più firme incapsulate e sicuramente anche altre tipologie.

          Spero di asserti stato di aiuto

          1. Grazie Enio, sei sempre molto efficiente e d’aiuto. Ho provato a utilizzare il comando diretto sul prompt comandi e ho ricevuto:

            Error reading S/MIME message
            1168:error:0D0680A8: asn1 encoding routines ASN1_CHEK_TLEN: wrong tag:.\crypto\asn1\tasn_dec.c:1319:
            1168:error:0d07803A:asn1 encoding routines:ASN1 encoding routines:asn1-ITEM_EX_D2I:nested asn1 error:.\crypto\asn\\tasn.c:381:Type=PKCS7

            Ho notato che aprendo il file P7M ‘inconvertibile’ con notepad i dati sono codificati in modo strano ma sono tutti su una riga sola, mentre quelli dei P7M convertibili sono codificati in binario e su più righe. Viaggiando in internet ho trovato questo comando per trattare i file base64:
            cat nomefileP7M | tr -d ‘\r\n’ | openssl base64 -d -A | openssl smime -verify -inform DER -noverify -out nomefileXML
            Tuttavia quando lo eseguo risponde:
            | non atteso
            Se eseguo invece:
            openssl base64 -d -A -in nomefileP7M -out nomefileXML
            crea il file xml, ma prima dei tag xml scrive dei caratteri strani e all’interno di xml riporta qua e là questa stringa: ‚è
            Hai idea di cosa posso avere sbagliato?
            Grazie tante Paola

          2. Ciao Paola,
            purtroppo non avendo il .p7m non posso esser preciso ma da quello che hai scritto credo che sei sulla buona strada.
            Io partirei dal mio commento 44 per vedere come convertire in DER il tuo file (dovrebbe essere identico al tuo ultimo comando). Supponiamo di convertirlo con il nome prova.xml.p7m.
            Fatto questo dovresti usare il tuo solito comando openssl (quello dentro al tuo .vbs) passandogli come ingresso il file prova.xml.p7m
            Facci sapere se riesci a risolvere

  21. Grazie molte Enio, troppo bravo e chiaro! grazie ho risolto con questo doppio passaggio di openssl
    Sono molto contenta 🙂
    Paola

  22. Buongiorno,
    un cliente mi invia file firmati con Dike (deduco infocert) con estensione .crt , non supportata dal software che mi occorre.
    Che istruzioni posso dargli per ottenere file con estensione p7m?
    Grazie!

    1. Ciao Laura,
      il file con estensione .crt è semplicemente il certificato (immagino del suo cliente) e serve al suo cliente per firmare il documento e quindi per incapsularlo in .p7m.
      Per sicurezza verifichi il contenuto usando il comando openssl (supponiamo che il file sia cliente.crt):
      openssl x509 -in cliente.crt -text -noout
      Oppure, se non ha la possibilità di usare il comando openssl su una shell o su prompt dei comandi ed usa Windows 10, basta aprire “Esplora risorse” e cliccare sul file cliente.crt.
      Non ho istruzioni da poterle dare per il suo cliente se non il consiglio di far leggere il manuale di Dike o di InfoCert (in rete ho trovato velocemente questa documentazione relativa a Dike 6).

  23. Grazie a questa eccellente pagina ed al qui illustrato utilizzo da riga di comando di “openssl”, ho realizzato già da un annetto una utility assolutamente freeware che distribuisco dal mio sito per la desbustazione/visualizzazione/arricchimento (singola o massiva) delle fatture lettroniche. Ha sempre funzionato perfettamente con tutti files firmati (Pem/Der/Base64 ecc.), fino a che, ieri, mi sono imbattuto in un file firmato (Fattura Enel) che non sono riuscito ad aprire in nessun modo con openssl, pur avendo provato con svariati parametri.
    Guardandolo con un editor esadecimale, sembra in tutto e per tutto un DER, ma il relativo comando va in errore.
    Infatti, con il comando “openssl smime -verify -inform DER -in 1.xml.p7m -noverify -out 1.txt” restitusce:
    Error reading S/MIME message
    7540:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag:./crypto/as
    n1/tasn_dec.c:1294:
    7540:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error:./
    crypto/asn1/tasn_dec.c:380:Type=PKCS7_ISSUER_AND_SERIAL
    7540:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 e
    rror:./crypto/asn1/tasn_dec.c:749:Field=issuer_and_serial, Type=PKCS7_SIGNER_INF
    O
    7540:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 e
    rror:./crypto/asn1/tasn_dec.c:710:Field=signer_info, Type=PKCS7_SIGNED
    7540:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 e
    rror:./crypto/asn1/tasn_dec.c:749:
    7540:error:0D08403A:asn1 encoding routines:ASN1_TEMPLATE_EX_D2I:nested asn1 erro
    r:./crypto/asn1/tasn_dec.c:578:Field=d.sign, Type=PKCS7

    Esiste una soluzione?
    Grazie mille dell’eventuale risposta

    1. Ciao Franco e grazie per i complimenti.
      Da quel che vedo dal messaggio di errore sembrerebbe che la fattura p7m sia del nuovo formato e non più compatibile con l'”smime” di openssl.
      Il nuovo formato, che sarebbe l’evoluzione, di “smime” è “cms” ed openssl ha preferito fare un nuovo comando piuttosto che adattare “smime” per problemi di semplicità di sviluppo del software.
      Quindi rispondendo alla tua domanda credo che basti usare il comando:
      openssl cms -verify -inform DER -in 1.xml.p7m -noverify -out 1.txt
      Facci sapere se riesci a risolvere il problema.

      1. Con la sintassi da te suggerita, funziona!
        Grazie mille

        P.S.: mi confermi anche che il comando “cms” è retrocompatibile con lo “smime”, nel senso che incorpora anche la gestione di tutti i formati precedentemente gestiti da quest’ultimo, per cui è possibile utilizzare “cms” anche per desbustare file firmati smime/der/pem non “evoluti” mandando, pertanto, definitivamente “in pensione” il comando “smime” come, sostanzialmente, superato?

        1. Perfetto!
          No, non è retro-compatibile con smime come avevo tentato di dire nel precedente commento.
          Lo sarebbe stato solo se openssl avessero deciso ci utilizzare smime anche per le evoluzioni del protocollo.
          Praticamente ci sono p7m che vanno solo in smime, altri solo in cms ed alcuni in entrambi.
          Puoi vedere come ho tentato di risolvere il problema per capire se il p7m è un smime o un cms tramite il mio programma p7m su github.

          1. Grazie delle info.
            Nel mio algoritmo, ho fatto più o meno la stessa cosa, aggiungendo anche, ma solo se tutti i precedenti falliscono (errore0), anche il tentativo di decodificare un base64, sia con riempimento che senza.
            In ogni caso, anche grazie alle tue dritte, ho già pubblicato la versione aggiornata della mia utility freeware per le elaborazioni massive delle fatture elettroniche, che integra un openssl più aggiornato capace di gestire i cms (il sito è syse.it)
            Ne ho approfittato per inserire una ulteriore funzionalità che, opzionalmente, crea un unico pdf a fronte di documenti da elaborare/desbustare

            Grazie ancora

  24. Ho provato ad estrarre il contenuto di diversi pdf.p7m con la riga di comando che hai indicato, ma il file pdf risulta illeggibile con acrobat reader. Ho notato che rispetto al pdf estratto con dike, ci sono diversi valori hexe “0D” doppi, cioe’ CR in coppia, mentre nel file corretto ci sono una sola volta. Inoltre il file da dike è piu’ piccolo di 1.012byte, probabilmente a causa di tutti questi CR che non dovrebbero esserci.

    1. Ciao Dino,
      per capire meglio il problema avrei bisogno che mi mandassi (per email enio.carboni at quoll.it) il file pdf.p7m.
      Un problema che mi viene in mente, velocemente, potrebbe essere che il file che hai estratto sia un altro p7m e che quindi devi ripetere il comando anche su tale file. Questo si presenta quando il documento è stato firmato in diversi momenti e quindi ci sono diversi incapsulamenti ognuno con la sua firma.
      In tal caso rinomina il file estratto aggiungendo l’estensione .p7m e prova di nuovo il comando openssl
      La soluzione migliore sarebbe quello di utilizzare il mio script in https://github.com/eniocarboni/p7m che però non funziona in Windows ma solo nei sistemi Linux e Unix in genere.
      Facci sapere se riesci a risolvere il problema.

      1. Ti ho inviato un file di prova, e’ un semplice pdf creato da word con scritto “Prova” in una pagina bianca. Il testo non viene visualizzato in acrobat, ma in questo caso non da errore, forse perche’ molto semplice. Naturalmente decodificandolo con dike la scritta viene fuori.

        1. Ciao Dino,
          come ti ho risposto via email, riesco ad estrarre il pdf senza nessun problema e leggo il contenuto pdf.
          Forse il problema potrebbe essere una versione errata di openssl, riesci ad aggiornarla?.
          Prova anche ad aggiungere al comando openssl il parametro -binary
          openssl cms -verify -noverify -in prova.pdf.p7m -inform DER -binary -out prova.pdf
          Facci sapere se risolvi il problema

          1. Si, ora funziona. Ho creato un piccolo script da riga di comando in semplice dos per estrarre i p7m presenti in una cartella. L’uso e’ molto semplice, basta indicare il percorso dove sono contenuti i file, tipo “estrai.cmd file_firmati”. Se i file sono con p7m multipli, tipo “file.pdf.p7m.p7m”, basta lanciare il comando piu’ volte. Fatemi sapere se ci sono problemi. Non e’ elegantissimo, ma non sono molto esperto di comandi dos.

            set OPENSSL_CONF=openssl.cnf
            for /f “usebackq delims=|” %%f in (`dir /b “%1” ^| findstr /i .p7m`) do openssl cms -verify -noverify -in “%1/%%f” -inform DER -binary -out “%1/%%fx”
            for /f “usebackq delims=|” %%F in (`dir /b %1\*.p7mx`) do ren “%1\%%~nxF” “%%~nF”
            del %1\*.p7mx

  25. Ho provato ad estrarre il contenuto PDF da un file P7M togliendo la parte prima di %PDF-1 e dopo di EOF ma il PDF risulta non valido, anche la dimensione resta superiore a quella del PDF originale.. Proprio non si riesce da PHP ad estrarre il contenuto PDF ?
    Grazie

    1. Ciao Franco,
      in generale facendo un semplice taglia del contenuto non si riesce ad estrarre il contenuto di un p7m, anche se per alcuni si riesce.
      Comunque consiglio di utilizzare il comando “openssl“.
      Se utilizzi Linux o Mac prova il mio script p7m che semplifica un po’ la vita!

  26. Ottimo script, l’ho scaricato e usato oggi stesso.
    A me servirebbe per estrarre da un file p7m il contenuto xml ma quando cerco di lanciare lo script senza opzioni o con l’opzione -v oppure -vx oppure -v -x ottengo un file senza l’estensione p7m ma che contiene solo un messaggio del tipo:
    .P7M
    Starting download fatturapa_v1.2.1.xsl … wait, please
    Non trovo nessuno dei comandi:
    xdg-open gvfs-open gnome-open
    I don’t know how to open the extracted file ‘/tmp/p7m_tmp.XXXXXXXXXXXXX.xml’
    [tipo: text/xml|application/xml].
    Come posso fare per salvare il contenuto del file senza le firme del p7m?
    Ti ringrazio in anticipo.

    1. Grazie mille Piermario per utilizzare il mio script p7m.
      Da quel che capisco l’xml te lo ha estratto nel file /tmp/p7m_tmp.XXXXXXXXXXXXX.xml ma non riesce ad aprirlo perché non sa come fare.
      Non hai nessuno dei comandi xdg-open, gvfs-open, gnome-open che P7M utilizza per aprire i file in un ambiente grafico.
      Se sei via terminale leggi il file che ti scrive in output editandolo con il tuo editor preferito.
      Se sei in un ambiente grafico mi potresti dire che ambiente è?

      1. Lo sto usando da riga di comando all’interno di uno script php che esegue una chiamata exec all’interno di un ciclo che legge una directory con delle fatture elettroniche:
        $cmd = “/home/…/…/p7m/bin/p7m $FileDaVerificare”;
        exec ( $cmd );

  27. Salve Enio, grazie per il prezioso script p7m, è un’utilità fondamentale su Linux, davvero utile!|
    Grazie ancora!!!
    Federico

  28. salve,
    con lo script dos for %%F in (*.p7m) do “C:\Program Files (x86)\OpenSSL\bin\openssl.exe” smime -verify -noverify -in “%%~nF”.p7m -inform DER -out “%%~nF” riesco ad estrarre una serie di file p7m senza problemi, ma non riesco ad adattarlo per i casi con multifirma/controfirma (che hanno estensione p7m ripetuta varie volte).

    mica avresti qualche idea/suggerimento su come adattare lo script per queste situazioni? grazie in anticipo!!

    1. scusami! mi ero perso un commento che ne parlava, aggiungendo -binary mi esce un .p7m valido a cui applicare lo script di nuovo
      grazie per le informazioni preziosissime che metti a disposizione 😉

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

5 + 3 =