Article technique

Signatures PDF longue durée en Delphi : PAdES B-LT et B-LTA

Pour qu'un PDF signé se vérifie encore dans plusieurs années, une fois le certificat de signature expiré et son autorité de certification renouvelée, PDFium Component sait produire des signatures PAdES longue durée sous Windows : un horodatage RFC 3161 pour le temps de confiance, un Document Security Store qui incorpore le matériel de validation, et un DocTimeStamp d'archive couvrant tout le fichier. Ces trois ajouts sont les niveaux de référence PAdES B-T, B-LT et B-LTA, et PDFium Component les atteint tous depuis un seul appel de signature. C'est une capacité réservée à Windows, conditionnée par PadesCryptoAvailable

Cet article est le troisième d'une série. Le premier, signer des PDF en PAdES B-B avec PDFium VCL, couvre la signature de base ; le deuxième, inspecter les signatures numériques PDF et les niveaux PAdES, couvre la relecture d'une signature et l'identification du niveau atteint. Ici la préoccupation est l'archive : des signatures qui doivent survivre à l'expiration du certificat et rester vérifiables pendant une durée de conservation comptée en années, pas en semaines

Pourquoi une signature PDF valide cesse-t-elle de se vérifier avec le temps ?

Une signature de base ne répond qu'à une seule question : ces octets ont-ils été modifiés après la signature. Elle ne prouve pas à elle seule quand la signature a eu lieu, et ce manque est ce qui la casse plus tard. La structure CMS porte un attribut d'heure de signature, mais le signataire y écrit la valeur de sa propre horloge : un validateur n'a donc aucune raison de lui faire confiance. Quand le certificat de signature expire ensuite ou que l'autorité le révoque, un validateur strict ne peut plus distinguer une signature faite alors que le certificat était valide d'une signature forgée après sa péremption. La signature allait bien le jour où elle a été faite et devient invérifiable sans qu'elle y soit pour rien

L'archivage longue durée corrige cela en deux mouvements. D'abord, un tiers de confiance, une autorité d'horodatage, atteste l'heure cryptographiquement, si bien qu'elle ne dépend plus de l'honnêteté du signataire. Ensuite, chaque certificat, réponse de révocation et CRL nécessaire pour bâtir et contrôler la chaîne de confiance est incorporé dans le PDF lui-même, si bien que la validation ne dépend pas de serveurs qui auront peut-être disparu le jour où quelqu'un regardera. PAdES, normalisé sous ETSI EN 319 142-1, dispose ces éléments en niveaux de référence, et PDFium Component écrit les structures que chaque niveau exige

Qu'est-ce qu'une signature PDF LTV ou à horodatage d'archive ?

PAdES définit quatre niveaux de référence qui s'appuient les uns sur les autres, et PDFium Component les expose par l'énumération TPadesLevel (plB_B, plB_T, plB_LT, plB_LTA). B-B est la signature simple. B-T ajoute un horodatage de confiance sur la valeur de signature. B-LT (longue durée) ajoute le matériel de validation incorporé, la propriété que la plupart des gens désignent par « LTV ». B-LTA (longue durée avec horodatage d'archive) enveloppe le tout dans un horodatage de plus qui couvre le fichier entier, si bien que le matériel incorporé est lui-même démontrablement intact depuis l'instant de l'archivage

La lecture pratique est un escalier. B-T prouve quand. B-LT prouve avec quoi la signature peut encore être contrôlée. B-LTA prouve que l'ensemble du paquet n'a pas été altéré depuis son scellement, et c'est le niveau que vous renouvelez, en ajoutant un DocTimeStamp frais avant l'expiration du précédent, pour prolonger l'archive indéfiniment. Pour un contrat ou un enregistrement de conformité soumis à une longue obligation de conservation, B-LTA est la cible ; B-LT est le plancher pragmatique

Schéma en escalier des quatre niveaux de référence PAdES produits par PDFium Component pour Delphi, montrant comment B-B grandit en B-T, B-LT et B-LTA
Chaque niveau ajoute une brique — B-T lie le temps de confiance, B-LT incorpore le magasin de validation, et B-LTA enveloppe le fichier scellé dans un horodatage d'archive renouvelable

Ajouter le temps de confiance : PAdES B-T avec RFC 3161

PDFium Component transforme une signature B-B en B-T en posant deux champs sur TPadesSignOptions : montez Level à plB_T et fournissez une TsaUrl. Quand les deux sont présents, la chaîne de signature hache les octets bruts de la signature en SHA-256, empaquette ce condensé comme messageImprint RFC 3161, poste la requête à l'autorité d'horodatage par WinHttp, et incorpore le jeton renvoyé comme attribut non signé signature-time-stamp (OID 1.2.840.113549.1.9.16.2.14) dans les unsignedAttrs [1] de SignerInfo, selon EN 319 142-1 §6.3. L'horodatage couvre spécifiquement la valeur de signature, ce qui lie le temps de confiance à cette signature exacte

Schéma de flux aller-retour d'une application Delphi utilisant PDFium Component pour poster une requête RFC 3161 à une autorité d'horodatage et incorporer le jeton renvoyé
Avec Level monté à plB_T et une TsaUrl définie, le composant hache la signature, obtient un jeton RFC 3161 de l'autorité et le stocke comme attribut non signé
uses
  PDFium, FPdfPades;

procedure SignWithTimestamp;
var
  Pdf: TPdf;
  Options: TPadesSignOptions;
begin
  Pdf := TPdf.Create(nil);
  try
    if not Pdf.PadesCryptoAvailable then
      raise Exception.Create('PAdES signing backend is Windows-only');
    Pdf.FileName := 'contract.pdf';
    Pdf.Active := True;

    Options := TPadesSignOptions.Default;
    Options.CertificateThumbprint := 'A1B2C3D4E5F6071829304152637485960A1B2C3D';
    Options.Level  := plB_T;
    Options.TsaUrl := 'http://timestamp.example-tsa.com/tsr';
    Options.Reason := 'Contract execution';
    // Nonce laissé à 0 : le composant dérive une valeur anti-rejeu unique.

    Pdf.SignPades('contract-bt.pdf', Options);
  finally
    Pdf.Free;
  end;
end;

Le CertificateThumbprint est le condensé SHA-1, en hexadécimal, d'un certificat du magasin « MY » de l'utilisateur courant dont vous pouvez utiliser la clé privée. Le champ Nonce est la valeur anti-rejeu RFC 3161 ; laissez-le à zéro et le composant en dérive une unique par requête à partir d'un repli SHA-256 sur un compteur, l'horloge, le compteur de ticks et l'identifiant de processus, si bien que deux requêtes émises dans la même milliseconde n'entrent pas en collision. Ne passez votre propre valeur que si vous disposez d'un générateur aléatoire cryptographique auquel vous préférez faire confiance. Une réserve honnête : B-T exige une autorité d'horodatage joignable, donc signer implique désormais un appel réseau et hérite de la disponibilité et de la latence de cette autorité

Incorporer le matériel de validation : B-LT et B-LTA en un seul appel

Le passage à la validation longue durée tient en un seul changement : posez Level à plB_LTA et gardez la TsaUrl. PDFium Component parcourt alors tout l'escalier à l'intérieur d'un unique appel SignPades. Il signe en B-B, horodate pour B-T, injecte le Document Security Store pour B-LT et ajoute l'horodatage d'archive pour B-LTA, chacun comme sa propre mise à jour incrémentielle, de sorte que les octets antérieurs restent intacts octet pour octet

procedure SignForArchive;
var
  Pdf: TPdf;
  Options: TPadesSignOptions;
begin
  Pdf := TPdf.Create(nil);
  try
    Pdf.FileName := 'contract.pdf';
    Pdf.Active := True;

    Options := TPadesSignOptions.Default;
    Options.CertificateThumbprint := 'A1B2C3D4E5F6071829304152637485960A1B2C3D';
    Options.Level    := plB_LTA;   // enchaîne B-B -> B-T -> B-LT -> B-LTA
    Options.TsaUrl   := 'http://timestamp.example-tsa.com/tsr';
    Options.Location := 'Head Office';

    // Un seul appel écrit l'horodatage, le DSS et le DocTimeStamp d'archive.
    Pdf.SignPades('contract-lta.pdf', Options);
  finally
    Pdf.Free;
  end;
end;

Pour l'étape B-LT, PDFium Component construit la chaîne de certificats avec CertGetCertificateChain et écrit un dictionnaire /DSS portant le certificat du signataire et chaque autorité intermédiaire dans un tableau /Certs (avec les tableaux parallèles /OCSPs et /CRLs), aux côtés d'un marqueur /Extensions /ESIC de niveau 1, exactement comme le prescrit EN 319 142-1 §5.4.2. La racine autosignée est délibérément omise, puisque RFC 5652 §10.2.3 le permet et que la racine est déjà une ancre de confiance que le validateur détient. Le résultat est une signature qu'un lecteur peut vérifier avec le seul fichier en main

Pour B-LTA, le composant ajoute un Document Time-stamp : un dictionnaire de signature avec /SubFilter /ETSI.RFC3161 dont le /ByteRange couvre le fichier entier, son /Contents portant un jeton RFC 3161 sur cette plage, et il promeut le marqueur ESIC au niveau 2. C'est l'étape d'archive du §5.4.3 et de TS 119 142-3. Parce que le DocTimeStamp couvre le DSS aussi bien que la signature, il prouve que le matériel de validation incorporé était présent et inaltéré au moment de l'archivage, ce qui est précisément ce qu'une longue politique de conservation doit pouvoir montrer

Schéma en couches de la disposition du fichier montrant les mises à jour incrémentielles qu'un seul appel SignPades en Delphi écrit : la valeur de signature, le jeton d'horodatage, le magasin DSS et le DocTimeStamp d'archive
Un appel plB_LTA écrit quatre étapes ajoutées — signature d'origine, horodatage de signature, magasin de validation DSS, puis un DocTimeStamp sur tout le fichier qui les scelle toutes

Augmenter une signature qui existe déjà

Parfois la signature est déjà sur le document et vous devez seulement ajouter ou rafraîchir le magasin de validation, par exemple pour hisser une signature B-B d'un tiers au niveau B-LT pour votre archive. PDFium Component expose l'injecteur de DSS directement par SaveAsPadesDss, qui ajoute les structures /DSS et /Extensions comme une mise à jour incrémentielle sans toucher aux octets de la signature existante

procedure AddValidationStore;
var
  Pdf: TPdf;
  DssOpts: TPadesDssOptions;
  Cert: TPadesDssMaterial;
begin
  Pdf := TPdf.Create(nil);
  try
    Pdf.FileName := 'already-signed.pdf';
    Pdf.Active := True;

    DssOpts := TPadesDssOptions.Default;
    DssOpts.EsicExtensionLevel := 1;         // 1 pour B-LT, 2 pour B-LTA
    Cert.DerBytes := LoadSignerCertDer;       // votre certificat encodé en DER
    SetLength(DssOpts.Certs, 1);
    DssOpts.Certs[0] := Cert;

    Pdf.SaveAsPadesDss('already-signed-lt.pdf', DssOpts);
  finally
    Pdf.Free;
  end;
end;

Vous fournissez les certificats encodés en DER, et facultativement les réponses OCSP et les CRL, dont un validateur aura besoin. Posez EsicExtensionLevel à 1 pour un magasin B-LT ou à 2 quand un DocTimeStamp suivra. Laissez IncludeVri à sa valeur par défaut False : EN 319 142-1 §5.4.2.3 traite le dictionnaire /VRI par signature comme facultatif et déconseille son usage, sauf si un lecteur précis que vous visez l'exige

Coûts et limites à prévoir

Trois limites honnêtes déterminent où ces niveaux trouvent leur place. D'abord, le moteur cryptographique est réservé à Windows : la signature et l'horodatage passent par les magasins CNG et WinHttp de la plateforme, si bien que PadesCryptoAvailable renvoie False ailleurs et que SignPades lève. L'inspection côté lecture couverte dans l'article compagnon reste multiplateforme ; seule l'écriture des signatures est liée à Windows. Ensuite, B-T et B-LTA dépendent d'une autorité d'horodatage, ce qui signifie un aller-retour réseau au moment de la signature et un service externe dont la disponibilité et les limites de débit deviennent une part de votre chemin de signature

Enfin, chaque niveau coûte du stockage. Chaque étape ajoute une mise à jour incrémentielle plutôt que de réécrire le fichier, le DSS incorpore une chaîne de certificats complète, et le DocTimeStamp d'archive réserve de la place pour son jeton : un fichier B-LTA est donc sensiblement plus gros que l'original B-B. C'est l'arbitrage assumé : vous dépensez des octets maintenant pour acheter de la vérifiabilité plus tard. Pour la plupart des archives contractuelles et de conformité, c'est le bon arbitrage, mais il vaut la peine de le mesurer sur vos propres documents plutôt que de le supposer. Quand vous devez confirmer qu'un fichier terminé a bien atteint le niveau visé, vérifiez-le avec les techniques de l'inspection des signatures numériques PDF et des niveaux PAdES, et si vous durcissez plus largement une chaîne documentaire, les notes sur l'audit des risques de sécurité des PDF couvrent les contrôles environnants

La signature PAdES, le DSS et les fonctions d'horodatage d'archive présentées ici font partie de PDFium Component pour Delphi et C++Builder, dont la page produit porte la référence complète de signature et les prérequis de plateforme