Alles in dit hoofdstuk gebeurt voor de eerste handtekening. Daarna is elke wijziging aan de AcroForm of de pagina-inhoud een wijziging van een ondertekend document, en Adobe zegt dat ook. Uitgangspunt is wat een formulierinvuller oplevert: een ingevuld formulier met tekstvelden en /NeedAppearances true. Drie van de echte bestanden die wij hebben bekeken gingen mis doordat een van deze vijf stappen was overgeslagen.
Dit is onafhankelijk van taal of bibliotheek. Elke PAdES-implementatie moet dezelfde bytes op dezelfde plek zetten; hoe je ze daar krijgt is aan jou.
0.1 Het formulier afronden
In de PDF Vul de velden en sla het formulier daarna plat, of maak op zijn minst elk veld read-only (/Ff bit 1). Velden die open blijven onder een handtekening blijven daarna wijzigbaar als "form filling", en dat breekt de handtekening niet: wat een lezer ziet is dan niet meer per se wat er is ondertekend.
Platmaken verwijdert de velden en tekent hun appearance streams in de pagina-inhoud. Het is de simpelste fix en neemt de hele klasse problemen weg, inclusief 0.2. Kies alleen read-only als een systeem verderop de veldwaarden uit de AcroForm moet kunnen lezen.
0.2 /NeedAppearances verwijderen
In de PDF Haal de sleutel uit de AcroForm-dictionary of zet hem op false. Staat de vlag op true, dan bouwt Adobe Reader bij het openen de weergave van elk veld opnieuw op en negeert daarbij ondertekende /Sig-velden: de handtekening is onzichtbaar in Acrobat, terwijl validators en andere viewers hem gewoon tonen (bekend als PDFBOX-3738). De ingevulde tekstvelden hebben na het invullen al hun eigen /AP /N, dus visueel verlies je niets.
Dit is de enige fix die je achteraf niet meer kunt toepassen zonder dat Acrobat het document als gewijzigd na ondertekening markeert.
0.3 Het handtekeningveld aanmaken
In de PDF Een veld met /FT /Sig, zijn widget als /Annot op een pagina en opgenomen in /AcroForm /Fields, en /SigFlags 3 op de AcroForm (handtekeningen bestaan, alleen aanvullen). Voor een onzichtbare handtekening gebruik je /Rect [0 0 0 0]; voor een zichtbare geef je de widget nu een appearance stream, want die valt binnen de ondertekende byte range.
Voor meerdere ondertekenaars maak je nu een veld per ondertekenaar aan, of laat je elke ondertekenronde zijn eigen veld toevoegen; beide werken. Maak je ze vooraf aan, lees dan 0.4 over de lock.
0.4 De velden vergrendelen (FieldMDP)
In de PDF Zet een lock op het eerste handtekeningveld. Bij het ondertekenen wordt die lock een FieldMDP-transform in de /Reference van de signature dictionary: na deze handtekening zijn de bestaande formuliervelden bevroren. Nieuwe handtekeningvelden, DSS-updates en documenttijdstempels blijven toegestaan, en dat is precies wat een uitbreiding naar B-LT en B-LTA later toevoegt.
/Lock << /Type /SigFieldLock /Action /All >>
Heb je in 0.3 lege handtekeningvelden voor andere ondertekenaars aangemaakt, gebruik dan /Action /Include /Fields [...] met alleen de formuliervelden; /All zou die lege handtekeningvelden ook op slot zetten. Gebruik geen DocMDP-certificering met /P 1: die verbiedt ook de LT- en LTA-updates. Kan je bibliotheek geen lock zetten, dan is platmaken in 0.1 het alternatief.
0.5 De signature dictionary klaarzetten
In de PDF /Filter /Adobe.PPKLite, /SubFilter /ETSI.CAdES.detached, /M met de geclaimde ondertekentijd, /Contents als hex-string van vaste lengte, en een /ByteRange die na het wegschrijven wordt ingevuld. Reserveer ruim: het certificaat, zijn keten en bij B-T het tijdstempeltoken komen alle in diezelfde CMS terecht, dus 8 tot 10 kB is de echte behoefte en 32768 is een veilige, gangbare keuze. Te krap is niet te herstellen zonder opnieuw te ondertekenen. B-LT en B-LTA laten dit veld niet groeien; die voegen hun eigen revisies toe, en elke documenttijdstempel brengt zijn eigen /Contents mee.
Wat dit openhoudt
Welk niveau je later ook wilt, de voorbereiding moet drie dingen mogelijk houden:
- Alleen aanvullen. Elk niveau boven B-B is een incrementele update. Nooit tussendoor "opslaan als" of het bestand herschrijven.
- Geen DocMDP
/P 1. Een documenttijdstempel is een nieuw veld dat aan/AcroForm /Fieldsen aan de/Annotsvan een pagina wordt toegevoegd. Een FieldMDP-lock op de formuliervelden is geen belemmering: die bevriest bestaande velden, niet het toevoegen van nieuwe. - Ruimte. De gereserveerde
/Contentsuit 0.5, en geen aannames over waar het bestand eindigt.
Ga daarna verder met de flow: het voorbereide bestand is de invoer van stap 1.