Salta ai contenuti
getnextpdf.com

Enterprise edizione

Livelli di garanzia eIDAS

NextPDF Enterprise trasforma le prove delle trusted-list UE in un esplicito livello di garanzia (LoA) eIDAS. Il servizio NextPDF\Enterprise\Security\Eidas\LoaMapping classifica una voce di servizio fiduciario come Low, Substantial o High. Restituisce una LoaAssertion che porta con sé il livello più codici motivazione leggibili dalla macchina. Il flusso di lavoro può applicare un vincolo sulla garanzia — “richiedere High” — e archiviare le motivazioni come prova di audit. Una protezione complementare, CertPiiGuard, occulta i campi identitari del firmatario prima che i record di audit lascino il processo.

Due confini inquadrano questa capacità in modo onesto. Primo, la qualificazione appartiene sempre al prestatore di servizi fiduciari (TSP) sotto la vigilanza dello Stato membro. NextPDF asserisce una classificazione su prove pubblicate; non concede, conferisce né certifica mai la qualificazione. Secondo, questa pagina copre solo l’asserzione e la mappatura del LoA. La policy PAdES strutturale eidasQualified(), inclusi i suoi criteri di superamento/insuccesso, è documentata in Validazione.

Questa capacità è inclusa in NextPDF Enterprise (nextpdf/enterprise) e si attiva con un envelope di licenza di livello Enterprise. Un deployment privo di tale titolarità non carica le classi della capacità. Confronta le edizioni e ottieni una licenza.

Terminal window
composer require nextpdf/enterprise

Anche il metapacchetto nextpdf/premium risolve il pacchetto Enterprise. L’attivazione usa l’envelope della licenza Enterprise; vedi Licenza e attivazione. Le classi eIDAS non necessitano di alcuna estensione PHP oltre la baseline del motore. Vengono caricate automaticamente sotto NextPDF\Enterprise\Security\Eidas e NextPDF\Enterprise\Signature\Eidas.

Il regolamento (UE) n. 910/2014 (eIDAS) definisce tre livelli di garanzia: basso, significativo ed elevato (articolo 8, paragrafo 1). Ciascun livello esprime un grado di affidabilità in un’identità dichiarata. Il livello elevato aggiunge controlli il cui scopo è impedire — non semplicemente ridurre — l’uso improprio o l’alterazione dell’identità (articolo 8, paragrafo 2, lettera c)). L’articolo 8 definisce questi livelli per i regimi di identificazione elettronica. NextPDF riutilizza lo stesso vocabolario per classificare le prove del servizio fiduciario dietro un certificato di firma. Tale riutilizzo è una convenzione ingegneristica per il vincolo di policy e l’audit, non un’equivalenza giuridica.

L’enum LoaLevel modella i tre livelli. I suoi valori di backing sono gli URI del LoA eIDAS anziché etichette nude, così un’asserzione persistita porta con sé l’identificatore completo. rank() fornisce un ordine totale (Low = 1, Substantial = 2, High = 3) e meetsOrExceeds() confronta rispetto a una soglia minima richiesta.

LoaMapping calcola un livello a partire da una voce di trusted list — un TspService dal sottosistema trusted-list Enterprise (NextPDF\Enterprise\Security\Tsl). La mappatura è deterministica:

Prove della trusted listLivelloCodici motivazione
Lo stato del servizio non è grantedLowservice_not_granted
Il tipo di servizio non è CA/QCLowservice_not_qualified_ca
CA/QC granted con QCWithQSCD e senza QCNoQSCDHighca_qc_with_qscd più esig_or_eseal o qc_default
CA/QC granted altrimentiSubstantialca_qc_no_qscd_or_unspecified

Il qualificatore QSCD (dispositivo per la creazione di una firma qualificata) è il perno. Ai sensi dell’articolo 3, punto 12), una firma elettronica qualificata richiede sia un certificato qualificato sia un dispositivo per la creazione qualificato. Una dichiarazione della trusted list secondo cui i certificati sono gestiti su un QSCD è quindi la prova che sostiene un’asserzione High. Senza tale dichiarazione, una CA qualificata granted sostiene comunque Substantial, mai High.

Il risultato è una LoaAssertion: il livello più un elenco di codici motivazione. Le motivazioni permettono a un consumatore di audit di ri-derivare la classificazione dalle stesse prove in seguito. I valutatori di policy a valle possono registrare l’asserzione insieme all’esito di una validazione di firma.

Un ulteriore componente è incluso in questo modulo: CertPiiGuard. Quando gli artefatti di validazione vengono serializzati in bundle di audit JSON, il certificato del firmatario porta con sé dati personali — il CN del Subject, gli attributi email e l’attributo serialNumber, che può codificare un identificativo nazionale per le persone fisiche. L’articolo 5, paragrafo 1, lettera c) del GDPR richiede che il trattamento sia limitato a quanto necessario. La protezione quindi occulta quei campi per impostazione predefinita, sostituendo i valori con [REDACTED] pur preservando l’involucro strutturale (campi organizzazione, paese, catena e stato). I consumatori possono ancora verificare se una firma è stata superata senza apprendere chi ha firmato.

La decisione portante è separare l’asserzione di garanzia dal verdetto di validazione. La validazione di firma, secondo ETSI EN 319 102-1, termina con un’indicazione di stato — TOTAL-PASSED, TOTAL-FAILED o INDETERMINATE — e quel verdetto appartiene al livello di validazione. La mappatura del LoA è una classificazione distinta e riproducibile sulle prove della trusted list, con codici motivazione anziché un’etichetta nuda. Questo impedisce a NextPDF di presentare mai una dichiarazione di garanzia come un risultato di validazione, o un risultato di validazione come una concessione di qualificazione. Rende inoltre la mappatura conservativa per costruzione: prove assenti o ambigue abbassano il livello, non lo alzano mai.

Contesto progettuale: Firme qualificate, spiegate.

Tutti i simboli seguenti sono API pubbliche in nextpdf/enterprise 3.1.0.

enum LoaLevel: string
{
case Low = 'http://eidas.europa.eu/LoA/low';
case Substantial = 'http://eidas.europa.eu/LoA/substantial';
case High = 'http://eidas.europa.eu/LoA/high';
public function rank(): int
public function meetsOrExceeds(self $required): bool
}

Lancia o fallisce con: nulla da rank() o meetsOrExceeds(). La costruzione nativa dell’enum tramite LoaLevel::from() lancia \ValueError su un URI non riconosciuto; LoaLevel::tryFrom() restituisce null invece.

final class LoaMapping
{
public function loaForService(TspService $service): LoaAssertion
}

Lancia o fallisce con: nulla. Il metodo è totale — ogni input TspService produce una LoaAssertion.

I DTO di input NextPDF\Enterprise\Security\Tsl\TspService e NextPDF\Enterprise\Security\Tsl\TspServiceQualifier sono DTO pubblici stabili (@api). La mappatura consulta TspService::STATUS_GRANTED, TspService::TYPE_CA_QC e le costanti del qualificatore TspServiceQualifier::QSCD_STATEMENT (QCWithQSCD), TspServiceQualifier::NO_QSCD (QCNoQSCD), TspServiceQualifier::FOR_ESIG e TspServiceQualifier::FOR_ESEAL.

final readonly class LoaAssertion
{
/**
* @param list<non-empty-string> $reasons Machine-readable reason codes for the assertion.
*/
public function __construct(
public LoaLevel $level,
public array $reasons,
) {}
}

Lancia o fallisce con: nulla. Value object immutabile.

final readonly class CertPiiGuard
{
public function __construct(
private bool $disclosePii = false,
) {}
public function disclosesPii(): bool
public function guardSignerCommonName(string $signer): string
public function guardDistinguishedName(string $dn): string
public function guardTsaName(string $tsaName): string
public function guardRootIssuer(string $issuer): string
public function guardChainIssue(string $issue): string
}

Lancia o fallisce con: nulla. Le protezioni sono trasformazioni di stringa pure. Su un componente DN che non può essere tokenizzato con sicurezza, la protezione fallisce in modo chiuso e collassa il componente a [REDACTED] anziché emettere un valore parzialmente mascherato.

Analizza un URI del LoA e confrontalo con una soglia minima richiesta.

loa-quick-start.php
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Enterprise\Security\Eidas\LoaLevel;
// A LoA URI as persisted in an audit record or received from a peer system.
$uri = 'http://eidas.europa.eu/LoA/substantial';
try {
$level = LoaLevel::from($uri);
} catch (\ValueError $e) {
// Unknown URI: refuse to classify. Never guess an assurance level.
echo "Unrecognized LoA URI: {$uri}\n";
exit(1);
}
echo 'Level: ' . $level->name . ' (rank ' . $level->rank() . ")\n";
echo 'Meets substantial: ' . ($level->meetsOrExceeds(LoaLevel::Substantial) ? 'yes' : 'no') . "\n";
echo 'Meets high: ' . ($level->meetsOrExceeds(LoaLevel::High) ? 'yes' : 'no') . "\n";

Output atteso:

Level: Substantial (rank 2)
Meets substantial: yes
Meets high: no

Classifica una voce di trusted list, applica un vincolo su un livello richiesto ed emetti un record di audit occultato.

loa-audit-gate.php
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Enterprise\Security\Eidas\LoaLevel;
use NextPDF\Enterprise\Security\Eidas\LoaMapping;
use NextPDF\Enterprise\Security\Tsl\TspService;
use NextPDF\Enterprise\Security\Tsl\TspServiceQualifier;
use NextPDF\Enterprise\Signature\Eidas\CertPiiGuard;
// Normally produced by the Enterprise trusted-list subsystem from a
// member-state TSL; constructed inline here for a self-contained example.
$caPem = (string) file_get_contents(__DIR__ . '/example-qc-ca.pem');
$service = new TspService(
tspName: 'Example Qualified TSP',
serviceName: 'Example Qualified CA G2',
serviceTypeIdentifier: TspService::TYPE_CA_QC,
serviceStatus: TspService::STATUS_GRANTED,
statusStartingTime: '2024-01-01T00:00:00Z',
serviceCertificatePem: $caPem,
qualifiers: [
new TspServiceQualifier(qualifierUri: TspServiceQualifier::QSCD_STATEMENT),
new TspServiceQualifier(qualifierUri: TspServiceQualifier::FOR_ESIG),
],
additionalServiceInformation: [],
);
try {
// Required floor from deployment configuration; defaults to High.
$required = LoaLevel::from(getenv('LOA_REQUIRED') ?: LoaLevel::High->value);
} catch (\ValueError $e) {
echo "Invalid LOA_REQUIRED URI; refusing to continue.\n";
exit(1);
}
$mapping = new LoaMapping();
$assertion = $mapping->loaForService($service);
// Privacy by default: signer identity fields are redacted in audit output.
$guard = new CertPiiGuard();
$audit = [
'loa' => $assertion->level->value,
'reasons' => $assertion->reasons,
'meets_required' => $assertion->level->meetsOrExceeds($required),
'signer' => $guard->guardSignerCommonName('CN=Jane Example, O=Example Corp, C=DE'),
];
echo json_encode($audit, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n";

Output atteso:

{
"loa": "http://eidas.europa.eu/LoA/high",
"reasons": [
"ca_qc_with_qscd",
"esig_or_eseal"
],
"meets_required": true,
"signer": "CN=[REDACTED], O=Example Corp, C=DE"
}
  • LoaLevel::from() lancia \ValueError su URI sconosciuti. Usa LoaLevel::tryFrom() dove è preferibile la gestione di null.
  • Le prove sui dispositivi in conflitto restano conservative. Un servizio che porta sia QCWithQSCD sia QCNoQSCD mappa a Substantial, non High.
  • Un servizio CA/QC granted senza qualificatori mappa a Substantial con motivazione ca_qc_no_qscd_or_unspecified — qualificato per impostazione predefinita, dispositivo non comprovato.
  • Gli URI dei qualificatori esterni all’insieme tracciato non influiscono sulla classificazione. Qualificatori sconosciuti o futuri non alzano mai il livello.
  • La mappatura legge solo lo stato corrente del servizio. Non valuta la cronologia di statusStartingTime; le finestre point-in-time appartengono al livello di validazione.
  • Persisti l’URI di backing dell’enum, non l’intero di rank(). I rank esistono solo per il confronto.
  • CertPiiGuard collassa interamente a [REDACTED] un nome nudo privo di =; le stringhe vuote passano invariate attraverso tutte le protezioni.
  • I DN legacy separati da slash di OpenSSL vengono rilevati e mascherati strutturalmente. Uno / all’interno di un valore RFC 4514 è trattato come contenuto, non come separatore.
  • Gli attributi DN non-PII (O, OU, C, ST, L) sono preservati, così il ragionamento giurisdizionale sopravvive all’occultamento.
  • Privacy per impostazione predefinita. Il costruttore della protezione ha come predefinito disclosePii: false. Costruisci new CertPiiGuard(disclosePii: true) solo dove disponi di una base giuridica documentata per il trattamento dell’identità del firmatario. Questo attua la minimizzazione dei dati dell’articolo 5, paragrafo 1, lettera c) del GDPR al confine di serializzazione.
  • Occultamento fail-closed. Quando un componente DN non può essere tokenizzato con sicurezza, l’intero componente collassa a [REDACTED]. Un controllo di privacy non fallisce mai in modo aperto.
  • Output deterministico. Le protezioni usano un’elaborazione di stringa pura — nessun orologio, nessuna casualità — così l’output mascherato è byte-stabile per input identici. Un output stabile mantiene significativi i diff di audit.
  • L’occultamento non è cifratura. [REDACTED] rimuove il valore dal record. Se hai bisogno che l’identità sia recuperabile, conservala separatamente sotto la propria base giuridica e il proprio controllo di accesso.
  • Immondizia in ingresso, immondizia in uscita. Una LoaAssertion è affidabile solo quanto le prove della trusted list che vi stanno dietro. Acquisisci e verifica la firma delle trusted list attraverso il sottosistema trusted-list Enterprise prima di alimentare le voci alla mappatura.

NextPDF Enterprise implementa un comportamento informato dal regolamento (UE) n. 910/2014 articolo 8 (livelli di garanzia) e articolo 3, punto 12) (elementi di una firma elettronica qualificata), e dal vocabolario dei qualificatori delle trusted-list ETSI. Il supporto non è conformità, e la conformità non è certificazione. NextPDF non detiene alcuna certificazione e non ne concede alcuna. NextPDF non è un prestatore di servizi fiduciari qualificato, non è un organismo di valutazione della conformità e non è un organismo di vigilanza. Una LoaAssertion è una classificazione software di prove pubblicate. Non è una determinazione giuridica di qualificazione o di garanzia, e non può rendere qualificata una firma.

Il regolamento (UE) 2024/1183 (eIDAS 2) continua a fare riferimento ai livelli dell’articolo 8 e richiede che i portafogli europei di identità digitale siano forniti al livello di garanzia elevato. Questa pagina lo cita come contesto normativo; NextPDF non fa alcuna dichiarazione di capacità relativa ai portafogli.

Se una specifica firma soddisfi una policy strutturale orientata a eIDAS è una questione separata, cui risponde il modulo di validazione; vedi Validazione.

Le classi LoA eIDAS non eseguono alcuna operazione crittografica — nessun hashing, nessuna verifica di firma, nessuna casualità. La policy di modalità FIPS Enterprise vincola le scelte crittografiche, quindi non ha nulla da vincolare in questo modulo. Abilitare la modalità FIPS non modifica la mappatura del LoA né il comportamento della protezione PII. La verifica crittografica delle firme e delle trusted list è governata dai moduli di verifica e sicurezza, dove si applica la policy di modalità FIPS.

  • LoaMapping::loaForService() è totale e deterministico. Ogni TspService produce una LoaAssertion; il metodo non lancia mai e non consulta orologio, rete o stato globale.
  • La classificazione è conservativa. Prove mancanti, sconosciute o in conflitto abbassano il livello; nulla lo alza tranne prove esplicite di CA/QC granted con QSCD.
  • I codici motivazione sono leggibili dalla macchina e stabili: service_not_granted, service_not_qualified_ca, ca_qc_with_qscd, esig_or_eseal, qc_default, ca_qc_no_qscd_or_unspecified.
  • L’ordine dei livelli è fisso: Low < Substantial < High, esposto tramite rank() e meetsOrExceeds().
  • CertPiiGuard ha come predefinito l’occultamento e fallisce in modo chiuso in caso di dubbio sulla tokenizzazione. Con disclosePii: true, ogni protezione restituisce il proprio input verbatim.
  • L’output della protezione è byte-stabile per input identici.

NextPDF Core verifica crittograficamente le firme PDF e fallisce in modo chiuso su prove corrotte. Core non ha alcun modello di trusted-list UE, nessun vocabolario LoaLevel, nessuna mappatura del LoA e nessuna protezione PII di livello eIDAS per la serializzazione di audit. Con Core da solo, devi derivare tu stesso le classificazioni di garanzia dai dati di fiducia che mantieni, e applicare il tuo occultamento prima che i record di audit lascino il processo.

Questa pagina documenta solo il comportamento osservabile esternamente e la superficie API pubblica supportata. Percorsi di namespace interni, classi helper, tabelle di meccanismi, nomi di file di runbook e prefissi di ticket sono fuori ambito.