App cross-platform (macOS Apple Silicon / Windows) per aprire i file .p7m
(buste CMS/PKCS#7, firma digitale CAdES italiana), verificarne la validità
della firma ed estrarre il documento contenuto.
La verifica è a validità legale: oltre all'integrità crittografica, la catena del certificato del firmatario viene ricondotta a una CA accreditata presente nelle Trusted List europee (EU LOTL) / italiana (AgID), con controllo di revoca CRL/OCSP.
| Livello | Controllo |
|---|---|
| Integrità | La firma corrisponde al contenuto (hash message-digest + firma sui signed attributes). Rileva manomissioni del documento. |
| Certificato | Titolare, organizzazione, codice fiscale/identificativo, emittente, numero di serie, validità temporale. |
| Catena / Trust | Il certificato risale a una CA accreditata nella Trusted List (EU/AgID). |
| Autenticità lista | La Trusted List è verificata nella firma XAdES e ancorata all'anchor OJ europeo (vedi sotto). |
| Marca temporale | Le firme CAdES-T (RFC 3161) sono verificate: impronta, firma della TSA e TSA accreditata; il tempo attestato diventa l'istante di validazione. |
| Revoca | Stato di revoca del certificato via CRL/OCSP (opzionale, online). |
| Firme multiple | Firme parallele (più firmatari) e annidate (file.pdf.p7m.p7m). |
- Python 3.10+ (consigliato 3.12).
- macOS:
brew install python@3.12 - Windows: installer ufficiale da python.org (64 bit).
- macOS:
# 1. ambiente virtuale
python3.12 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# 2. dipendenze
pip install -r requirements.txt
pip install -e .
# 3. avvio interfaccia grafica
python -m corianosignLa Trusted List si aggiorna automaticamente all'avvio (per impostazione predefinita ogni 7 giorni, configurabile in Impostazioni). Al primo avvio l'app la scarica da sola; puoi comunque forzare l'aggiornamento con «Aggiorna Trusted List». La cache è locale, quindi poi funziona offline.
- Apri file .p7m (o trascinalo nella finestra).
- Leggi l'esito: verde = firma valida e riconducibile a CA accreditata.
- Estrai documento per salvare il file originale contenuto nella busta.
Le opzioni sono in Impostazioni ▸ Verifica (barra verticale a sinistra): Valida catena, Controllo revoca online, Verifica autenticità delle liste, aggiornamento automatico (all'avvio + ogni N giorni), Ambito (Italia/UE) e il pulsante Aggiorna Trusted List ora.
Il secondo tab firma un documento con la firma remota Aruba (con OTP):
-
In Impostazioni (barra verticale a sinistra: Generali / Verifica / Firma) configuri una volta:
- Generali: il fuso orario usato per la data/ora della firma;
- Firma ▸ aspetto grafico: il testo è sempre il Nome Cognome del firmatario (dal certificato); motivazione e luogo sono checkbox che, se attive, vengono chieste al momento della firma; più logo e «solo immagine»;
- Firma ▸ utenti: uno o più utenti di firma remota (Nome, Utente, Dominio = tipo OTP, certID, HSM). Password e OTP non si salvano mai.
-
Nel tab Firma: scegli documento, formato (PAdES/CAdES) e livello (Predefinito/B/T/LT/LTA).
-
Per PAdES, firma visibile: trascina il riquadro direttamente sull'anteprima del PDF per posizionarlo (testo e logo vengono dai settaggi).
-
Scegli l'utente («Firma come:») e premi Firma con Aruba (OTP) → password + OTP → il file firmato viene salvato e, per il CAdES, ri-verificato automaticamente col motore di CorianoSign.
Dettagli e parametri del contratto in docs/firma-remota.md.
La stessa firma è disponibile da riga di comando (corianosign-cli firma-remota).
# aggiorna le CA italiane (o --tutti-eu per tutta l'UE)
corianosign-cli aggiorna-trust
# verifica una firma
corianosign-cli verifica documento.pdf.p7m
# estrai il contenuto
corianosign-cli estrai documento.pdf.p7m -o documento.pdfverifica restituisce exit code 0 se tutte le firme sono pienamente valide,
1 se qualcuna non lo è, 2 in caso di errore di parsing.
./packaging/build_macos.sh
open dist/CorianoSign.appPer distribuire fuori dal proprio Mac serve firma + notarizzazione Apple (istruzioni stampate a fine build).
powershell -ExecutionPolicy Bypass -File packaging\build_windows.ps1
# risultato: dist\CorianoSign\CorianoSign.exePer evitare l'avviso SmartScreen serve firmare con un certificato Authenticode.
Il packaging va eseguito sulla piattaforma di destinazione: l'
.appsi costruisce su macOS, l'.exesu Windows (PyInstaller non fa cross-compiling).
L'icona è generata da packaging/icon.svg con
python packaging/generate_icons.py (produce .icns, .ico e i PNG). La
generazione è già inclusa negli script di build.
Facendo doppio clic su un file .p7m, l'app si apre con il file già
caricato e verificato.
L'associazione è dichiarata nell'Info.plist del bundle (CFBundleDocumentTypes).
Diventa attiva quando l'app è registrata in Launch Services — cosa che avviene
spostando CorianoSign.app in /Applications e avviandola una volta. Per
forzarla subito su una build in dist/:
/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -f dist/CorianoSign.appSe un altro programma è già predefinito per i .p7m: clic destro sul file →
Ottieni informazioni → Apri con → CorianoSign → Modifica tutti.
Esegui una volta lo script di registrazione (non serve admin):
powershell -ExecutionPolicy Bypass -File packaging\windows_associa_p7m.ps1Poi, la prima volta: clic destro sul .p7m → Apri con → Scegli un'altra app
→ CorianoSign → spunta Usa sempre questa app.
(Windows protegge la scelta predefinita: non è impostabile in modo totalmente
automatico, va confermata una volta dall'utente.)
src/corianosign/
├── cms.py parsing CMS/PKCS#7 + verifica crittografica delle firme
├── trust.py download/parse Trusted List (EU LOTL / AgID) -> CA fidate
├── tsl_signature.py verifica firma XAdES delle liste + pinning agli anchor OJ
├── timestamp.py verifica marche temporali CAdES-T (RFC 3161)
├── cades_lt.py materiale di validazione LT + archive-timestamp (LTA)
├── archive_ts.py ricalcolo impronta archive-timestamp-v3 (ats-hash-index-v3)
├── validation.py validazione catena PKIX + revoca (pyhanko-certvalidator)
├── verifier.py orchestratore: firme multiple/annidate, estrazione contenuto
├── config.py impostazioni persistenti (auto-update, intervallo)
├── model.py strutture dati dei risultati
├── gui.py interfaccia PySide6
├── cli.py interfaccia a riga di comando
└── paths.py cartelle dati per piattaforma
L'anchor OJ europeo è impacchettato in
packaging/trust_anchors/eu_lotl_signers.pem.
La cache delle Trusted List è in:
- macOS:
~/Library/Application Support/CorianoSign/trust/ - Windows:
%LOCALAPPDATA%\CorianoSign\trust\
L'autenticità della lista non dipende solo dal canale HTTPS: la firma XAdES viene verificata e il firmatario è ancorato secondo il modello eIDAS (ETSI TS 119 612):
anchor OJ (impacchettato) ──firma──▶ EU LOTL
EU LOTL dichiara il certificato firmatario di ogni TSL nazionale
certificato dichiarato ──firma──▶ TSL nazionale (AgID per l'Italia)
TSL nazionale elenca i certificati delle CA accreditate
CA accreditata ──firma──▶ certificato del firmatario del .p7m
In pratica: verifichiamo la firma del LOTL contro l'anchor OJ della Gazzetta UE (bundle), dal LOTL ricaviamo il certificato firmatario atteso della TSL-IT, e verifichiamo la firma della TSL-IT contro quel certificato. Se una firma non è valida o il firmatario non combacia, le relative CA non vengono caricate (modalità strict). Lo stato è mostrato in basso: ✓ autentiche.
L'unico presupposto di bootstrap è l'anchor OJ impacchettato — come in tutte le
implementazioni (incluso DSS, il riferimento della Commissione UE). Va aggiornato
se la UE ruota i certificati OJ (l'attuale è valido fino al 17/11/2027);
per rigenerarlo vedi il commento in tsl_signature.py.
Se la firma include una marca temporale RFC 3161 (attributo
id-aa-signatureTimeStampToken), CorianoSign la verifica:
- l'impronta della marca corrisponde al valore della firma;
- la marca è firmata dalla TSA (firma CMS valida);
- il certificato della TSA è accreditato nella Trusted List (servizio TSA).
Il tempo attestato dalla marca diventa l'istante di validazione del
certificato del firmatario (trusted_time): a differenza del solo
signing-time auto-dichiarato di CAdES-BES, è un tempo fidato. Le firme senza
marca restano valide (mostrano «marca assente, data auto-dichiarata»).
CorianoSign riconosce e mostra il livello di ogni firma:
| Livello | Cosa contiene | Cosa fa CorianoSign |
|---|---|---|
| BES | firma base | integrità + catena + revoca online |
| T | + marca temporale | verifica marca e usa il tempo fidato |
| LT | + certificati e CRL/OCSP incapsulati | valida catena e revoca offline con il materiale incapsulato (ltv_used) |
| LTA | + archive-timestamp | verifica TSA d'archivio e ricalcola l'impronta d'archivio (archive-timestamp-v3) |
Il valore di LT è la validazione storica: la firma resta verificabile anche senza rete e dopo la scadenza dei certificati, perché il materiale di revoca è dentro la busta. La riga «Materiale LT» in interfaccia indica quanti certificati/CRL/OCSP sono incapsulati e se sono stati usati per la revoca.
Per LTA (archive-timestamp-v3) l'app ricalcola l'impronta d'archivio:
ricostruisce l'ats-hash-index-v3 dalla struttura (contenuto, certificati,
CRL/OCSP, attributi non firmati) e verifica che l'impronta
H( DER(eContentType) || H(eContent) || DER(ATSHashIndexV3) )
coincida con il messageImprint della marca d'archivio. Così si prova che la
marca copre davvero questa firma con tutto il suo materiale — se qualcosa viene
alterato o rimosso, l'impronta non combacia più.
CorianoSign implementa i controlli fondamentali della validazione CAdES, ma non sostituisce i verificatori ufficiali (es. il verificatore eIDAS della Commissione UE, o software come Dike/ArubaSign) quando serve valore legale probatorio. In particolare:
- Archive-timestamp v2 (legacy): per gli archive-timestamp v3
(EN 319 122,
ats-hash-index-v3) l'impronta d'archivio viene ricalcolata e verificata (copertura di contenuto, certificati, CRL/OCSP e attributi). Per il vecchio ATSv2 (TS 101 733) l'impronta non viene ancora ricalcolata: se ne verifica solo la firma della TSA. L'interoperabilità del ricalcolo v3 è validata su fixture autoprodotti secondo la specifica; con file reali prodotti da altre implementazioni va confermata su campioni effettivi. - Per le firme CAdES-BES senza marca, la validità temporale del certificato
è valutata al
signing-timeauto-dichiarato (o all'ora corrente se assente).
Per l'uso quotidiano (integrità, CA accreditata su lista autenticata, marca temporale, validazione a lungo termine LT, estrazione documento) l'app è pienamente operativa.
Nella cartella tests/fixtures/ uno script OpenSSL (genera_fixture.sh) genera
esempi di prova:
chained.txt.p7m— firma valida con catena CA→titolare (esito fidato usandoca_cert.pemcome radice);chained_ts.txt.p7m— come sopra + marca temporale CAdES-T (TSA di test);chained_lt.txt.p7m— CAdES-LT: certificati e CRL incapsulati (revoca validabile offline);chained_lta.txt.p7m— CAdES-LTA: come LT + archive-timestamp;documento.txt.p7m— firma self-signed (esito non fidato, corretto).
MIT.