Techninis straipsnis

Ilgalaikiai PDF parašai Delphi aplinkoje: PAdES B-LT ir B-LTA

Kad pasirašytas PDF failas būtų sėkmingai tikrinamas po daugelio metų, pasibaigus pasirašymo sertifikato galiojimui bei pasikeitus sertifikavimo įstaigai, PDFium komponentas gali sukurti ilgalaikius PAdES parašus „Windows“ sistemoje: RFC 3161 laiko žymą patikimam laikui nustatyti, dokumento saugumo saugyklą, įterpiančią patvirtinimo duomenis, bei archyvo DocTimeStamp virš viso failo. Šie trys priedai sudaro PAdES B-T, B-LT bei B-LTA bazinius lygius, o PDFium komponentas pasiekia juos visus vienu pasirašymo iškvietimu. Tai yra tik „Windows“ aplinkoje prieinama galimybė, ribojama PadesCryptoAvailable vėliavėle

Šis straipsnis yra trečiasis serijoje. Pirmasis, PDF pasirašymas su PAdES B-B naudojant PDFium VCL, aprašo bazinį parašą; antrasis, PDF skaitmeninių parašų bei PAdES lygių tikrinimas, aprašo parašo nuskaitymą bei jo lygio nustatymą. Šiame straipsnyje dėmesys skiriamas archyvui: parašams, kurie turi išlikti patikrinami pasibaigus sertifikato galiojimui ilgą saugojimo laikotarpį, matuojamą metais, o ne savaitėmis

Kodėl galiojantis PDF parašas laikui bėgant nustoja būti patikrinamas?

Bazinis parašas atsako tik į vieną klausimą: ar šie baitai buvo pakeisti po pasirašymo. Jis pats savaime neįrodo, kada įvyko pasirašymas, ir šis trūkumas vėliau viską sugadina. CMS struktūroje yra pasirašymo laiko atributas, tačiau pasirašantysis šią reikšmę įrašo iš savo laikrodžio, todėl tikrintuvas neturi pagrindo ja pasitikėti. Kai pasirašymo sertifikatas vėliau nustoja galioti arba CA jį atšaukia, griežtas tikrintuvas nebegali atskirti parašo, sukurto sertifikato galiojimo metu, nuo suklastoto po jo galiojimo pabaigos. Parašas buvo geras jo sukūrimo dieną, tačiau tampa nepatikrinamas ne dėl savo kaltės

Ilgalaikis archyvavimas tai išsprendžia dviem žingsniais. Pirma, patikima trečioji šalis — laiko žymėjimo institucija — kriptografiškai patvirtina laiką, todėl jis nebepriklauso nuo pasirašiusiojo sąžiningumo. Antra, kiekvienas sertifikatas, atšaukimo atsakymas bei CRL, reikalingi pasitikėjimo grandinei sukurti bei patikrinti, yra įterpiami pačiame PDF faile, todėl patikrinimas nepriklauso nuo serverių, kurie gali būti išjungti iki tol, kol kas nors tikrins dokumentą. PAdES standartas ETSI EN 319 142-1 išdėsto juos kaip bazinius lygius, o PDFium komponentas įrašo kiekvienam lygiui reikalingas struktūras

Kas yra LTV arba archyvo laiko žymos PDF parašas?

PAdES apibrėžia keturis bazinius lygius, kurie papildo vienas kitą, o PDFium komponentas pateikia juos per TPadesLevel sąrašą (plB_B, plB_T, plB_LT, plB_LTA). B-B yra paprastas parašas. B-T prideda patikimą laiko žymą virš parašo reikšmės. B-LT (ilgalaikis) prideda įterptus patvirtinimo duomenis — savybę, kurią daugelis vadina „LTV“. B-LTA (ilgalaikis su archyvo laiko žyma) apgaubia viską dar viena laiko žyma, kuri apima visą failą, todėl patyts įterptieji duomenys yra proviškai nepažeisti nuo pat archyvavimo momento

Šie laiptai yra praktinė išraiška. B-T įrodo kada. B-LT įrodo su kuo parašas vis dar gali būti patikrintas. B-LTA įrodo, kad visas paketas nebuvo modifikuotas nuo užsandarinimo momento; tai yra lygis, kurį atnaujinate pridėdami naują DocTimeStamp prieš pasibaigiant ankstesnio galiojimui, kad neribotam laikui pratęstumėte archyvą. Sutartims ar atitikties įrašams su ilga saugojimo prievole tikslas yra B-LTA; B-LT yra pragmatiškas minimumas

Patikimo laiko pridėjimas: PAdES B-T su RFC 3161

PDFium komponentas paverčia B-B parašą į B-T nustatydamas du laukus TPadesSignOptions struktūroje: pakeičia Level į plB_T bei nurodo TsaUrl. Kai abu yra nustatyti, pasirašymo procesas sukuria neapdorotų parašo baitų maišą su SHA-256, suformuoja jį kaip RFC 3161 messageImprint užklausą, išsiunčia ją į TSA per WinHttp bei įterpia gautą žetoną kaip signature-time-stamp nepasirašytą atributą (OID 1.2.840.113549.1.9.16.2.14) SignerInfo unsignedAttrs [1] lauke pagal EN 319 142-1 standarto 6.3 punktą. Laiko žyma apima būtent parašo reikšmę, kas ir susieja patikimą laiką su tuo konkrečiu parašu

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 left at 0: the component derives a unique anti-replay value.

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

CertificateThumbprint yra sertifikato, esančio Current User „MY“ saugykloje, kurio privatųjį raktą galite naudoti, SHA-1 maiša šešioliktainiu formatu. Nonce laukas yra RFC 3161 apsaugos nuo pakartojimo reikšmė; palikite ją nuliu, ir komponentas sugeneruos unikalią reikšmę kiekvienai užklausai iš skaitiklio, laikrodžio, procesoriaus taktų skaičiaus bei proceso ID SHA-256 maišos, kad dvi užklausos, pateiktos tą pačią milisekundę, nesusidurtų. Savo reikšmę perduokite tik tada, kai turite kriptografinį atsitiktinių skaičių generatorių, kuriuo norite pasitikėti. Verta pastebėti vieną dalyką: B-T reikalauja pasiekiamos TSA, todėl pasirašymas dabar atlieka tinklo iškvietimą bei priklauso nuo TSA pasiekiamumo bei vėlavimo

Patvirtinimo duomenų įterpimas: B-LT bei B-LTA vienu iškvietimu

Perėjimas prie ilgalaikio patvirtinimo reikalauja tik vieno pakeitimo: nustatykite Level į plB_LTA bei palikite TsaUrl. Tada PDFium komponentas atlieka visus žingsnius vienu SignPades iškvietimu. Jis pasirašo B-B lygį, uždeda laiko žymą B-T lygiui, įterpia dokumento saugumo saugyklą B-LT lygiui bei prideda archyvo laiko žymą B-LTA lygiui — kiekvieną žingsnį kaip atskirą prieaugio atnaujinimą, todėl ankstesni baitai lieka nepaliesti

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

    // One call writes the timestamp, the DSS and the archive DocTimeStamp.
    Pdf.SignPades('contract-lta.pdf', Options);
  finally
    Pdf.Free;
  end;
end;

B-LT etapui PDFium komponentas sukuria sertifikatų grandinę naudodama CertGetCertificateChain bei įrašo /DSS žodyną, kuriame yra pasirašiusiojo sertifikatas bei kiekvienas tarpinis CA /Certs masyve (su lygiagrečiais /OCSPs bei /CRLs masyvais), kartu su /Extensions /ESIC 1 lygio žymekliu, būtent taip, kaip reikalauja EN 319 142-1 standarto 5.4.2 punktas. Pačių pasirašytas šakninis sertifikatas sąmoningai praleidžiamas, nes RFC 5652 standarto 10.2.3 punktas tai leidžia, o šaknis jau yra tikrintuvo turimas pasitikėjimo inkaras. Rezultatas yra parašas, kurį skaitytuvas gali patikrinti turėdamas tik patį failą

B-LTA lygio atveju komponentas prideda dokumento laiko žymą: parašo žodyną su /SubFilter /ETSI.RFC3161, kurio /ByteRange apima visą failą, o jo /Contents saugo RFC 3161 žetoną virš to diapazono, bei perkelia ESIC žymeklį į 2 lygį. Tai yra 5.4.3 punkto bei TS 119 142-3 standartų archyvavimo žingsnis. Kadangi DocTimeStamp apima tiek DSS, tiek parašą, ji įrodo, kad įterptieji patvirtinimo duomenys buvo vietoje bei nepakeisti archyvavimo metu; būtent tai turi įrodyti ilgalaikė saugojimo politika

Esamo parašo papildymas

Kartais parašas jau yra ant dokumento ir jums tereikia pridėti arba atnaujinti patvirtinimo saugyklą, pavyzdžiui, kad trečiosios šalies B-B parašą paverstumėte B-LT savo archyvui. PDFium komponentas atveria DSS įterpiklį tiesiogiai per SaveAsPadesDss, kuris prideda /DSS bei /Extensions struktūras kaip prieaugio atnaujinimą, neliesdamas esamų parašo baitų

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 for B-LT, 2 for B-LTA
    Cert.DerBytes := LoadSignerCertDer;       // your DER-encoded certificate
    SetLength(DssOpts.Certs, 1);
    DssOpts.Certs[0] := Cert;

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

Pateikiate DER formatu užkoduotus sertifikatus bei pasirinktinai OCSP atsakymus bei CRL, kurių reikės tikrintuvui. Nustatykite EsicExtensionLevel į 1, jei norite B-LT saugyklos, arba į 2, kai po jos seks DocTimeStamp. Palikite IncludeVri numatytojoje reikšmėje False: EN 319 142-1 standarto 5.4.2.3 punktas laiko kiekvieno parašo /VRI žodyną neprivalomu bei pataria jo nenaudoti, nebent to reikalauja konkretus skaitytuvas, į kurį orientuojatės

Sąnaudos ir ribos, kurias verta suplanuoti

Trys realios ribos nustato šių lygių taikymą. Pirma, kriptografinė dalis yra skirta tik „Windows“ sistemai: pasirašymas bei laiko žymėjimas eina per platformos CNG bei WinHttp saugyklas, zodžiu, kitose sistemose PadesCryptoAvailable grąžina False bei SignPades iškelia klaidą. Skaitymo tikrinimas, aprašytas susijusiame straipsnyje, išlieka kelių platformų; tik parašų rašymas yra susietas su „Windows“. Antra, B-T bei B-LTA priklauso nuo laiko žymėjimo institucijos, o tai reiškia tinklo iškvietimą pasirašymo metu bei išorinės paslaugos prieinamumą ir limitus, kurie tampa jūsų pasirašymo kelio dalimi

Trečia, kiekvienas lygis kainuoja vietos. Kiekvienas etapas prideda prieaugio atnaujinimą, užuot perrašęs failą, DSS įterpia visą sertifikatų grandinę, o archyvo DocTimeStamp rezervuoja vietą savo žetonui, todėl B-LTA failas yra pastebimai didesnis už B-B originalą. Tai yra sąmoningas kompromisas: išleidžiate baitus dabar, kad nusipirktumėte patikrinamumą vėliau. Daugumai sutarčių bei atitikties archyvų tai yra teisingas kompromisas, tačiau verta tai išmatuoti savo dokumentuose, užuot spėliojus. Kai reikia patvirtinti, ar baigtas failas pasiekė jūsų norimą lygį, patikrinkite jį metodais, aprašytais straipsnyje PDF skaitmeninių parašų bei PAdES lygių tikrinimas, o jei norite plačiau apsaugoti dokumentų srautą, straipsnis apie PDF saugumo rizikų auditą aprašo susijusias patikras

Čia parodytos PAdES pasirašymo, DSS bei archyvo laiko žymos funkcijos platinamos kaip PDFium komponento, skirto Delphi bei C++Builder, dalis, kurio produkto puslapyje pateikiamas visas pasirašymo žinynas bei platformos reikalavimai