Technischer Artikel

PAdES-LTV-Evidenz und Seed Values in HotPDF

Ein soeben signiertes PDF ist eine B-B-Signatur und nichts weiter. Es beweist, wer unterschrieben hat, und dass die Bytes sich nicht bewegt haben, aber es trägt keinen Beweis dafür, dass das Unterzeichnerzertifikat zum Signaturzeitpunkt gültig war, also muss ein Validator Jahre später nach Widerrufsdaten suchen, die längst nicht mehr existieren mögen. Diese Lücke zu schließen bedeutet, OCSP-Antworten und CRLs in den dokumentweiten Document Security Store zu schreiben, und in HotPDF ist das ein einziger Aufruf: PopulatePAdESLTVEvidence läuft durch jede geladene Signatur, leitet die Widerrufsanfragen aus dem Zertifikatssatz ab, führt sie über einen Transport aus, den Sie liefern, und schreibt das geholte Material plus die CMS-Kette in den DSS. Sie gibt die Anzahl der Signaturen zurück, deren Evidenz landete, oder minus eins, wenn das Dokument überhaupt kein Signaturfeld hat

Die Designentscheidung, die man verstehen sollte, bevor man sie nutzt: Die Bibliothek öffnet niemals einen Socket. Jedes Byte, das aus dem Netzwerk ankommt, kommt durch einen Callback, den Sie geschrieben haben. Das ist keine Vorsicht um der Vorsicht willen; es ist der einzige Weg, wie dieses Feature in den Umgebungen funktionieren kann, die Langzeitvalidierung tatsächlich verlangen

Warum weigert sich die Bibliothek, eigenes HTTP zu fahren?

Weil die Orte, die B-LT-Signaturen verlangen, die Orte sind, an denen man einer Bibliothek das Netzwerk nicht anvertrauen kann. Signaturdienste laufen hinter authentifizierenden Proxys mit Unternehmens-Roots. Air-gapped Signatur-Ebenen haben keinen Weg zu einem Responder und müssen mit gecachter Evidenz gefüttert werden. Audit-Regime verlangen, dass jede ausgehende Anfrage von der Anwendung protokolliert wird, nicht in einer Abhängigkeit vergraben. Und Test-Suiten brauchen deterministische Antworten, was unmöglich ist, wenn die Bibliothek eigenmächtig hinauswählt

Der Transport ist eine schlichte Funktionsreferenz mit fester Gestalt, also bleibt die Richtlinie Ihre. HotPDF reicht Ihnen einen Anfragedatensatz weiter, der genau beschreibt, was zu holen ist, einschließlich Content-Typ und einer Obergrenze für die Antwortgröße, und Sie geben die Bytes plus einen Status zurück

Der PopulatePAdESLTVEvidence-Ablauf in HotPDF: der vom Aufrufer gelieferte FetchEvidence-Transport, Anfragedatensatz-Felder und Statusausgänge je Signatur
Jedes Netzwerk-Byte läuft durch Ihren FetchEvidence-Callback, und jede Signatur bekommt ihren eigenen Status, sodass ein Timeout den Durchlauf nie abbricht
function FetchEvidence(const Request: THPDFSignatureEvidenceRequest;
  Attempt: Integer; CancellationToken: THPDFCancellationToken;
  out Response: TBytes; out RetryAfterMS: Cardinal;
  out ErrorMessage: UnicodeString): THPDFSignatureEvidenceTransportStatus;
begin
  RetryAfterMS := 0;
  try
    // Request.Kind sagt, ob dies ein OCSP-POST oder ein CRL-GET ist;
    // Request.ContentType und Request.Body sind bereits vorbereitet,
    // und Request.MaxResponseBytes ist die Obergrenze, die Sie einhalten müssen
    Response := HttpExchange(Request.URI, Request.ContentType,
      Request.Body, Request.MaxResponseBytes);
    Result := setsSucceeded;
  except
    on E: Exception do
    begin
      ErrorMessage := E.Message;
      // setsRetry lässt die Retry-Richtlinie zurückweichen; für eine 404
      // oder eine schlechte URL verwenden Sie setsPermanentFailure
      Result := setsRetry;
    end;
  end;
end;

// B-B-nach-B-LT-Upgrade mit einem Aufruf für jede Signatur in der geladenen Datei
var
  Pdf: THotPDF;
  Upgraded: Integer;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.BeginIncrementalUpdate('signed.pdf');
    Upgraded := Pdf.PopulatePAdESLTVEvidence(FetchEvidence,
      THPDFSignatureEvidenceRetryPolicy.Default);
    if Upgraded > 0 then
      // Append-only-Speicherung: Die Bytes, die die bestehenden Signaturen
      // abdecken, bleiben wortwörtlich erhalten
      Pdf.SaveIncrementalUpdate('signed-lt.pdf');
  finally
    Pdf.Free;
  end;
end;

Fehler gelten je Signatur, nicht je Dokument. Ein Responder, der für einen Unterzeichner ein Timeout hat, überspringt das Material dieses Unterzeichners und lässt den Rest des Durchlaufs intakt, was das Verhalten ist, das man im Batch will: Partielle Evidenz schlägt einen abgebrochenen Lauf, und der Rückgabewert sagt Ihnen, wie viele Signaturen tatsächlich verbessert wurden

Die Kette, die das CMS zu liefern vergaß

Die Widerrufsprüfung braucht das Issuer-Zertifikat, und eine erstaunliche Zahl von Signaturstacks lässt die Intermediates aus dem CMS-Container weg. Der Bergungsweg ist die Authority-Information-Access-Erweiterung, Zugriffsmethode 1.3.6.1.5.5.7.48.2, die eine URL anpreist, unter der das Issuer-Zertifikat herunterladbar ist. HPDFFetchAIAIntermediates läuft diese URLs über denselben Transport ab, parst das DER aus jeder Antwort und gibt nur die Zertifikate zurück, die das CMS noch nicht mitführte, indiziert nach DER-Hash, damit Duplikate und Schleifen sich nicht drehen können

Zwei Details entscheiden, ob das gegen echte Zertifizierungsstellen funktioniert. Das erste ist die Kodierung: CA-Endpunkte liefern das Zertifikat etwa genauso oft als nacktes DER wie PEM-gepanzert, und es gibt keinen verlässlichen Content-Typ, um sie zu unterscheiden. Die robuste Sonde ist erst textuell, dann strukturell. Suchen Sie nach der -----BEGIN CERTIFICATE------Markierung, entfernen Sie die Panzerung und dekodieren Sie Base64, falls sie vorhanden ist, und bestätigen Sie in beiden Pfaden, dass das erste Byte des Ergebnisses $30 ist, das DER-Tag für eine SEQUENCE. Das zweite ist die Tiefe: Ein geholtes Intermediate kann selbst eine AIA-URL für seinen eigenen Issuer anpreisen, also hängt der Lauf neue Kandidaten an die Warteschlange an und vervollständigt Ketten, die zwei oder drei Hops zu kurz sind. Das muss begrenzt werden, wofür der Parameter MaxFetch da ist

AIA-Kettenvervollständigung für HotPDF: caIssuers-URL-Abholung, PEM-gegen-DER-Sonde, DER-Hash-Deduplizierung und die MaxFetch-Tiefenbegrenzung
HPDFFetchAIAIntermediates läuft caIssuers-URLs über denselben Transport ab, sondiert die PEM-Panzerung und begrenzt die Warteschlange mit MaxFetch

Was ist ein Signatur-Seed Value, und warum scheitert er still?

Ein Seed Value ist eine Einschränkung, die der Dokumentautor an ein Signaturfeld hängt, um dem Unterzeichner zu sagen, welche Art von Signatur akzeptabel ist: welcher SubFilter, welcher Digest-Algorithmus, welche Gründe, welche Mindest-PDF-Version, ob Widerrufsinformationen eingebettet sein müssen. Er lebt in einem /SV-Dictionary auf dem Feld und ist in ISO 32000-1 §12.7.5.5 definiert. HotPDF schreibt ihn mit AttachPAdESSeedValue und prüft ihn mit CheckLoadedSignatureSeedValue, das True zurückgibt, wenn das Feld unbeschränkt ist oder jede vorhandene Einschränkung besteht, und bei False die erste scheiternde Einschränkung über einen Ausgabeparameter nennt, den Sie direkt in eine Fehlermeldung einsetzen können

Der Mechanismus, der Seed Values leicht falsch machbar macht, ist der in §12.7.5.5.3 beschriebene /Ff-Flags-Eintrag. Ein gesetztes Bit markiert seine Einschränkung als erforderlich: Eine Abweichung ist ein Fehler, und der Unterzeichner muss sich verweigern. Ein gelöschtes Bit markiert dieselbe Einschränkung als Präferenz: Der Wert filtert, was die UI anbieten sollte, und nichts weiter. Daraus folgen zwei Fallen. Erstens lebt /Ff innerhalb des /SV-Dictionarys, nicht auf der Widget-Annotation, also bekommt Code, der das Feld-/Ff liest, für immer eine leere Antwort und schließt, dass nichts erzwungen wird. Zweitens sind die Bit-Zuweisungen keine einfache Folge von eins, zwei, vier, acht; in HotPDF emittiert der Writer 2 für SubFilter, 4 für MinVersion, 32 für AddRevInfo und 64 für DigestMethod. Ein Reader, der sequenzielle Bits annimmt, dekodiert jede Einschränkung als optional und besteht jeden Test außer dem, der zählt

Seed-Value-Flag-Bit-Tabelle für HotPDF-PAdES-Signierung mit Ff-Bits 2, 4, 32 und 64 sowie erforderlich-gegen-Präferenz-Behandlung von Einschränkungen
Der /Ff-Eintrag lebt innerhalb von /SV, und jede Bitposition entscheidet, ob eine Abweichung eine harte Verweigerung oder eine UI-Präferenz ist
var
  Violation: AnsiString;
begin
  // Das Feld fragen, ob das Profil, mit dem wir gleich signieren, erlaubt ist
  if not Pdf.CheckLoadedSignatureSeedValue(0, 'ETSI.CAdES.detached',
       'SHA256', 'Approved for payment', 1, Violation) then
    raise Exception.Create('Signature field rejects this profile: ' +
      String(Violation));
  // Einschränkung erfüllt: mit dem Signaturdurchlauf fortfahren
end;

Der Test, der den ursprünglichen Dekodier-Fehler aufdeckte, war kein Positivtest. Es war die Assertion, dass eine erzwungene Abweichung zurückgewiesen werden muss, und sie ist die einzige Testart, die diese Fehlerklasse fangen kann: Ein Dekodierer, der das falsche Dictionary oder die falschen Bitpositionen liest, erzeugt für jede Eingabe „keine Einschränkung verletzt“, was exakt wie korrektes Verhalten aussieht, bis man absichtlich eine verletzt

Wo das auf der LTV-Leiter steht

Vier Sprossen, und jede braucht die darunter. B-B ist die nackte Signatur. B-T fügt einen vertrauenswürdigen Zeitstempel hinzu, der die Signaturzeit festhält, sodass ein Validator weiß, gegen welchen Moment er den Widerruf bewertet. B-LT fügt die Widerrufsevidenz dem DSS hinzu, was PopulatePAdESLTVEvidence automatisiert. B-LTA fügt Dokumentzeitstempel hinzu, die erneuert werden, bevor der vorherige schwächelt, und die Gültigkeit unbegrenzt verlängern; HotPDF stellt das als RenewPAdESLTATimestamp bereit, das einen neuen Zeitstempel als inkrementelle Revision anhängt und jede frühere Signatur, jeden Zeitstempel und jeden DSS-Eintrag unangetastet bewahrt

Ein Inkrementell-Update-Modell ist der einzige korrekte Weg, Evidenz zu einem signierten Dokument hinzuzufügen, denn ein Umschreiben der Datei würde die Bytebereiche zerstören, die die bestehenden Signaturen abdecken. Wenn Sie darüber nachdenken müssen, was sich zwischen Revisionen änderte und ob diese Änderungen die Art sind, die eine Signatur erlaubt, wird diese Analyse separat behandelt in der DocMDP- und FieldMDP-Revisionsanalyse. Die Signaturpipeline selbst, einschließlich Zertifikatsquellen und Byte-Order-Fallen, steckt in dem PAdES-Signaturdurchgang, und die Validierungsseite in Signaturen auf geladenen Dokumenten verifizieren

Eine praktische Warnung zur Reihenfolge. Sammeln Sie die Evidenz so früh wie möglich nach dem Signieren, idealerweise im selben Job. Die Responder, die für ein Zertifikat antworten können, sind online, solange das Zertifikat aktuell ist, und Jahre später verschwunden, also kann ein Dokument, das Ihre Pipeline als B-B verlässt, möglicherweise nie wieder angehoben werden. HotPDF läuft als native VCL-Komponente für Delphi und C++Builder, und der gesamte Evidenzdurchlauf ist in-process abgesehen von Ihrem eigenen Transport; die unterstützten Profile listet die Produktseite der HotPDF Delphi PDF-Komponente