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

Μακροπρόθεσμες Υπογραφές PDF στο Delphi: PAdES B-LT και B-LTA

Για να διασφαλιστεί ότι ένα υπογεγραμμένο PDF θα επαληθεύεται χρόνια από τώρα, αφού λήξει το πιστοποιητικό υπογραφής και αλλάξει η CA, το PDFium Component μπορεί να παράγει μακροπρόθεσμες υπογραφές PAdES στα Windows: μια χρονοσήμανση RFC 3161 για αξιόπιστο χρόνο, μια Document Security Store (DSS) που ενσωματώνει το υλικό επικύρωσης, και ένα αρχείο DocTimeStamp πάνω σε ολόκληρο το αρχείο. Αυτές οι τρεις προσθήκες αποτελούν τα επίπεδα αναφοράς PAdES B-T, B-LT και B-LTA, και το PDFium Component τα φτάνει όλα από μία μόνο κλήση υπογραφής. Αυτή είναι μια δυνατότητα μόνο για Windows, η οποία ελέγχεται από το PadesCryptoAvailable

Αυτό το άρθρο είναι το τρίτο μιας σειράς. Το πρώτο, υπογραφή PDF με PAdES B-B χρησιμοποιώντας το PDFium VCL, καλύπτει τη βασική υπογραφή. Το δεύτερο, επιθεώρηση ψηφιακών υπογραφών PDF και επιπέδων PAdES, καλύπτει την ανάγνωση μιας υπογραφής και την αναγνώριση του επιπέδου που έφτασε. Εδώ το θέμα είναι η αρχειοθέτηση: υπογραφές που πρέπει να επιβιώσουν από τη λήξη του πιστοποιητικού και να παραμείνουν επαληθεύσιμες για περίοδο διατήρησης που μετριέται σε χρόνια, και όχι σε εβδομάδες

Γιατί μια έγκυρη υπογραφή PDF σταματά να επαληθεύεται με την πάροδο του χρόνου;

Μια βασική υπογραφή απαντά σε μία μόνο ερώτηση: αν αλλοιώθηκαν αυτά τα bytes μετά την υπογραφή. Δεν αποδεικνύει, από μόνη της, πότε έγινε η υπογραφή, και αυτό το κενό είναι που την καθιστά άκυρη αργότερα. Η δομή CMS φέρει ένα χαρακτηριστικό signing-time, αλλά ο υπογράφων γράφει αυτήν την τιμή από το δικό του ρολόι, οπότε ένας επικυρωτής δεν έχει λόγο να την εμπιστευτεί. Όταν το πιστοποιητικό υπογραφής λήξει αργότερα ή η CA το ανακαλέσει, ένας αυστηρός επικυρωτής δεν μπορεί πλέον να διακρίνει μια υπογραφή που έγινε ενώ το πιστοποιητικό ήταν έγκυρο από μια πλαστογραφημένη υπογραφή αφού αυτό είχε λήξει. Η υπογραφή ήταν εντάξει την ημέρα που έγινε και καθίσταται μη επαληθεύσιμη χωρίς δική της υπαιτιότητα

Η μακροπρόθεσμη αρχειοθέτηση το διορθώνει αυτό με δύο κινήσεις. Πρώτον, ένας τρίτος, μια Αρχή Χρονοσήμανσης (Time Stamping Authority - TSA), βεβαιώνει το χρόνο κρυπτογραφικά, ώστε να μην εξαρτάται πλέον από την ειλικρίνεια του υπογράφοντος. Δεύτερον, κάθε πιστοποιητικό, απόκριση ανάκλησης και CRL που απαιτείται για τη δημιουργία και τον έλεγχο της αλυσίδας εμπιστοσύνης ενσωματώνεται μέσα στο ίδιο το PDF, οπότε η επικύρωση δεν εξαρτάται από διακομιστές που μπορεί να έχουν κλείσει μέχρι να ψάξει κανείς. Το PAdES, τυποποιημένο ως ETSI EN 319 142-1, ταξινομεί αυτά ως επίπεδα αναφοράς (baseline levels), και το PDFium Component γράφει τις δομές που απαιτεί κάθε επίπεδο

Tι είναι μια υπογραφή PDF LTV ή με χρονοσήμανση αρχείου;

Το PAdES ορίζει τέσσερα επίπεδα αναφοράς (baseline levels) που βασίζονται το ένα στο άλλο, και το PDFium Component τα εκθέτει μέσω του απαριθμητή TPadesLevel (plB_B, plB_T, plB_LT, plB_LTA). Το B-B είναι η απλή υπογραφή. Το B-T προσθέτει μια αξιόπιστη χρονοσήμανση πάνω από την τιμή της υπογραφής. Το B-LT (long-term) προσθέτει το ενσωματωμένο υλικό επικύρωσης, η ιδιότητα που οι περισσότεροι εννοούν με το "LTV". Το B-LTA (long-term με χρονοσήμανση αρχείου) τυλίγει τα πάντα σε μία ακόμη χρονοσήμανση που καλύπτει ολόκληρο το αρχείο, οπότε το ίδιο το ενσωματωμένο υλικό είναι αποδεδειγμένα άθικτο από τη στιγμή της αρχειοθέτησης

Η πρακτική ανάγνωση είναι μια σκάλα. Το B-T αποδεικνύει το πότε. Το B-LT αποδεικνύει με τι μπορεί ακόμα να ελεγχθεί η υπογραφή. Το B-LTA αποδεικνύει ότι ολόκληρο το πακέτο δεν έχει αλλοιωθεί από τότε που σφραγίστηκε, και είναι το επίπεδο που ανανεώνετε, προσθέτοντας ένα νέο DocTimeStamp προτού λήξει το προηγούμενο, για να επεκτείνετε το αρχείο επ' αόριστον. Για ένα συμβόλαιο ή ένα αρχείο συμμόρφωσης με μακρά υποχρέωση διατήρησης, το B-LTA είναι ο στόχος. Το B-LT είναι το ρεαλιστικό κατώτατο όριο

Προσθήκη αξιόπιστου χρόνου: PAdES B-T με RFC 3161

Το PDFium Component μετατρέπει μια υπογραφή B-B σε B-T ορίζοντας δύο πεδία στο TPadesSignOptions: αυξήστε το Level σε plB_T και παρέχετε ένα TsaUrl. Όταν και τα δύο είναι παρόντα, η ροή εργασίας υπογραφής κατακερματίζει (hashes) τα ακατέργαστα ψηφία της υπογραφής με SHA-256, πακετάρει αυτήν τη σύνοψη ως RFC 3161 messageImprint, στέλνει με POST το αίτημα στην TSA μέσω WinHttp, και ενσωματώνει το επιστρεφόμενο token ως το μη υπογεγραμμένο χαρακτηριστικό signature-time-stamp (OID 1.2.840.113549.1.9.16.2.14) στο unsignedAttrs [1] του SignerInfo, σύμφωνα με το EN 319 142-1 §6.3. Η χρονοσήμανση καλύπτει ειδικά την τιμή της υπογραφής, πράγμα που συνδέει τον αξιόπιστο χρόνο με τη συγκεκριμένη υπογραφή

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 είναι μόνο για Windows');
    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 αφήνεται στο 0: το στοιχείο παράγει μια μοναδική τιμή anti-replay

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

Το CertificateThumbprint είναι το hash SHA-1, σε δεκαεξαδικό, ενός πιστοποιητικού στο αποθετήριο "MY" του Τρέχοντος Χρήστη, του οποίου το ιδιωτικό κλειδί μπορείτε να χρησιμοποιήσετε. Το πεδίο Nonce είναι η τιμή anti-replay του RFC 3161. Αφήστε το μηδέν και το στοιχείο παράγει μια μοναδική τιμή ανά αίτημα από ένα SHA-256 fold ενός μετρητή, του ρολογιού, του αριθμού ticks και του αναγνωριστικού διεργασίας (process id), ώστε δύο αιτήματα που εκδίδονται στο ίδιο χιλιοστό του δευτερολέπτου να μην συγκρούονται. Περάστε τη δική σας τιμή μόνο όταν έχετε έναν κρυπτογραφικό RNG που προτιμάτε να εμπιστευτείτε. Μια ειλικρινής προειδοποίηση: το B-T χρειάζεται μια προσβάσιμη TSA, οπότε η υπογραφή κάνει τώρα μια κλήση δικτύου και κληρονομεί τη διαθεσιμότητα και την καθυστέρηση (latency) της TSA

Ενσωμάτωση υλικού επικύρωσης: B-LT και B-LTA σε μία κλήση

Το βήμα προς τη μακροπρόθεσμη επικύρωση είναι μια απλή αλλαγή: ορίστε το Level σε plB_LTA και κρατήστε το TsaUrl. Το PDFium Component εκτελεί στη συνέχεια ολόκληρη τη σκάλα μέσα σε μία μόνο κλήση SignPades. Υπογράφει το B-B, βάζει χρονοσήμανση για το B-T, εισάγει το Document Security Store για το B-LT, και προσαρτά τη χρονοσήμανση αρχείου για το B-LTA, καθένα ως δική του σταδιακή ενημέρωση, ώστε τα προηγούμενα bytes να παραμένουν άθικτα byte προς byte

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;   // οδηγεί B-B -> B-T -> B-LT -> B-LTA
    Options.TsaUrl   := 'http://timestamp.example-tsa.com/tsr';
    Options.Location := 'Head Office';

    // Μία κλήση γράφει τη χρονοσήμανση, το DSS και το αρχείο DocTimeStamp.
    Pdf.SignPades('contract-lta.pdf', Options);
  finally
    Pdf.Free;
  end;
end;

Για το στάδιο B-LT, το PDFium Component χτίζει την αλυσίδα πιστοποιητικών με το CertGetCertificateChain και γράφει ένα λεξικό /DSS που μεταφέρει το πιστοποιητικό του υπογράφοντος συν κάθε ενδιάμεση CA σε έναν πίνακα /Certs (με παράλληλους πίνακες /OCSPs και /CRLs), μαζί με έναν δείκτη Level 1 /Extensions /ESIC, ακριβώς όπως ορίζει το EN 319 142-1 §5.4.2. Η αυτο-υπογεγραμμένη ρίζα παραλείπεται σκόπιμα, καθώς το RFC 5652 §10.2.3 το επιτρέπει και η ρίζα είναι ήδη ένα trust anchor που κατέχει ο επικυρωτής. Το αποτέλεσμα είναι μια υπογραφή που ο αναγνώστης μπορεί να επαληθεύσει μόνο με το αρχείο στο χέρι

Για το B-LTA, το στοιχείο προσαρτά ένα Document Time-stamp: ένα λεξικό υπογραφής με /SubFilter /ETSI.RFC3161 του οποίου το /ByteRange καλύπτει ολόκληρο το αρχείο, με το /Contents να κρατά ένα token RFC 3161 πάνω από αυτό το εύρος, και προάγει τον δείκτη ESIC στο Level 2. Αυτό είναι το βήμα αρχειοθέτησης της §5.4.3 και του TS 119 142-3. Επειδή το DocTimeStamp καλύπτει το DSS καθώς και την υπογραφή, αποδεικνύει ότι το ενσωματωμένο υλικό επικύρωσης ήταν παρόν και αναλλοίωτο κατά το χρόνο αρχειοθέτησης, το οποίο είναι ακριβώς αυτό που πρέπει να μπορεί να δείξει μια πολιτική μακράς διατήρησης

Επαύξηση υπογραφής που υπάρχει ήδη

Μερικές φορές η υπογραφή βρίσκεται ήδη στο έγγραφο και χρειάζεται μόνο να προσθέσετε ή να ανανεώσετε το validation store, για παράδειγμα για να αναβαθμίσετε μια υπογραφή B-B τρίτου σε B-LT για το αρχείο σας. Το PDFium Component εκθέτει τον DSS εισαγωγέα απευθείας μέσω του SaveAsPadesDss, το οποίο προσαρτά τις δομές /DSS και /Extensions ως σταδιακή ενημέρωση χωρίς να αγγίζει τα υπάρχοντα bytes της υπογραφής

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 για B-LT, 2 για B-LTA
    Cert.DerBytes := LoadSignerCertDer;       // το κωδικοποιημένο κατά DER πιστοποιητικό σας
    SetLength(DssOpts.Certs, 1);
    DssOpts.Certs[0] := Cert;

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

Παρέχετε τα κωδικοποιημένα κατά DER πιστοποιητικά, και προαιρετικά τις αποκρίσεις OCSP και τα CRLs, που θα χρειαστεί ο επικυρωτής. Ορίστε το EsicExtensionLevel σε 1 για μια αποθήκη B-LT ή 2 όταν θα ακολουθήσει DocTimeStamp. Αφήστε το IncludeVri στην προεπιλογή του False: το EN 319 142-1 §5.4.2.3 αντιμετωπίζει το λεξικό /VRI ανά υπογραφή ως προαιρετικό και συμβουλεύει να μην χρησιμοποιείται εκτός εάν το απαιτεί κάποιο συγκεκριμένο πρόγραμμα ανάγνωσης που στοχεύετε

Κόστη και όρια που αξίζει να προγραμματίσετε

Tρία ειλικρινή όρια καθορίζουν πού ταιριάζουν αυτά τα επίπεδα. Πρώτον, το κρυπτογραφικό backend είναι μόνο για Windows: η υπογραφή και η χρονοσήμανση γίνονται μέσω των αποθηκών CNG και WinHttp της πλατφόρμας, οπότε το PadesCryptoAvailable επιστρέφει False αλλού και το SignPades εγείρει σφάλμα. Η επιθεώρηση από την πλευρά της ανάγνωσης που καλύπτεται στο συνοδευτικό άρθρο παραμένει cross-platform. Μόλις η συγγραφή υπογραφών δεσμεύεται στα Windows. Δεύτερον, τα B-T και B-LTA εξαρτώνται από μια Αρχή Χρονοσήμανσης (TSA), πράγμα που σημαίνει μια κλήση δικτύου κατά το χρόνο υπογραφής και μια εξωτερική υπηρεσία της οποίας η διαθεσιμότητα και τα όρια ρυθμού γίνονται μέρος της διαδρομής υπογραφής σας

Τρίτον, κάθε επίπεδο κοστίζει σε αποθηκευτικό χώρο. Κάθε στάδιο προσαρτά μια σταδιακή ενημέρωση αντί να ξαναγράφει το αρχείο, το DSS ενσωματώνει μια πλήρη αλυσίδα πιστοποιητικών, και το αρχείο DocTimeStamp κρατά χώρο για το token του, οπότε ένα αρχείο B-LTA είναι αισθητά μεγαλύτερο από το πρωτότυπο B-B. Αυτή είναι η σκόπιμη ανταλλαγή: ξοδεύετε bytes τώρα για να αγοράσετε επαληθευσιμότητα αργότερα. Για τα περισσότερα αρχεία συμβολαίων και συμμόρφωσης είναι η σωστή ανταλλαγή, αλλά αξίζει να το μετρήσετε στα δικά σας έγγραφα αντί να το υποθέσετε. Όταν πρέπει να επιβεβαιώσετε ότι ένα έτοιμο αρχείο έφτασε πράγματι στο επίπεδο που θέλατε, επαληθεύστε το με τις τεχνικές στο επιθεώρηση ψηφιακών υπογραφών PDF και επιπέδων PAdES, και αν θωρακίζετε μια ροή εγγράφων γενικότερα, οι σημειώσεις σχετικά με τον έλεγχο κινδύνων ασφαλείας PDF καλύπτουν τους σχετικούς ελέγχους

Οι δυνατότητες υπογραφής PAdES, DSS και χρονοσήμανσης αρχείου που εμφανίζονται εδώ αποτελούν μέρος του PDFium Component για Delphi και C++Builder, του οποίου η σελίδα προϊόντος φέρει την πλήρη αναφορά υπογραφής και τις απαιτήσεις πλατφόρμας