Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Signet Pdf Laravel Package

lsnepomuceno/signet-pdf

Signet PDF is a Laravel package for digitally signing PDF documents. It provides a simple API for adding X.509 certificate signatures to existing or generated PDFs, helping PHP applications implement document authenticity, signature validation, and secure signing workflows with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install with composer require lsnepomuceno/signet-pdf:^3.0. Confirm the PHP and extension requirements in the package's composer.json; signing needs OpenSSL, and ICP-Brasil certificate handling may also require mbstring/gmp.
  • Read first, in this order: UPGRADE.md (three breaking changes), the 3.0.0 CHANGELOG.md, then the v3 documentation site. Do not follow 1.x/2.x snippets — those docs are archived at /v1/ and /v2/.
  • First use case: sign an existing PDF with an ICP-Brasil PAdES policy, write the result to a Laravel disk, and persist the receipt. A minimal flow looks like this (method names are illustrative — confirm against the v3 docs):
use Lsnepomuceno\Signet\Facades\Signet;
use Lsnepomuceno\Signet\Enums\PadesProfile;
use Lsnepomuceno\Signet\Enums\SignaturePolicy;

$policy = SignaturePolicy::forProfile(PadesProfile::PadesADRB);

$signed = Signet::pdf(Storage::path('contracts/in.pdf'))
    ->withPolicy($policy)
    ->sign($certificatePath, $password);

Storage::disk('s3')->writeStream(
    'contracts/signed.pdf',
    $signed->document->stream()
);

$receipt = $signed->receipt(); // policy, profile, digest, signer, timestamps
  • Before writing application code, sign one fixture PDF and run it through the ICP-Brasil Verificador. That validates the policy declaration, security store, and archival PBAD_ entries end to end.

Implementation Patterns

  • Stream through the whole pipeline. 3.0.0's Support\DocumentBuffer exists to avoid holding the document twice. Read from Storage::readStream() or a temporary path, pass the buffer through signing, and stream the result directly to its destination. Avoid file_get_contents(), base64_encode(), and response helpers that buffer the full body.
  • Choose the profile deliberately. Use SignaturePolicy::forProfile(...) and treat a null result as "ITI publishes no such policy," not as a package error. For long-term/archival signatures, use the ICP-Brasil archival profiles (AD-RB/AD-RT) that the package now makes conformant; B-LT is not one of them.
  • External/HSM signing. When the private key must not enter the PHP process, prepare the signature, send the digest/byte range to your signer (PKCS#11, KMS, Vault, hardware token), and inject the raw signature. Put this behind your own Signer service so controllers and jobs do not know whether signing is local or remote.
  • Queue large signatures. Signing is CPU-bound and potentially slow, especially with timestamping. Dispatch a job with the disk/path and policy parameters — never serialize the DocumentBuffer or PDF bytes into the queue payload. Store the receipt in the same transaction or job step as the signed file.
  • Persist receipt() as audit data. It records what was signed, under which policy/profile. Keep it alongside the document hash, signer identity, timestamp information, and the Verificador result. The signed bytes alone do not tell you which policy was applied.
  • Timestamped profiles need a TSA. Configure the RFC 3161 timestamp authority for T/AD-RT policies and handle TSA downtime with retries/backoff. Do not cache stale timestamp responses.
  • Validate outside the package. Treat the ICP-Brasil Verificador as the source of truth. In CI, use fixture PDFs and a fake signer for speed, then run a smaller set of real-policy signature tests against the Verificador or a PAdES validator.
  • Laravel integration points. Use a dedicated filesystem disk for signed artifacts, streamed downloads (response()->streamDownload()), a validation rule for uploaded PDFs, and events/listeners for "document signed" so notifications and audits are decoupled from the signing call.

Gotchas and Tips

  • PreparedSignature::$document is no longer a string. It is a Support\DocumentBuffer. Any strlen(), echo, base64_encode(), string concatenation, or Storage::put($path, $signed->document) will break. Move to the buffer's stream/write API and update tests that assert on string contents.
  • intervention/image 4.x is required. Applications pinned to 3.x will hit Composer conflicts. Check direct and transitive constraints before upgrading; Image 4 also has its own API changes if you use it directly.
  • SignaturePolicy::forProfile(PadesBLT) returns null by design. Do not "fix" this with a fallback policy. ITI publishes no B-LT policy that the signature satisfies; select an archival ICP-Brasil profile instead.
  • Streaming lowers the multiplier, not the floor. A 300 MB document signing in ~310 MB still requires memory_limit above the document size plus PHP/library overhead. Disable output buffering, avoid loading the result into a response string, and stream downloads.
  • Queue payloads are a common regression. After the 3.0 change, code that previously serialized the document string may silently serialize a buffer object or fail. Pass paths/disks and reconstruct the buffer inside the job.
  • Certificate chain completeness matters. Missing intermediates cause Verificador failures even when the signature bytes are correct. Include the full ICP-Brasil chain and confirm the end-entity certificate's validity window and key usage.
  • Clock and timezone accuracy affect validity. Timestamp and certificate-validity checks are time-sensitive; ensure the host clock is synchronized.
  • Third-party validators may not understand the new entries. The policy declaration, security store, and PBAD_ entries are required for ICP-Brasil archival conformance, but Adobe or other PAdES tools may report differently. Test against the validator your users/customers actually rely on.
  • Clear config cache after policy/TSA changes. Laravel config caching can mask updated OIDs, TSA URLs, and certificate paths.
  • Extension points to keep stable in your codebase: a custom signer (local/HSM/KMS), a TSA client wrapper, and a policy/profile mapping service. These isolate you from future package API changes and make the 3.x DocumentBuffer migration a one-place change.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums