Τεχνικό Άρθρο

Αποδείξεις PAdES LTV και seed values στο HotPDF

Ένα PDF που μόλις υπογράψατε είναι μια υπογραφή B-B και τίποτα περισσότερο. Αποδεικνύει ποιος υπέγραψε και ότι τα bytes δεν μετακινήθηκαν, αλλά δεν κουβαλά απόδειξη ότι το πιστοποιητικό του υπογράφοντος ήταν έγκυρο τη στιγμή της υπογραφής, οπότε ένας validator χρόνια μετά πρέπει να ψάξει δεδομένα ανάκλησης που μπορεί να μην υπάρχουν πια. Το κλείσιμο αυτού του κενού σημαίνει γραφή απαντήσεων OCSP και CRLs στο Document Security Store επιπέδου εγγράφου, και στο HotPDF αυτό είναι μία κλήση: η PopulatePAdESLTVEvidence διατρέχει κάθε φορτωμένη υπογραφή, εξάγει τα αιτήματα ανάκλησης από το σύνολο πιστοποιητικών, τα εκτελεί μέσω μιας μεταφοράς που εσείς παρέχετε, και γράφει το υλικό που ανακτήθηκε συν την αλυσίδα CMS στο DSS. Επιστρέφει τον αριθμό των υπογραφών των οποίων οι αποδείξεις κατέληξαν, ή μείον ένα όταν το έγγραφο δεν έχει καθόλου πεδίο υπογραφής

Η απόφαση σχεδιασμού που αξίζει να κατανοήσετε πριν τη χρησιμοποιήσετε είναι ότι η βιβλιοθήκη δεν ανοίγει ποτέ socket. Κάθε byte που φτάνει από το δίκτυο φτάνει μέσω μιας callback που γράψατε εσείς. Αυτό δεν είναι προφύλαξη για χάρη της προφύλαξης· είναι ο μόνος τρόπος να δουλέψει αυτή η λειτουργία μέσα στα περιβάλλοντα που απαιτούν πραγματικά μακροχρόνια επικύρωση

Γιατί η βιβλιοθήκη αρνείται να κάνει το δικό της HTTP;

Επειδή οι τόποι που απαιτούν υπογραφές B-LT είναι οι τόποι όπου μια βιβλιοθήκη δεν μπορεί να εμπιστευτεί το δίκτυο. Οι υπηρεσίες υπογραφής τρέχουν πίσω από proxies πιστοποίησης με εταιρικά roots. Τα air-gapped στρώματα υπογραφής δεν έχουν δρόμο προς responder και πρέπει να τροφοδοτούνται με cached αποδείξεις. Τα καθεστώτα ελέγχου απαιτούν κάθε εξερχόμενο αίτημα να καταγράφεται από την εφαρμογή, και όχι θαμμένο σε μια εξάρτηση. Και οι σουίτες δοκιμών χρειάζονται ντετερμινιστικές απαντήσεις, που είναι αδύνατο αν η βιβλιοθήκη καλεί μόνη της έξω

Η μεταφορά είναι μια απλή αναφορά συνάρτησης με σταθερό σχήμα, οπότε η πολιτική παραμένει δική σας. Το HotPDF σας δίνει ένα record αιτήματος που περιγράφει ακριβώς τι να ανακτήσετε, περιλαμβανομένου του content type και ενός ορίου μεγέθους απάντησης, και εσείς επιστρέφετε τα bytes συν μια κατάσταση

Ροή PopulatePAdESLTVEvidence του HotPDF: η μεταφορά FetchEvidence που παρέχει ο καλών, τα πεδία του record αιτήματος και οι καταστάσεις ανά υπογραφή
Κάθε byte δικτύου περνά από τη callback FetchEvidence σας, και κάθε υπογραφή παίρνει τη δική της κατάσταση ώστε ένα timeout να μην εγκαταλείπει ποτέ το πέρασμα
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 λέει αν αυτό είναι OCSP POST ή CRL GET·
    // τα Request.ContentType και Request.Body είναι ήδη έτοιμα,
    // και το Request.MaxResponseBytes είναι το όριο που πρέπει
    // να σεβαστείτε
    Response := HttpExchange(Request.URI, Request.ContentType,
      Request.Body, Request.MaxResponseBytes);
    Result := setsSucceeded;
  except
    on E: Exception do
    begin
      ErrorMessage := E.Message;
      // Το setsRetry αφήνει την πολιτική επαναλήψεων να περιμένει·
      // χρησιμοποιήστε setsPermanentFailure για 404 ή κακή URL
      Result := setsRetry;
    end;
  end;
end;

// Αναβάθμιση B-B σε B-LT με μία κλήση για κάθε υπογραφή στο φορτωμένο αρχείο
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
      // Αποθήκευση μόνο σε προσθήκη: τα bytes που καλύπτουν οι
      // υπάρχουσες υπογραφές διατηρούνται αυτούσια
      Pdf.SaveIncrementalUpdate('signed-lt.pdf');
  finally
    Pdf.Free;
  end;
end;

Οι αστοχίες είναι ανά υπογραφή, όχι ανά έγγραφο. Ένας responder που ξεπερνά το όριο χρόνου για έναν υπογράφοντα παραλείπει το υλικό εκείνου του υπογράφοντος και αφήνει το υπόλοιπο του περάσματος άθικτο, που είναι η συμπεριφορά που θέλετε σε μια δέσμη: μερικές αποδείξεις νικούν μια εγκαταλειμμένη εκτέλεση, και η τιμή επιστροφής σας λέει πόσες υπογραφές βελτιώθηκαν πραγματικά

Η αλυσίδα που το CMS ξέχασε να συμπεριλάβει

Ο έλεγχος ανάκλησης χρειάζεται το πιστοποιητικό του εκδότη, και ένας εκπληκτικός αριθμός στοίβων υπογραφής παραλείπει τα intermediates από το container CMS. Η διαδρομή ανάκτησης είναι η επέκταση Authority Information Access, μέθοδος πρόσβασης 1.3.6.1.5.5.7.48.2, που διαφημίζει μια URL από όπου μπορεί να κατέβει το πιστοποιητικό του εκδότη. Η HPDFFetchAIAIntermediates διατρέχει εκείνες τις URL μέσω της ίδιας μεταφοράς, αναλύει το DER από κάθε απάντηση, και επιστρέφει μόνο τα πιστοποιητικά που το CMS δεν κουβαλούσε ήδη, κλειδωμένα με DER hash ώστε διπλότυπα και βρόχοι να μην μπορούν να στριφογυρίσουν

Δύο λεπτομέρειες αποφασίζουν αν αυτό δουλεύει απέναντι σε πραγματικές αρχές πιστοποίησης. Η πρώτη είναι η κωδικοποίηση: τα endpoints CA σερβίρουν το πιστοποιητικό ως γυμνό DER περίπου όσο συχνά το σερβίρουν θωρακισμένο PEM, και δεν υπάρχει αξιόπιστο content type για τη διάκρισή τους. Η robust δοκιμή είναι textual, μετά structural. Ψάξτε τη σημαία -----BEGIN CERTIFICATE-----, βγάλτε τη θωράκιση και αποκωδικοποιήστε base64 αν είναι παρούσα, και και στις δύο διαδρομές επιβεβαιώστε ότι το πρώτο byte του αποτελέσματος είναι $30, η ετικέτα DER για SEQUENCE. Η δεύτερη είναι το βάθος: ένα ανακτημένο intermediate μπορεί το ίδιο να διαφημίζει URL AIA για τον δικό του εκδότη, οπότε η περιήγηση προσθέτει νέους υποψηφίους στην ουρά και συμπληρώνει αλυσίδες που λείπουν δύο ή τρία άλματα. Πρέπει να περιορίζεται, και για αυτό είναι η παράμετρος MaxFetch

Διάγραμμα συμπλήρωσης αλυσίδας AIA για το HotPDF: ανάκτηση URL caIssuers, δοκιμή PEM έναντι DER, αποδιπλοποίηση με DER hash και το όριο βάθους MaxFetch
Η HPDFFetchAIAIntermediates διατρέχει URL caIssuers μέσω της ίδιας μεταφοράς, δοκιμάζοντας θωράκιση PEM και περιορίζοντας την ουρά με MaxFetch

Τι είναι το seed value υπογραφής, και γιατί αποτυγχάνει σιωπηλά;

Ένα seed value είναι ένας περιορισμός που επισυνάπτει ο συγγραφέας του εγγράφου σε ένα πεδίο υπογραφής για να πει στον υπογράφοντα τι είδους υπογραφή είναι αποδεκτή: ποιο SubFilter, ποιος αλγόριθμος περίληψης, ποιες αιτίες, ποια ελάχιστη έκδοση PDF, αν οι πληροφορίες ανάκλησης πρέπει να ενσωματώνονται. Ζει σε ένα λεξικό /SV στο πεδίο και ορίζεται στο ISO 32000-1 §12.7.5.5. Το HotPDF το γράφει με την AttachPAdESSeedValue και το ελέγχει με την CheckLoadedSignatureSeedValue, που επιστρέφει True όταν το πεδίο δεν έχει περιορισμούς ή όταν κάθε παρών περιορισμός περνά, και σε False ονομάζει τον πρώτο αποτυχημένο περιορισμό μέσω παραμέτρου εξόδου που μπορείτε να βάλετε κατευθείαν σε μήνυμα σφάλματος

Ο μηχανισμός που κάνει τα seed values εύκολο να πάουν στραβά είναι η εγγραφή σημαιών /Ff που περιγράφεται στο §12.7.5.5.3. Ένα αναμένο bit σηματοδοτεί τον περιορισμό του ως απαιτούμενο: μια ασυμφωνία είναι σφάλμα και ο υπογράφων πρέπει να αρνηθεί. Ένα σβηστό bit σηματοδοτεί τον ίδιο περιορισμό ως προτίμηση: η τιμή φιλτράρει τι πρέπει να προσφέρει το UI και τίποτα παραπάνω. Δύο παγίδες προκύπτουν από εκεί. Πρώτον, το /Ff ζει μέσα στο λεξικό /SV, όχι στην annotation widget, οπότε κώδικας που διαβάζει το /Ff επιπέδου πεδίου παίρνει κενή απάντηση για πάντα και συμπεραίνει ότι τίποτα δεν επιβάλλεται. Δεύτερον, οι αναθέσεις bit δεν είναι μια απλή σειρά ένα, δύο, τέσσερα, οκτώ· στο HotPDF ο writer εκπέμπει 2 για SubFilter, 4 για MinVersion, 32 για AddRevInfo και 64 για DigestMethod. Ένας reader που υποθέτει διαδοχικά bits αποκωδικοποιεί κάθε περιορισμό ως προαιρετικό και περνά κάθε test εκτός από αυτό που μετράει

Πίνακας bit σημαιών seed value για υπογραφή PAdES στο HotPDF που δείχνει bits 2, 4, 32 και 64 του Ff και χειρισμό απαιτούμενων έναντι προτιμώμενων περιορισμών
Η εγγραφή /Ff ζει μέσα στο /SV, και κάθε θέση bit αποφασίζει αν μια ασυμφωνία είναι σκληρή άρνηση ή προτίμηση UI
var
  Violation: AnsiString;
begin
  // Ρωτήστε το πεδίο αν το προφίλ που πρόκειται να υπογράψουμε επιτρέπεται
  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));
  // Περιορισμός ικανοποιημένος: προχωρήστε στο πέρασμα υπογραφής
end;

Το test που αποκάλυψε το αρχικό σφάλμα αποκωδικοποίησης δεν ήταν θετικό test. Ήταν ο ισχυρισμός ότι μια επιβαλλόμενη ασυμφωνία πρέπει να απορρίπτεται, και είναι το μόνο είδος test που μπορεί να πιάσει αυτή την κατηγορία ελαττωμάτων: ένας decoder που διαβάζει λάθος λεξικό ή λάθος θέσεις bit παράγει «κανένας περιορισμός δεν παραβιάστηκε» για κάθε είσοδο, που μοιάζει ακριβώς με σωστή συμπεριφορά μέχρι να παραβιάσετε εσκεμμένα έναν

Πού κάθεται αυτό στη σκάλα LTV

Τέσσερα σκαλοπάτια, και το καθένα χρειάζεται το από κάτω του. Το B-B είναι η γυμνή υπογραφή. Το B-T προσθέτει αξιόπιστη χρονική σήμανση, που στερεώνει την ώρα υπογραφής ώστε ένας validator να ξέρει σε ποια στιγμή να αξιολογήσει την ανάκληση. Το B-LT προσθέτει τις αποδείξεις ανάκλησης στο DSS, που είναι αυτό που αυτοματοποιεί η PopulatePAdESLTVEvidence. Το B-LTA προσθέτει χρονικές σημάνσεις εγγράφου που ανανεώνονται πριν εξασθενήσει η προηγούμενη, επεκτείνοντας την ισχύ αόριστα· το HotPDF το εκθέτει ως RenewPAdESLTATimestamp, που προσθέτει νέα χρονική σήμανση ως επαυξητική αναθεώρηση και διατηρεί κάθε προηγούμενη υπογραφή, χρονική σήμανση και εγγραφή DSS ανέγγιχτη

Το μοντέλο επαυξητικής ενημέρωσης είναι ο μόνος σωστός τρόπος να προστεθούν αποδείξεις σε υπογεγραμμένο έγγραφο, γιατί η επανεγγραφή του αρχείου θα έσπαζε τα εύρη bytes που καλύπτουν οι υπάρχουσες υπογραφές. Αν χρειάζεται να συλλογιστείτε τι άλλαξε ανάμεσα σε αναθεωρήσεις, και αν εκείνες οι αλλαγές είναι του είδους που επιτρέπει μια υπογραφή, η ανάλυση εκείνη καλύπτεται ξεχωριστά στην ανάλυση αναθεωρήσεων DocMDP και FieldMDP. Ο ίδιος ο αγωγός υπογραφής, συμπεριλαμβανομένων πηγών πιστοποιητικών και παγίδων σειράς bytes, βρίσκεται στον οδηγό υπογραφής PAdES, και η πλευρά επικύρωσης στη επαλήθευση υπογραφών σε φορτωμένα έγγραφα

Μια πρακτική προειδοποίηση για τη σειρά. Συλλέξτε αποδείξεις το συντομότερο δυνατό μετά την υπογραφή, ιδανικά στην ίδια εργασία. Οι responders που μπορούν να απαντήσουν για ένα πιστοποιητικό είναι online όσο το πιστοποιητικό είναι ισχύον και εξαφανίζονται χρόνια μετά, οπότε ένα έγγραφο που φεύγει από τον αγωγό σας ως B-B μπορεί να μην αναβαθμιστεί ποτέ ξανά. Το HotPDF τρέχει ως εγγενές στοιχείο VCL για Delphi και C++Builder, και ολόκληρο το πέρασμα αποδείξεων είναι εντός διεργασίας εκτός από τη δική σας μεταφορά· τα υποστηριζόμενα προφίλ καταγράφονται στη σελίδα προϊόντος HotPDF Delphi PDF component