Plugins
Lockbox
A security addon for Filament v4 that protects sensitive fields with user-bound encryption keys (Split-Key, TOTP, crypto password or Passkeys).
Form Builder
Action
Widget
Form Field
Dark theme support
Yes
Multi language support
Yes
Not compatible with v5
Supported versions: 4.x
Documentation

CI Security Rating Maintainability Code Coverage Latest Stable Version Latest Unstable Version License CodeRabbit Pull Request Reviews

Filament Lockbox Logo

Secure per-user field encryption for Filament v4.
This package allows you to encrypt and decrypt sensitive data on a per-user basis, using a split-key approach:

  • Part A (server-side key) is stored encrypted in the database.
  • Part B (user-provided secret) is collected at runtime (crypto password, passkey, or TOTP).
  • Final key is derived from PartA + PartB using hash('sha256', ...).

This ensures that even administrators cannot decrypt data without the user-provided input.


#🧪 Code Quality & Coverage

To ensure long-term maintainability and security, this package is continuously analyzed with two systems:

  • SonarQube Cloud
    Monitors code quality, maintainability, and potential security issues. Results are automatically updated on every commit.

  • qlty.sh
    Provides detailed path coverage via PHPUnit’s --path-coverage, ensuring not only that lines are executed but also that different execution paths are validated.
    For cryptographic code, this level of coverage is especially important: it verifies complete execution flows (e.g. valid vs. invalid keys, missing secrets, or failed TOTP checks).
    Compared to branch coverage, path coverage ensures higher confidence in correctness and security-critical behavior.

Both tools run in CI and guarantee that security and quality checks are part of the development workflow.


#🚧 Project Status

This package is currently in alpha and under active development. Features and APIs may change before a stable release.


#✨ Features

  • 🔑 Per-user encryption keys (split key: server + user)
  • 🧩 Plug-and-play Filament components:
    • EncryptedTextInput → encrypts before save
    • DecryptedTextDisplay → decrypts on display
    • UnlockLockboxAction → prompts for crypto password or TOTP
  • 🔒 User-configurable crypto password support
  • 🗝️ Passkey (WebAuthn) support if your user implements HasPasskeys
  • 🔐 TOTP support if your user implements HasAppAuthentication
  • 🛡️ Zero-knowledge for admins – data is unreadable without user input
  • ⚙️ Configurable key material providers (PBKDF2, Passkeys, TOTP, custom)

#🗄️ Centralized Lockbox Storage

Unlike typical field encryption solutions, Filament Lockbox does not store encrypted data on your models.
Instead, all encrypted values are kept in a dedicated, polymorphic lockbox table — completely transparent to your application.

#✅ Benefits of This Architecture

  • Drop-in Usage
    Simply use EncryptedTextInput anywhere in your Filament form schema — no schema changes or model attributes required.

  • Polymorphic & Universal
    Works with any Eloquent model (User, Product, Order, ...).
    All sensitive data is centralized, making it easy to see which records have encrypted fields.

  • Performance-Friendly
    Main tables remain lean and fast, as encrypted data is kept out of your core business tables.

  • Compliance & Auditing

    • Simplified GDPR / “Right to be Forgotten”: just delete Lockbox entries per user.
    • Perfect for audits: one table gives full visibility of all encrypted fields.
    • Allows separate backup and retention strategies.
  • Developer Experience

    • No manual hooks or closures needed — saving & loading is handled automatically.
    • dehydrated(false) is applied internally.
    • Just replace TextInput with EncryptedTextInput and get full encryption.
$form->schema([
// Before:
TextInput::make('credit_card'),
 
// After:
EncryptedTextInput::make('credit_card')
->label('Credit Card'),
]);

The plugin takes care of everything:

  • 🔑 Per-user key management
  • 🔐 Encryption & decryption
  • 🗄️ Transparent Lockbox record handling
  • 🔄 Auto-loading of values on form display
  • 🧹 Automatic cleanup when models are deleted

#🔑 How It Works (Key Derivation)

┌────────────────────────┐
│ encrypted_user_key │ (in DB, encrypted with APP_KEY)
└──────────┬─────────────┘
│ decrypt
┌──────────┐
│ Part A │ (server key)
└─────┬────┘
┌───────────▼───────────┐
│ Part B (User Input) │ ← crypto password, passkey, or TOTP
└───────────┬──────────┘
│ combine
┌───────────────────┐
│ Final Key (32B) │
└─────────┬─────────┘
┌─────────────▼─────────────┐
│ Encrypt / Decrypt fields │
└──────────────────────────┘

This means database leaks alone cannot decrypt your data – PartB must be provided by the user.


#🚀 Installation

Install the package via Composer:

composer require n3xt0r/filament-lockbox

Important:
This package integrates with spatie/laravel-passkeys. Before running the install command, make sure you have published and run the Spatie migrations:

php artisan vendor:publish --provider="Spatie\\LaravelPasskeys\\LaravelPasskeysServiceProvider" --tag="laravel-passkeys-migrations"
php artisan migrate
Run the install command to publish all required assets and migrations:
 
```bash
php artisan filament-lockbox:install

#🔌 Register the Plugin (Filament v4)

Add the plugin to your Filament panel provider:

// app/Providers/Filament/AdminPanelProvider.php
 
use Filament\Panel;
use Filament\PanelProvider;
use N3XT0R\FilamentLockbox\FilamentLockboxPlugin;
 
class AdminPanelProvider extends PanelProvider
{
public function panel(Panel $panel): Panel
{
return $panel
->plugins([
FilamentLockboxPlugin::make(),
]);
}
}

Optional configuration:

// config/filament-lockbox.php
return [
'show_widget' => true, // set false to hide the status widget
'providers' => [
\N3XT0R\FilamentLockbox\Managers\KeyMaterial\TotpKeyMaterialProvider::class,
\N3XT0R\FilamentLockbox\Managers\KeyMaterial\CryptoPasswordKeyMaterialProvider::class,
],
];

You can publish the config and translations if you need customization:

php artisan vendor:publish --tag="filament-lockbox-config"
php artisan vendor:publish --tag="filament-lockbox-translations"

#⚙️ Model Setup

Your User model must:

  • Implement HasLockboxKeys
  • Use the InteractsWithLockboxKeys trait
  • Hide and cast the lockbox fields

#Example: User Model

use Filament\Models\Contracts\FilamentUser;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use N3XT0R\FilamentLockbox\Contracts\HasLockboxKeys;
use N3XT0R\FilamentLockbox\Concerns\InteractsWithLockboxKeys;
 
class User extends Authenticatable implements FilamentUser, MustVerifyEmail, HasLockboxKeys
{
use InteractsWithLockboxKeys;
 
protected $hidden = [
'encrypted_user_key',
'crypto_password_hash',
'lockbox_provider',
];
 
protected function casts(): array
{
return [
'encrypted_user_key' => 'encrypted',
'crypto_password_hash' => 'string',
'lockbox_provider' => 'string',
];
}
}

#Example: Any Model with Encrypted Fields

Any Eloquent model that should have encrypted fields must:

  • Implement HasLockbox
  • Use the InteractsWithLockbox trait

This enables the polymorphic relation to the lockbox table and lets the package handle encryption transparently.

use Illuminate\Database\Eloquent\Model;
use N3XT0R\FilamentLockbox\Contracts\HasLockbox;
use N3XT0R\FilamentLockbox\Concerns\InteractsWithLockbox;
 
class Company extends Model implements HasLockbox
{
use InteractsWithLockbox;
 
protected $fillable = [
'name',
'email',
// no need to list encrypted fields here – they live in the lockbox table
];
}

You can now use EncryptedTextInput::make('field_name') in your Filament form schemas for this model —
the package will automatically store and retrieve the data from the centralized lockbox table.


#🧑‍💻 User Flow

  1. Go to the Lockbox widget in your Filament panel.
  2. Click Generate Lockbox Key.
  3. Set a crypto password, register a passkey, or enable TOTP.
  4. Unlock once per session to access or modify encrypted fields.

#🧩 Usage in Filament Forms

#1️⃣ Storing Encrypted Data

use N3XT0R\FilamentLockbox\Forms\Actions\UnlockLockboxAction;
use N3XT0R\FilamentLockbox\Forms\Components\EncryptedTextInput;
 
$form
->schema([
EncryptedTextInput::make('secret_notes')
->label('Secret Notes'),
])
->extraActions([
UnlockLockboxAction::make(),
]);

#2️⃣ Displaying Decrypted Data

use N3XT0R\FilamentLockbox\Forms\Components\DecryptedTextDisplay;
use N3XT0R\FilamentLockbox\Forms\Actions\UnlockLockboxAction;
 
$form
->schema([
DecryptedTextDisplay::make('secret_notes')
->label('Secret Notes'),
])
->extraActions([
UnlockLockboxAction::make(),
]);

#🔒 Security Model

  • Split-key encryption (PartA + PartB → Final Key)
  • PBKDF2 key derivation with 100,000 iterations
  • Server keys stored encrypted with APP_KEY
  • Extensible providers for alternative key material

#🔑 Passkeys (WebAuthn)

This package ships with built-in support for spatie/laravel-passkeys and requires it by default.

You can control Passkey usage via this package's configuration. If you don't plan to use WebAuthn/Passkeys, disable the integration in config/filament-lockbox.php.


#📖 Roadmap

  • [ ] Textarea and file encryption support
  • [ ] Automatic modal prompt if unlock is missing
  • [ ] Session-based unlock expiry
  • [ ] Configurable PBKDF2 parameters
  • [ ] Improve TOTP integration: ensure user-assigned secrets (crypto password) are required and TOTP is used only as a second factor

#📜 License

MIT © N3XT0R

Ilya Beliaev

I’m a software engineer with 15+ years of experience in backend development, system architecture, and DevOps. As a certified ISO 27001 Information Security Officer, I combine development expertise with a strong focus on security and compliance. I enjoy contributing to open-source and creating tools that make complex systems more secure and developer-friendly.

2
Plugins
11
Stars
More from this author
Featured Plugins