signerphp / pdf-signer
Open-source PHP library for PDF digital signing with multiple signatures, RFC3161 timestamping, PAdES profiles, and PDF protection
Requires
- php: ^8.2
- ext-curl: *
- ext-fileinfo: *
- ext-openssl: *
- ext-zlib: *
- signerphp/pdf-core: ^0.1.1
Requires (Dev)
- deptrac/deptrac: ^4.6
- infection/infection: ^0.29
- laravel/pint: ^1.20
- pestphp/pest: ^3.0
- roave/security-advisories: dev-latest
- symfony/var-dumper: ^6.4.2
- vimeo/psalm: ^6.15
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-14 18:13:36 UTC
README
PHP library to digitally sign PDFs using A1 certificates (.pfx/.p12) with a simple, developer-friendly API.
PDF parsing and incremental serialization live in the sibling package signerphp/pdf-core. This package owns signing, timestamps, PAdES, LTV, validation and protection. The public API is SignerPHP\PdfSigner\Presentation\Signer.
What problem it solves
If you need backend PDF signing with cryptographic validity, this library provides a direct flow to:
- apply digital signatures to PDF files
- include signer metadata
- add visible signatures (image)
- apply RFC3161 timestamping (TSA)
- sign the same PDF multiple times (incremental flow)
Main features
- PKCS#12 (
.pfx/.p12) digital signature - Fluent builder API (
Signer::signer()) - Invisible signature
- Visible signature with background image (
PNG/JPEG), contain-scaled and centred - Visible signature with drawn signature image on a configurable sub-area of the bbox
- Visible signature with custom PDF content stream (text, graphics) in the n2 layer
- Automatic default visible appearance (built-in fallback)
- Signature metadata (
name,contactInfo,reason,location) - DocMDP certification (levels 1, 2 and 3)
- Brazil policy mode (
br-iti) signing preset - PAdES Baseline-B profile mode (SubFilter
ETSI.CAdES.detached) - PAdES Baseline-T profile mode (PAdES-B + required timestamp)
- PAdES Baseline-LT profile mode (PAdES-T + embedded DSS/Certs)
- PAdES Baseline-LTA profile mode (PAdES-LT + extra archival timestamp)
- Multiple signatures in the same document
- Optional RFC3161 timestamping
- RFC3161 timestamping with public default TSA when enabled (
withTimestamp()) - PDF permission protection (for example, block content copying)
- Validation of existing digital signatures in PDF files
Requirements
- PHP
^8.2 ext-opensslext-curl- recommended:
ext-zlibandext-fileinfo
Installation
Install with Composer:
composer require signerphp/pdf-signer
Composer also installs signerphp/pdf-core, which provides PDF parsing and incremental serialization.
Architecture
signerphp/pdf-signer
|
+-- signerphp/pdf-core PDF parse, xref, ByteRange, incremental update
|
+-- CMS / PAdES / LTV signature container, timestamp, DSS
|
+-- SignatureProvider private-key operation (local OpenSSL by default)
pdf-core never depends on pdf-signer. Local PKCS#12 signing is the default; CSC/HSM providers are not part of the public API yet.
Usage
1) Basic signature
<?php use SignerPHP\PdfSigner\Presentation\Signer; $signedPdf = Signer::signer() ->withPdfContent(file_get_contents('/tmp/input.pdf')) ->withCertificatePath('/tmp/certificate.pfx', 'secret-password') ->sign(); file_put_contents('/tmp/output-signed.pdf', $signedPdf);
By default, the library applies a fallback visible appearance with a styled built-in stamp (internal image + default position) for simpler usage.
If you already have PKCS#12 in memory, use content instead of a file path:
$pkcs12 = file_get_contents('/tmp/certificate.pfx'); $signedPdf = Signer::signer() ->withPdfContent(file_get_contents('/tmp/input.pdf')) ->withCertificateContent($pkcs12, 'secret-password') ->sign();
2) Signature with metadata
<?php use SignerPHP\PdfSigner\Application\DTO\SignatureActorDto; use SignerPHP\PdfSigner\Application\DTO\SignatureMetadataDto; use SignerPHP\PdfSigner\Presentation\Signer; $metadata = new SignatureMetadataDto( reason: 'Contract approval', location: 'Sao Paulo - BR', actor: new SignatureActorDto( name: 'Maria Silva', contactInfo: 'maria@company.com' ) ); $signedPdf = Signer::signer() ->withPdfContent(file_get_contents('/tmp/input.pdf')) ->withCertificatePath('/tmp/certificate.pfx', 'secret-password') ->withMetadata($metadata) ->sign();
3) Visible signature with background image
The image is placed in the n0 layer and scaled with contain logic (aspect ratio preserved, centred inside the bbox).
<?php use SignerPHP\PdfSigner\Application\DTO\SignatureAppearanceDto; use SignerPHP\PdfSigner\Presentation\Signer; $appearance = new SignatureAppearanceDto( backgroundImagePath: '/tmp/stamp.png', rect: [350, 770, 500, 830], // [x1, y1, x2, y2] page: 0 // 0-based index ); $signedPdf = Signer::signer() ->withPdfContent(file_get_contents('/tmp/input.pdf')) ->withCertificatePath('/tmp/certificate.pfx', 'secret-password') ->withAppearance($appearance) ->sign();
A base64-encoded string is also accepted:
$appearance = new SignatureAppearanceDto( backgroundImagePath: base64_encode(file_get_contents('/tmp/stamp.png')), rect: [350, 770, 500, 830], page: 0 );
3.1) Visible signature with signer's drawn image
To show the signer's drawn PNG on a specific area of the bbox (e.g. left half), use signatureImagePath and signatureImageFrame. This places the image as an external XObject in the n2 layer, independently from the n0 background.
<?php use SignerPHP\PdfSigner\Application\DTO\SignatureAppearanceDto; use SignerPHP\PdfSigner\Presentation\Signer; $bboxW = 150; // urx - llx $bboxH = 60; // ury - lly $appearance = new SignatureAppearanceDto( backgroundImagePath: null, // no background stamp rect: [350, 770, 500, 830], page: 0, signatureImagePath: '/tmp/drawn-signature.png', signatureImageFrame: [0.0, 0.0, $bboxW / 2, (float) $bboxH], // left half ); $signedPdf = Signer::signer() ->withPdfContent(file_get_contents('/tmp/input.pdf')) ->withCertificatePath('/tmp/certificate.pfx', 'secret-password') ->withAppearance($appearance) ->sign();
3.2) Visible signature with custom content stream (n2 layer)
To embed arbitrary PDF text or graphics operators in the n2 layer — for example, the signer's name, date and reason — pass a SignatureAppearanceXObjectDto with the stream and its resource dictionary.
<?php use SignerPHP\PdfSigner\Application\DTO\SignatureAppearanceDto; use SignerPHP\PdfSigner\Application\DTO\SignatureAppearanceXObjectDto; use SignerPHP\PdfSigner\Presentation\Signer; $stream = "BT\n/F1 9 Tf\n0 0 0 rg\n4 44 Td\n(Signed by: Maria Silva) Tj\n0 -12 Td\n(Date: 2026-03-04) Tj\nET\n"; $appearance = new SignatureAppearanceDto( backgroundImagePath: '/tmp/stamp.png', rect: [350, 770, 500, 830], page: 0, xObject: new SignatureAppearanceXObjectDto( stream: $stream, resources: [ 'Font' => [ 'F1' => ['Type' => '/Font', 'Subtype' => '/Type1', 'BaseFont' => '/Helvetica'], ], ], ), ); $signedPdf = Signer::signer() ->withPdfContent(file_get_contents('/tmp/input.pdf')) ->withCertificatePath('/tmp/certificate.pfx', 'secret-password') ->withAppearance($appearance) ->sign();
4) Disable default appearance (invisible signature)
<?php use SignerPHP\PdfSigner\Presentation\Signer; $signedPdf = Signer::signer() ->withPdfContent(file_get_contents('/tmp/input.pdf')) ->withCertificatePath('/tmp/certificate.pfx', 'secret-password') ->withoutDefaultAppearance() ->sign();
5) Multiple signatures in the same PDF
Use the signed output as input for the next signature:
<?php use SignerPHP\PdfSigner\Presentation\Signer; $step1 = Signer::signer() ->withPdfContent(file_get_contents('/tmp/input.pdf')) ->withCertificatePath('/tmp/signer-a.pfx', 'password-a') ->sign(); $step2 = Signer::signer() ->withPdfContent($step1) ->withCertificatePath('/tmp/signer-b.pfx', 'password-b') ->sign(); file_put_contents('/tmp/output-multi-signed.pdf', $step2);
6) Signature with RFC3161 timestamp
To enable timestamping with default configuration, call withTimestamp().
In this case, the library uses a public default TSA (https://freetsa.org/tsr).
<?php use SignerPHP\PdfSigner\Presentation\Signer; $signedPdf = Signer::signer() ->withPdfContent(file_get_contents('/tmp/input.pdf')) ->withCertificatePath('/tmp/certificate.pfx', 'secret-password') ->withTimestamp() ->sign();
If you want a custom TSA only for this signing flow, use withTimestamp(new TimestampOptionsDto(...)).
The hashAlgorithm field accepts HashAlgorithm (recommended) or a compatible string (sha256, sha384, sha512, sha224, sha1).
6.1) Override the default TSA for this flow
<?php use SignerPHP\PdfSigner\Application\DTO\TimestampOptionsDto; use SignerPHP\PdfSigner\Presentation\Signer; $signedPdf = Signer::signer() ->withPdfContent(file_get_contents('/tmp/input.pdf')) ->withCertificatePath('/tmp/certificate.pfx', 'secret-password') ->withDefaultTimestampProfile(new TimestampOptionsDto( tsaUrl: 'https://timestamp.your-provider.com', hashAlgorithm: 'sha256', certReq: true, username: null, password: null, timeoutSeconds: 15 )) ->sign();
6.2) Disable default timestamping
<?php use SignerPHP\PdfSigner\Presentation\Signer; $signedPdf = Signer::signer() ->withPdfContent(file_get_contents('/tmp/input.pdf')) ->withCertificatePath('/tmp/certificate.pfx', 'secret-password') ->withoutTimestamp() ->sign();
6.3) Real TSA test and token generation (RFC3161)
For SaaS/API flows, you can run a real TSA routine (not only endpoint ping) using the timestamp facade:
<?php use SignerPHP\PdfSigner\Application\DTO\TimestampOptionsDto; use SignerPHP\PdfSigner\Presentation\Signer; $tsa = Signer::timestamp() ->withOptions(new TimestampOptionsDto( tsaUrl: 'https://freetsa.org/tsr', hashAlgorithm: 'sha256', )); $connection = $tsa->testConnection(); if (! $connection->success) { throw new RuntimeException('TSA test failed: '.($connection->message ?? 'unknown error')); } $tokenHex = $tsa ->withContent('probe-content') ->requestTokenHex();
6.3) Enable PAdES Baseline-B profile
<?php use SignerPHP\PdfSigner\Presentation\Signer; $signedPdf = Signer::signer() ->withPdfContent(file_get_contents('/tmp/input.pdf')) ->withCertificatePath('/tmp/certificate.pfx', 'secret-password') ->withPadesBaselineB() ->sign();
6.4) Enable PAdES Baseline-T profile
<?php use SignerPHP\PdfSigner\Presentation\Signer; $signedPdf = Signer::signer() ->withPdfContent(file_get_contents('/tmp/input.pdf')) ->withCertificatePath('/tmp/certificate.pfx', 'secret-password') ->withPadesBaselineT() ->sign();
In PAdES-T mode, timestamp must be active (for example, withTimestamp(...)).
6.5) Enable PAdES Baseline-LT profile
<?php use SignerPHP\PdfSigner\Presentation\Signer; $signedPdf = Signer::signer() ->withPdfContent(file_get_contents('/tmp/input.pdf')) ->withCertificatePath('/tmp/certificate.pfx', 'secret-password') ->withPadesBaselineLT() ->sign();
In PAdES-LT mode, besides timestamping, the library applies DSS enrichment with certificates extracted from CMS/RFC3161 signatures.
6.6) Enable PAdES Baseline-LTA profile
<?php use SignerPHP\PdfSigner\Presentation\Signer; $signedPdf = Signer::signer() ->withPdfContent(file_get_contents('/tmp/input.pdf')) ->withCertificatePath('/tmp/certificate.pfx', 'secret-password') ->withPadesBaselineLTA() ->sign();
In PAdES-LTA mode, after LT enrichment, the library adds one extra archival Document Timestamp on the final document revision.
6.7) Define document certification (DocMDP)
<?php use SignerPHP\PdfSigner\Application\DTO\CertificationLevel; use SignerPHP\PdfSigner\Presentation\Signer; $signedPdf = Signer::signer() ->withPdfContent(file_get_contents('/tmp/input.pdf')) ->withCertificatePath('/tmp/certificate.pfx', 'secret-password') ->withCertificationLevel(CertificationLevel::FormFillAndSignatures) ->sign();
Available levels:
CertificationLevel::NoChangesAllowed(1): no changes allowed after certification.CertificationLevel::FormFillAndSignatures(2): allows form filling and additional signatures.CertificationLevel::FormFillSignaturesAndAnnotations(3): allows forms, signatures, and annotations.
Default behavior:
- Without
withCertificationLevel(...), DocMDP is not explicitly set (null). - In
withBrazilPolicy(...), the library forcesCertificationLevel::FormFillAndSignatures(level2).
6.8) Brazil policy mode (br-iti)
<?php use SignerPHP\PdfSigner\Application\DTO\BrazilSignaturePolicyOptionsDto; use SignerPHP\PdfSigner\Presentation\Signer; $signedPdf = Signer::signer() ->withPdfContent(file_get_contents('/tmp/input.pdf')) ->withCertificatePath('/tmp/certificate.pfx', 'secret-password') ->withBrazilPolicy(new BrazilSignaturePolicyOptionsDto( tsaUrl: 'https://tsa.your-icpbrasil-provider.com', hashAlgorithm: 'sha256', timeoutSeconds: 20, certReq: true, )) ->sign();
This preset applies PAdES-LTA + DocMDP=2 + explicit policy timestamp.
To switch quickly to another TSA:
$policy = BrazilSignaturePolicyOptionsDto::tsa('https://tsa.your-provider.com') ->withHashAlgorithm('sha256') ->withTimeoutSeconds(20);
SERPRO support (homologation):
- OAuth2 token:
https://gateway.apiserpro.serpro.gov.br/token - ASN.1 timestamp endpoint:
https://gateway.apiserpro.serpro.gov.br/apitimestamp/v1/stamps-asn1
SERPRO helper example:
<?php use SignerPHP\PdfSigner\Application\DTO\BrazilSignaturePolicyOptionsDto; use SignerPHP\PdfSigner\Presentation\Signer; $signedPdf = Signer::signer() ->withPdfContent(file_get_contents('/tmp/input.pdf')) ->withCertificatePath('/tmp/certificate.pfx', 'secret-password') ->withBrazilPolicy(BrazilSignaturePolicyOptionsDto::serpro( consumerKey: 'YOUR_CONSUMER_KEY', consumerSecret: 'YOUR_CONSUMER_SECRET', hashAlgorithm: 'sha256', timeoutSeconds: 20 )) ->sign();
7) Protect PDF (block copy/print/modify)
<?php use SignerPHP\PdfSigner\Application\DTO\ProtectionOptionsDto; use SignerPHP\PdfSigner\Presentation\Signer; $protectedPdf = Signer::protection() ->withPdfContent(file_get_contents('/tmp/input.pdf')) ->withProtection(ProtectionOptionsDto::preventCopy( ownerPassword: 'owner-secret', userPassword: '' )) ->protect(); file_put_contents('/tmp/output-protected.pdf', $protectedPdf);
8) Recommended flow: protect and sign in the same builder
Use this flow to avoid ordering mistakes and ensure the signature is applied on the already protected PDF.
<?php use SignerPHP\PdfSigner\Application\DTO\ProtectionOptionsDto; use SignerPHP\PdfSigner\Presentation\Signer; $signedProtectedPdf = Signer::signer() ->withPdfContent(file_get_contents('/tmp/input.pdf')) ->withProtection(ProtectionOptionsDto::preventCopy( ownerPassword: 'owner-secret', userPassword: '' )) ->withCertificatePath('/tmp/certificate.pfx', 'secret-password') ->protectThenSign(); file_put_contents('/tmp/output-protected-signed.pdf', $signedProtectedPdf);
9) Validate digital signatures in a PDF
<?php use SignerPHP\PdfSigner\Presentation\Signer; $validation = Signer::validation() ->withPdfContent(file_get_contents('/tmp/input.pdf')) ->validate(); if (! $validation->hasSignatures) { // PDF has no signatures } if ($validation->allValid) { // all signatures were verified }
9.1) Validation with trust chain (trust store)
<?php use SignerPHP\PdfSigner\Presentation\Signer; $validation = Signer::validation() ->withPdfContent(file_get_contents('/tmp/input.pdf')) ->enableTrustChainValidation('/etc/ssl/certs/ca-certificates.crt') // optional; if omitted, tries the system default bundle ->validate(); foreach ($validation->entries as $entry) { var_dump($entry->trustValid); // true|false|null }
9.2) Validation with Brazil policy mode (br-iti)
<?php use SignerPHP\PdfSigner\Presentation\Signer; $validation = Signer::validation() ->withPdfContent(file_get_contents('/tmp/input.pdf')) ->withBrazilPolicy('/path/to/icp-brasil-bundle.pem') ->validate();
withBrazilPolicy(...) trust store precedence:
- If
trustStorePathis provided, it is used directly. - If
trustStorePathisnull, the library automatically builds/updates a local cached ICP-Brasil bundle and uses it.
If trustStorePath is null, br-iti mode builds an ICP-Brasil trust anchors bundle automatically in local cache:
- default directory:
sys_get_temp_dir()/signer-php/trust-anchors - default URLs:
http://acraiz.icpbrasil.gov.br/Certificado_AC_Raiz.crthttp://acraiz.icpbrasil.gov.br/credenciadas/RAIZ/ICP-Brasilv2.crthttp://acraiz.icpbrasil.gov.br/credenciadas/RAIZ/ICP-Brasilv5.crthttp://acraiz.icpbrasil.gov.br/credenciadas/RAIZ/ICP-Brasilv6.crthttp://acraiz.icpbrasil.gov.br/credenciadas/RAIZ/ICP-Brasilv7.crt
In br-iti mode, validation also verifies ICP-Brasil PAdES policy list (LPA):
https://politicas.icpbrasil.gov.br/LPA_PAdES.derhttps://politicas.icpbrasil.gov.br/LPA_PAdES.p7s
You can override these URLs:
<?php use SignerPHP\PdfSigner\Application\DTO\BrazilPolicyLpaUrlsDto; use SignerPHP\PdfSigner\Application\DTO\BrazilTrustAnchorsOptionsDto; use SignerPHP\PdfSigner\Presentation\Signer; $validation = Signer::validation() ->withPdfContent(file_get_contents('/tmp/input.pdf')) ->withBrazilPolicy( '/path/to/icp-brasil-bundle.pem', new BrazilPolicyLpaUrlsDto( lpaUrlAsn1Pades: 'https://your-endpoint/LPA_PAdES.der', lpaUrlAsn1SignaturePades: 'https://your-endpoint/LPA_PAdES.p7s', ), new BrazilTrustAnchorsOptionsDto( directory: '/tmp/my-trust-anchors-cache', urls: [ 'http://acraiz.icpbrasil.gov.br/Certificado_AC_Raiz.crt', 'http://acraiz.icpbrasil.gov.br/credenciadas/RAIZ/ICP-Brasilv7.crt', ], ), ) ->validate();
9.3) How to interpret trustValid and policyValid
trustValid = true: certificate chain is valid for the trust store in use.trustValid = false: chain is invalid, incomplete, or not trusted by the trust store in use.trustValid = null: trust chain validation was not executed for that signature.policyValid = true: PAdES LPA check (ICP-Brasil or overridden URLs) passed.policyValid = false: policy/LPA check failed for that signature.policyValid = null: policy mode was not requested in the flow.
Signature inspection via CLI
Besides signing, the project provides bin/signer-inspect for technical diagnostics of signed PDFs.
Basic usage
php bin/signer-inspect --input=/tmp/output-signed.pdf
JSON output
php bin/signer-inspect --input=/tmp/output-signed.pdf --json
Main inspection fields:
inferred_profile: inferred profile (pades-baseline-b,t,lt,lta).features: presence ofDSS,VRI,DocMDP,OCSPs,CRLs.revocation_endpoints: OCSP/CRL endpoints per discovered certificate.revocation_risk_summary: connectivity/missing-endpoint risk flags.
This inspection helps explain warnings reported by external validators (for example CRL/OCSP connectivity issues).
Environment diagnostics via CLI
Use bin/signer-doctor to quickly validate runtime dependencies (PHP version, required extensions, OpenSSL binary and openssl ts, qpdf, and temporary directory access).
php bin/signer-doctor
php bin/signer-doctor --json
Recommended flow (Brazil/ITI)
- Sign with
--policy=br-itiusingbin/signer-sign. - Validate programmatically with
Signer::validation()->withBrazilPolicy(...). - Inspect final PDF with
bin/signer-inspect --json. - If revocation warnings appear, check
revocation_risk_summaryand endpoint availability for OCSP/CRL URLs.
Running with Docker Compose
This project already includes docker-compose.yml and Dockerfile for the app service.
1) Create external network (first time only)
docker network create kool_global
2) Start the service
docker compose up -d --build
3) Install dependencies
docker compose exec app composer install
4) Run tests
docker compose exec app php ./vendor/bin/pest --configuration phpunit.xml tests
5) Stop environment
docker compose down
Sign using command line (CLI)
The project provides bin/signer-sign, bin/signer-inspect, and bin/signer-doctor.
Basic usage
php bin/signer-sign \
--input=/tmp/input.pdf \
--output=/tmp/output-signed.pdf \
--cert=/tmp/certificate.pfx \
--password='secret-password'
Example with PAdES Baseline-B and explicit timestamp
php bin/signer-sign \ --input=/tmp/input.pdf \ --output=/tmp/output-signed.pdf \ --cert=/tmp/certificate.pfx \ --password='secret-password' \ --pades-baseline-b \ --timestamp-url='https://tsa.example.com' \ --timestamp-hash='sha256' \ --timestamp-timeout=20
Example with DocMDP certification
php bin/signer-sign \
--input=/tmp/input.pdf \
--output=/tmp/output-certified.pdf \
--cert=/tmp/certificate.pfx \
--password='secret-password' \
--certification-level=2
Example with Brazil policy in CLI
php bin/signer-sign \ --input=/tmp/input.pdf \ --output=/tmp/output-br-iti.pdf \ --cert=/tmp/certificate.pfx \ --password='secret-password' \ --policy=br-iti \ --policy-serpro-consumer-key='YOUR_CONSUMER_KEY' \ --policy-serpro-consumer-secret='YOUR_CONSUMER_SECRET' \ --policy-timestamp-hash='sha256' \ --policy-timestamp-timeout=20
Example with PAdES Baseline-LT
php bin/signer-sign \ --input=/tmp/input.pdf \ --output=/tmp/output-signed-lt.pdf \ --cert=/tmp/certificate.pfx \ --password='secret-password' \ --pades-baseline-lt \ --timestamp-url='https://freetsa.org/tsr' \ --timestamp-hash='sha256' \ --timestamp-timeout=20
Example with PAdES Baseline-LTA
php bin/signer-sign \ --input=/tmp/input.pdf \ --output=/tmp/output-signed-lta.pdf \ --cert=/tmp/certificate.pfx \ --password='secret-password' \ --pades-baseline-lta \ --timestamp-url='https://freetsa.org/tsr' \ --timestamp-hash='sha256' \ --timestamp-timeout=20
Options help
php bin/signer-sign --help
Exceptions you should handle
SignerPHP\\PdfSigner\\Domain\\Exception\\InvalidCertificateExceptionSignerPHP\\PdfSigner\\Domain\\Exception\\SignProcessExceptionSignerPHP\\PdfSigner\\Domain\\Exception\\SignerException
Operational requirements
- For RFC3161 timestamping, host
opensslmust supportopenssl ts. - For PDF permissions protection, host
qpdfmust be installed. - If you use the public default TSA, consider availability/SLA for production and prefer a dedicated provider.
Implementation notes
- A digital signature covers specific PDF bytes (
ByteRange). Because of that, operations that rewrite file bytes should run before signing. - Validation checks
ByteRangeintegrity and CMS/PKCS#7 cryptographic validity with OpenSSL. Optionally, it can validate trust chain (enableTrustChainValidation(...)) and Brazil policy (withBrazilPolicy(...)). - PAdES profiles:
- Baseline-B:
SubFilter /ETSI.CAdES.detached - Baseline-T: Baseline-B + RFC3161
- Baseline-LT: Baseline-T +
DSS(Certs,OCSPs,CRLs,VRI) with best-effort evidence collection depending on chain endpoint availability - Baseline-LTA: Baseline-LT + additional archival
Document Timestamp
- Baseline-B:
- Default appearance uses
page = 0and an internal default rectangle; for full control usewithAppearance(...). - Supported PNG bit depths: 1, 2, 4, 8, and 16 bits per channel. 16-bit RGBA and grayscale-alpha PNGs are fully supported including SMask alpha extraction.
- PDF parsing (classic xref, xref streams, object streams,
/Prev, hybrid/XRefStm) is implemented insignerphp/pdf-core.
Running tests
vendor/bin/pest --configuration phpunit.xml tests
Code quality
composer pint:check composer pint:fix composer security:audit composer tests:coverage composer psalm composer deptrac composer infection