Odločiti, da je PDF podpis kvalificiran pod eIDAS, pomeni odgovoriti na vprašanje, ki nima ničesar s kriptografijo: je bil certifikat izdan s strani storitve zaupanja, ki jo je država članica navedla kot kvalificirano, v trenutku, ko je bil podpis narejen. Odgovor živi v zaupanem seznamu, dokumentu XML, objavljenem na ozemlje, in celotna vrednost tega dokumenta je odvisna od njegove avtentičnosti. Torej komponenta PDFium odkloni pogledati znotraj ene, dokler kdo ni zanjo jamil. TPdfEuropeanTrustedList.ParseAuthenticated izroči popolne surove bajte klicatelju-preskrbljenemu IPdfTrustedListAuthenticator, preden razčleni eno samo storitev, in ustvari posnetek samo, če ta overitelj izrecno gre
To razporeditev je zasnova. Vse ostalo v tej funkciji sledi iz nje, vključno z deli, ki izgledajo neprijetno
Razčlenjeno ni zaupano
Zaupani seznam, ki se razčleni čisto, vam pove, da je XML dobro oblikovan. Ne pove vam ničesar o tem, kdo ga je napisal. Ker je seznam tisto, na čemer počiva vaša celotna odločitev kvalificiranega stanja, bi sprejetje enega, ker se je razčlenil, naredilo odločitev nesmiselno: napadalec, ki lahko zamenja seznam, lahko izjavi svojo lastno certifikacijsko avtoriteto kvalificirano
Isto utemeljevanje velja za predpomnjenje in to je past, vredna poimenovanja. Predpomnilniški posnetek shrani izvirni XML skupaj z zgostitvijo SHA-256 in bi bilo enostavno obravnavati ujemajočo zgostitev ob nalaganju kot dokaz, da je seznam pristen. Ni. Zgostitev, izračunana s strani istega procesa, ki je shranil datoteko, brez vpletenega ključa, preveri samo, da bajti niso spremenjeni od takrat, ko ste jih zapisali; če je bil seznam goljufiv, ko je bil predpomnjen, zgostitev potrjuje, da je isti goljufiv seznam. Torej nalaganje predpomnjenega posnetka teče skozi isti overitelj kot razčlenjevanje svežega. Celovitost in avtentičnost sta različni lastnosti in samo ena od njiju potrebuje ključ
uses
FPdfTrustedList;
type
TListAuthenticator = class(TInterfacedObject, IPdfTrustedListAuthenticator)
public
function Authenticate(const XmlData: TBytes;
out AuthenticationDetails: string): Boolean;
end;
function TListAuthenticator.Authenticate(const XmlData: TBytes;
out AuthenticationDetails: string): Boolean;
begin
// Vaša politika živi tukaj: preverite ovito podpis XMLDSIG
// proti certifikatu podpisovanja seznamov, ki ste ga pripeli
// izven pasu, in opišite, kaj ste preverili za revizijsko sled
Result := VerifyEnvelopedXmlSignature(XmlData, FPinnedListSigner);
if Result then
AuthenticationDetails := 'XMLDSIG verified against pinned LOTL signer';
end;
var
List: TPdfEuropeanTrustedList;
Cache: TFileStream;
begin
List := TPdfEuropeanTrustedList.ParseAuthenticated(RawXml,
TListAuthenticator.Create, TPdfTrustedListOptions.Default);
// Posnetek obstaja samo, ker je overitelj rekel da
Cache := TFileStream.Create('tl-de.snapshot', fmCreate);
try
List.SaveCache(Cache);
finally
Cache.Free;
end;
end;
Validator ne lasti politike omrežja
Validator PAdES nima opravka z odločanjem, kako doseči seznam zaupanih seznamov, ali gre skozi posrednika, kako pogosto poskusiti znova ali kaj početi, ko je ozemlje nedosegljivo. To so odločitve aplikacije in namestitve in v reguliranih okoljih so pogosto revizirane. Torej posodobitve prispejo skozi IPdfTrustedListSource, ki dobi URI in omejitev bajtov in vrne bajte
Kar komponenta uveljavlja, so invarianti, ki naredijo posodobitev posodobitev in ne zamenjavo. Update zahteva, da je ozemlje nespremenjeno, da številka zaporedja strogo raste in da se čas izdaje ne premika nazaj. Ti trije pregledi premagajo najbolj očitne napade povrnitve: ponavljanje starejšega seznama, ki še vedno navaja storitev, umaknjeno od takrat, ali zamenjavo s seznamom drugega ozemlja, katerega storitev niste nikoli nameravali zaupati
Meje razčlenjevalnika in sploh brez DTD
TPdfTrustedListOptions omeji velikost XML, število žetonov, globino gnezdenja, število storitev, število certifikatov in velikost posameznega certifikata, s razredno funkcijo Default, ki preskrbi uporabne vrednosti. Zaupani seznami so objavljeni dokumenti napovedljive velikosti, zato so meje poceni za nastavitev in ni legitimnega seznama, ki bi jih moral preseči
Ločeno in brezpogojno razčlenjevalnik odkloni deklaracije DTD in entitet. To zapre tako zavrnitev storitve razširitve entitet kot pot razkritja zunanjih entitet v eni odklonitvi in ne stane ničesar, ker zaupani seznami ne uporabljajo entitet. Vsak razčlenjevalnik XML, dosegljiv iz nezaupanega vhoda, bi moral biti nastavljen na ta način; razlika tukaj je, da odklonitev ni nastavljiva, tako da je ne more izklopiti dobro namenjena sprememba možnosti
Kvalificirano stanje je zapisano poleg zaupanja verige in ne spojeno vanj
Stran vrednotenja je namensko ločena. TPadesTrustValidationOptions.QualifiedTrustEvaluator vzame IPdfQualifiedTrustEvaluator, ki ga implementira posnetek zaupanih seznamov. Med validacijo vrednotitelj prejme listni certifikat, verigo in čas validacije, ujema certifikate storitev z natančno primerjavo DER proti podpisniku in verigi, kombinira stanje storitve, identifikator tipa storitve in URI-je kvalifikatorjev ob tistem trenutku in vrne zapis vrednotenja
Rezultat pristane na dveh mestih na vsakem podpisu: QualifiedTrustStatus kot grobo stanje in QualifiedTrust kot polno vrednotenje z ozemljem, imenom ponudnika, imenom storitve, identifikatorjem tipa, stanjem in začetnim časom stanja. Kar ne počne, je spremeniti CertificateTrustStatus. Zaupanje sistemske verige in kvalificirano stanje odgovarjata različnim vprašanjem in poročilo, ki ju skrči, ne more razlikovati »zaupano, ampak ne kvalificirano« od »kvalificirano, ampak veriga ne validira«, oboje pa je resnično in oboje potrebuje različno obravnavo
var
Options: TPadesTrustValidationOptions;
Report: TPadesValidationResult;
I: Integer;
begin
Options := TPadesTrustValidationOptions.Default;
Options.CheckRevocation := True;
Options.QualifiedTrustEvaluator := List; // overjeni posnetek
Options.QualifiedValidationTime := SigningTime; // ne Now
Report := Pdf.ValidatePadesTrust(Options);
for I := 0 to High(Report.Signatures) do
if Report.Signatures[I].QualifiedTrustStatus = pcsValid then
Writeln(Format('signature %d qualified by %s / %s (%s)',
[I, Report.Signatures[I].QualifiedTrust.Territory,
Report.Signatures[I].QualifiedTrust.ProviderName,
Report.Signatures[I].QualifiedTrust.ServiceName]))
else if Report.Signatures[I].QualifiedTrustStatus = pcsIndeterminate then
// Brez ujemajoče storitve ali posnetek ne more odgovarjati za ta čas
Writeln(Format('signature %d: qualified status undetermined', [I]));
end;
Zakaj čas validacije ni zdaj
Ker je kvalifikacija lastnost trenutka. Storitvi zaupanja je lahko podeljeno kvalificirano stanje, kasneje umaknjeno in kasneje še obnovljeno, in vsak od teh prehodov nosi začetni čas v seznamu. Podpis, narejen, medtem ko je bila storitev kvalificirana, ostane kvalificiran potem; podpis, narejen pred podelitvijo, ne postane kvalificiran retroaktivno. Vrednotenje proti trenutnemu času torej da napačen odgovor v obeh smereh
Seznam nosi tisto, kar je potrebno za to: vsak zapis storitve ima začetni čas stanja in zastavico, ki razlikuje zgodovinske vnose od trenutnih, vrednotitelj pa jih kombinira proti času, ki ga preskrbite. V praksi ta čas pride iz zaupanja vrednega časovnega žiga na podpisu in ne iz časa podpisovanja, trdjenega v CMS, kar je razlog, zakaj gradivo dolgoročne validacije šteje celo za vprašanje, ki izgleda kot iskanje politike; stran časovnega žiga in DSS je pokrita v članku o dolgoročnih podpisih
Kaj še vedno morate zgraditi
Trije stvari in nobena ne pripada PDF knjižnici. Overitelj, kar pomeni dejansko preverjanje XMLDSIG proti certifikatu podpisovanja seznamov, ki ste ga pridobili skozi kanal, ki mu zaupate. Politika pridobivanja, kar pomeni kako in kako pogosto osvežujete in kaj počne vaša aplikacija, ko osvežitev odpove. In teritorialni obseg, kar pomeni katere sezname sploh nosite, kar je poslovna odločitev o tem, v katerih državah članicah vaše nasprotne strani podpisujejo
Kar dobite od komponente, je del, ki ga je enostavno dobiti subtilno napačnega: razporeditev overi-pred-razčlenitvijo, omejeno razčlenjevanje XML brez entitet, monotone invarianti posodobitev, ujemanje storitev z natančnim DER, zgodovinsko vrednotenje stanja in rezultat, ki ostane ločen od običajnega zaupanja verige. Če je vaša takojšnja težava bolj osnovna, da validator odkloni podpis, ki ga menite, da je v redu, so običajni vzroki katalogizirani v zakaj validatorji odklanjajo podpise PAdES, površina pregledovanja podpisov pa je opisana v pregledovanju podpisov in ravni PAdES. Zmožnosti komponente so navedene na strani produkta PDFium Delphi component