kukux/digital-signature

A Laravel Filament package for digital signature capture, certificate issuance, and PDF signing (v4 + v5 compatible).

Maintainers

Package info

github.com/cortejojicoy/digital-signature

pkg:composer/kukux/digital-signature

Statistics

Installs: 24

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.26 2026-04-16 07:57 UTC

README

Latest Version on Packagist Total Downloads License

A Laravel Filament plugin for capturing signatures, issuing X.509 certificates, and embedding cryptographically signed stamps into PDF documents.

Supports: Filament v4 and v5 — Laravel 11 / 12 — PHP 8.2+

Documentation

Doc Description
Installation Composer, migrations, plugin registration, admin resource
Configuration All config keys and env variables
Model Setup Signable interface and HasSignatures trait
Filament Components SignaturePad, SignatureColumn, SignatureResource, SignDocumentAction
Signing Workflow Full lifecycle and SignatureManager API
Certificates Certificate issuance, CA setup, CFSSL
Security HMAC metadata, machine binding, DB cross-validation, forgery detection

Requirements

  • PHP 8.2+ with ext-openssl and ext-gd
  • Laravel 11 or 12
  • Filament 4 or 5

Quick Install

composer require kukux/digital-signature
php artisan vendor:publish --tag=signature-migrations
php artisan vendor:publish --tag=signature-config
php artisan migrate

Register the plugin in your panel provider:

// app/Providers/Filament/AdminPanelProvider.php
use Kukux\DigitalSignature\SignaturePlugin;

->plugins([
    SignaturePlugin::make()
        ->navigationGroup('Documents')   // optional
        ->navigationIcon('heroicon-o-pencil-square')  // optional
        ->navigationSort(10),             // optional
])

This registers:

  • Signatures — a full admin resource (list + view all signature records)
  • Sign Document — a standalone page for ad-hoc signing

Preparing a Signable Model

Any model whose PDF can be signed must implement Signable and use HasSignatures.

use Kukux\DigitalSignature\Contracts\Signable;
use Kukux\DigitalSignature\Traits\HasSignatures;

class Contract extends Model implements Signable
{
    use HasSignatures;

    public function getSignableTitle(): string   { return $this->title; }
    public function getSignablePdfPath(): string { return $this->pdf_path; }
    public function getSignableId(): int|string  { return $this->id; }
}

Adding the Sign Action to Your Own Resource

use Kukux\DigitalSignature\Filament\Actions\SignDocumentAction;
use Kukux\DigitalSignature\Filament\Columns\SignatureColumn;

class ContractResource extends Resource
{
    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                TextColumn::make('title'),
                SignatureColumn::make('signature')->thumbSize(80, 32),
            ])
            ->actions([
                SignDocumentAction::make()
                    ->stampAt(page: 1, x: 100, y: 650, w: 200, h: 80),
            ]);
    }
}

Built-in Signatures Admin Resource

When the plugin is registered, a Signatures resource appears in the sidebar automatically.

List page — table of all signature records with thumbnail, signer, status, and method.
View page — full infolist showing the large signature image, signer details, security metadata.

Both pages include a Sign Document header action.

Customize appearance:

SignaturePlugin::make()
    ->navigationGroup('Documents')
    ->navigationIcon('heroicon-o-pencil-square')
    ->navigationSort(10)
    ->navigationLabel('Document Signatures')

// Disable the resource entirely (bring your own):
SignaturePlugin::make()->withoutResource()

// Disable only the standalone sign page:
SignaturePlugin::make()->withoutPages()

Security Highlights

Feature Default
PKCS#7 cryptographic signature embedded in PDF Always on
DocMDP P=2 — post-signing modification detection Always on
HMAC-signed PNG metadata (tEXt + XMP) Always on
XMP metadata visible in macOS Preview & Windows Explorer Always on
Signer identity (name + email) embedded in PNG Always on
Forgery / screenshot upload rejection Always on
Document integrity hashes (before + after) Always on
Machine binding — DB cross-validation on re-upload Always on
Machine lock — reject re-upload from different device SIGNATURE_MACHINE_LOCK=true
CRL certificate revocation check SIGNATURE_CRL_ENABLED=true
RFC 3161 trusted timestamp via TSA SIGNATURE_TSA_URL=https://...

For full details see docs/security.md.

Queue

Signing runs asynchronously. Start a queue worker:

php artisan queue:work

To sign synchronously (no queue required):

SignDocumentAction::make()   // default is now synchronous

The action calls embedAndFinalize() directly unless you opt in to queued signing:

SignDocumentAction::make()->queued()