Come sono collocate le firme in un PDF
ISO 32000-2 §12.8 Spec: ETSI EN 319 142-1 ETSI EN 319 142-1 Spec: RFC 5652 RFC 5652 Evidence: Standard-backed
In sintesi
Sezione intitolata “In sintesi”Una firma PDF non avvolge il file. È incorporata al suo interno: un dizionario di firma la identifica e un digest viene calcolato su un intervallo di byte dichiarato, escludendo deliberatamente il valore della firma stessa. Questa pagina illustra tale meccanismo e, con pari importanza, ciò che non garantisce.
Perché è importante
Sezione intitolata “Perché è importante”«Il documento è firmato» è una frase su cui si prendono decisioni. Può essere collegata a un pagamento, a un’approvazione, a un obbligo legale. Se non si sa con precisione quali byte copre una firma, non si può dire cosa dimostri davvero un risultato valido. Un PDF può contenere una firma perfettamente valida e mostrare comunque al lettore contenuti che il firmatario non ha mai visto, perché tali contenuti sono stati aggiunti dopo la firma, in un’area che la firma non ha mai dichiarato di coprire. Sapere dove inizia e dove finisce la portata della firma è la differenza tra una decisione difendibile e una basata sulla speranza.
In breve
Sezione intitolata “In breve”- Una firma PDF risiede in un dizionario di firma e in un campo di firma all’interno del documento, non in un involucro esterno.
- I byte firmati sono dichiarati dall’array
ByteRange: due segmenti(offset, length)che insieme coprono l’intero file tranne il valore esadecimale della firma contenuto nella voceContents. - Il digest di questi due segmenti concatenati è ciò che la firma crittografica protegge effettivamente.
- Qualunque elemento aggiunto in seguito in una nuova revisione è al di fuori dell’intervallo di byte originale. La firma originale resta valida; non ha mai fatto alcuna asserzione sui nuovi byte.
- Una firma di approvazione e una firma di certificazione differiscono per ambito: la certificazione (DocMDP) vincola quali modifiche successive sono consentite; l’approvazione no.
Come lo affronta NextPDF
Sezione intitolata “Come lo affronta NextPDF”NextPDF costruisce la firma secondo il formato, seguendo un ordine fisso, così che l’intervallo di byte sia esatto anziché approssimativo.
Quando il motore scrive una firma, riserva innanzitutto uno slot di dimensione fissa per il
valore Contents e scrive un segnaposto ByteRange di larghezza fissa. Attende
che il documento sia scritto per intero — tabella dei riferimenti incrociati e
marcatore di fine file inclusi. Solo allora calcola i due offset reali,
li riscrive nel segnaposto senza spostare alcun byte, esegue l’hash dei due
segmenti e inserisce l’oggetto CMS risultante nello slot riservato. Il
segnaposto viene riempito con zeri fino a una lunghezza costante, in modo che l’inserimento dei
numeri reali non possa spostare gli stessi byte sottoposti a hash. Questo è l’unico ordine
che produce una firma coerente con sé stessa. Il motore tratta qualsiasi errore in
questa sequenza come un errore irreversibile, non come un ripiego silenzioso.
L’oggetto firma in sé, per il profilo PDF 2.0, è una struttura CMS
SignedData distaccata (detached). Il dizionario PDF indica dove e come; l’oggetto CMS
contiene il chi e la prova crittografica.
- Step 1 of 4: ISO 32000-2 §12.8.1 — ByteRange digest & signature dictionary
- Step 2 of 4: ISO 32000-2 §12.8.3.3 — ETSI.CAdES.detached SubFilter
- Step 3 of 4: ETSI EN 319 142-1 PAdES baseline profile
- Step 4 of 4: RFC 5652 CMS SignedData in Contents
Cosa dicono le evidenze
Sezione intitolata “Cosa dicono le evidenze” Evidence: Standard-backed Il meccanismo è definito da
Spec: ISO 32000-2, §12.8.1 ISO 32000-2 §12.8.1 . Il digest viene
calcolato sull’intervallo di byte indicato dalla voce ByteRange. Tale intervallo
dovrebbe corrispondere all’intero file, incluso il dizionario di firma ma escluso
il valore della firma — la voce Contents. ByteRange è un array di
coppie di interi — offset iniziale e lunghezza. Gli intervalli non contigui sono
usati appositamente affinché il digest possa omettere il valore della firma stessa.
Per il profilo PDF 2.0, Spec: ISO 32000-2, §12.8.3.3 ISO 32000-2 §12.8.3.3 specifica che, quando SubFilter è ETSI.CAdES.detached, il valore Contents è un oggetto CMS SignedData codificato in DER — la stessa struttura definita da
Spec: RFC 5652 RFC 5652 — e il profilo PAdES di tale oggetto
è quello descritto da Spec: ETSI EN 319 142-1 ETSI EN 319 142-1 .
L’ambito non è lo stesso per tutte le firme. Spec: ISO 32000-2, §12.7.4.5 ISO 32000-2 §12.7.4.5 definisce il permesso MDP: un valore di 0 rende la firma una firma di approvazione, mentre i valori 1–3 la rendono una firma di certificazione che vincola quali modifiche successive mantengono il documento conforme. Stesso meccanismo dell’intervallo di byte; promessa diversa sul futuro.
Il motore di NextPDF implementa esattamente questo: un segnaposto ByteRange di larghezza fissa, il digest dei due segmenti concatenati e un oggetto CMS distaccato in uno slot Contents riservato, finalizzato solo dopo che il file è completo.
Esempio pratico
Sezione intitolata “Esempio pratico”Raramente si costruisce a mano un ByteRange. Lo scopo dell’esempio è mostrare la forma del risultato in modo che sia riconoscibile quando si ispeziona un file firmato.
<?php
declare(strict_types=1);
use NextPDF\Security\Signature\ByteRangeCalculator;
// Offsets the engine knows only after the whole PDF is written:// $contentsStart — byte just before the '<' of the hex signature// $contentsEnd — byte just after the '>' that closes it// $fileLength — total file size in bytes$range = ByteRangeCalculator::calculate( contentsStart: $contentsStart, contentsEnd: $contentsEnd, fileLength: $fileLength,);// $range === [0, $contentsStart, $contentsEnd, $fileLength - $contentsEnd]// Segment 1: file start → just before the signature value// Segment 2: just after the signature value → end of file// The signature value itself is the gap. It is never hashed.
$signedMessage = ByteRangeCalculator::extractSignedData($pdfBytes, $range);// $signedMessage is segment 1 concatenated with segment 2 — exactly the// bytes the cryptographic digest is computed over.Lo spazio tra i due segmenti è il valore della firma. Non può essere incluso nel proprio digest, motivo per cui l’intervallo è composto da due parti e non da una.
Equivoco comune
Sezione intitolata “Equivoco comune”La trappola sta nel credere che una firma valida significhi che l’intero file che si sta visualizzando sia ciò che è stato firmato. Non è così. Significa che i byte all’interno dell’intervallo dichiarato sono integri. Una revisione successiva può legittimamente aggiungere contenuti — una seconda firma, dati di modulo, materiale di convalida — al di fuori di tale intervallo. La prima firma resta valida e non dice nulla riguardo all’aggiunta. Un visualizzatore corretto indica che una firma copre «il documento così com’era al momento della firma», non «ogni byte sullo schermo». Trattare i due aspetti come la stessa cosa è il modo in cui un documento firmato acquisisce contenuti non firmati che sembrano firmati.
Limiti e confini
Sezione intitolata “Limiti e confini”Questa pagina illustra la struttura, non la fiducia. Un
ByteRange e un oggetto CMS formati correttamente indicano che i byte sono integri e quale chiave li ha firmati.
Non indicano, da soli, se quella chiave appartenga al soggetto atteso,
se il suo certificato fosse valido al momento della firma o se sia stato successivamente
revocato. Questo è compito del percorso di certificazione e della revoca, trattato in
Convalidare correttamente una firma.
Questa pagina inoltre non tratta quando la firma è avvenuta con un’autorità
indipendente. Un orario autodichiarato della firma non è un orario attendibile —
vedere Marche temporali e orario attendibile.
NextPDF costruisce la struttura qui descritta; i certificati, le ancore di fiducia
e l’autorità di marcatura temporale sono forniti dalla distribuzione in uso, non dal motore.
Ciò che il motore fornisce, per ciascun livello, è la capacità di costruire la struttura:
| Edition | Availability |
|---|---|
| Core | PAdES B-B: il dizionario di firma, il ByteRange di larghezza fissa e l’oggetto CMS SignedData distaccato descritti in questa pagina. |
| Pro | Aggiunge PAdES B-T — una marca temporale attendibile applicata al valore della firma — sulla stessa struttura. |
| Enterprise | Aggiunge i profili a lungo termine (B-LT, B-LTA): materiale di convalida incorporato e marche temporali del documento stratificate sulla stessa base dell’intervallo di byte. |
Documenti correlati
Sezione intitolata “Documenti correlati”- Aggiornamenti incrementali e perché sono importanti — perché accodare, anziché riscrivere, mantiene intatto l’intervallo di byte della prima firma.
- Profili baseline PAdES — cosa viene stratificato su questa struttura e quale profilo richiede quale obbligo.
- Convalida a lungo termine — come le evidenze di convalida vengono incorporate affinché una firma resti verificabile per anni.
Glossario
Sezione intitolata “Glossario”- Dizionario di firma — il dizionario PDF che identifica il gestore della firma, il
SubFilter, ilByteRangee il valoreContents. ByteRange— un array di coppie di interi(offset, length)che dichiara i byte esatti coperti dal digest della firma.Contents— la voce esadecimale che contiene il valore della firma (per PDF 2.0, un oggetto CMSSignedDatadistaccato); è esclusa dal proprio digest.- CMS
SignedData— struttura Cryptographic Message Syntax (RFC 5652) che contiene il certificato del firmatario e i byte della firma. - PAdES — PDF Advanced Electronic Signatures: il profilo ETSI delle firme CMS per PDF, definito nella serie ETSI EN 319 142.
- Firma di approvazione — una firma con permesso
MDP0; attesta il contenuto senza vincolare le modifiche successive. - Firma di certificazione — una firma con permesso DocMDP (
MDP1–3) che limita quali modifiche successive mantengono il documento conforme.