addRoot(new SignatureField(new PartialFieldName(new TextString('Demonstration')), value: new IndirectReference($pending))); $form = new AcroForm($fields); // PDF 2.0 requires explicit metrics and a descriptor even for standard fonts. $font = require __DIR__ . '/fixtures/pdf20-courier-font.php'; $resources = new ResourceDictionary(new Font(new DictionaryType(new Entry(new NameType('F1'), new IndirectReference($font))))); $content = new StreamObject(new ContentStreams( new Op\BeginTextObject(), new Op\SetTextFontAndSize(new NameType('F1'), new NumericType(20)), new Op\MoveTextPosition(new NumericType(48), new NumericType(740)), new Op\ShowText(new LiteralString('PDF 2.0: an explicit modern signature')), new Op\SetTextFontAndSize(new NameType('F1'), new NumericType(12)), new Op\MoveTextPosition(new NumericType(0), new NumericType(-48)), new Op\ShowText(new LiteralString('Named curve: P-256. Message digest: SHA3-256.')), new Op\MoveTextPosition(new NumericType(0), new NumericType(-28)), new Op\ShowText(new LiteralString('ISO/TS 32001 and ISO/TS 32002 are declared separately.')), new Op\MoveTextPosition(new NumericType(0), new NumericType(-28)), new Op\ShowText(new LiteralString('The exact ByteRange is signed through CMS signed attributes.')), new Op\MoveTextPosition(new NumericType(0), new NumericType(-40)), new Op\ShowText(new LiteralString('PUBLIC TEST KEY: no trusted production identity is asserted.')), new Op\EndTextObject(), )); $page = new PageObject(new Rectangle(new NumericType(0), new NumericType(0), new NumericType(595), new NumericType(842)), $resources, $content); $catalog = new DocumentCatalog((new PageTreeNode())->addKid($page), new Entry(new NameType('Extensions'), $extensions), new Entry(new NameType('AcroForm'), new IndirectReference($form))); $file = new FileStructure(new FileHeader('2.0'), new FileBody($catalog)); // 3. Preparing fixes the final byte ranges. Signing hashes those exact bytes, // hashes DER signedAttrs with the same digest, verifies the mathematical // result, and fills only the preallocated Contents region. $prepared = (new SignatureWriter())->prepare($file, $pending); $signed = $prepared->sign($backend); $path = $argv[1] ?? __DIR__ . '/pdf20-modern-signature.pdf'; $signed->writeTo($path); echo 'PDF written to ' . $path . PHP_EOL;