n3xt0r / filament-lockbox
Filament v4 security addon to protect sensitive data with user-bound encryption keys (Split-Key, TOTP, or crypto password)
Fund package maintenance!
N3XT0R
Requires
- php: ^8.2
- filament/filament: ^4.0
- nesbot/carbon: ^3.8
- spatie/laravel-package-tools: ^1.15.0
- spatie/laravel-passkeys: ^1.0
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.0
- nunomaduro/collision: ^8.0
- orchestra/testbench: ^9.0|^10.0
- phpstan/extension-installer: ^1.1
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
- phpunit/phpunit: ^11.5
- rector/rector: ^2.0
- spatie/laravel-ray: ^1.26
This package is auto-updated.
Last update: 2025-09-20 14:39:41 UTC
README
Filament Lockbox
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.
π§ 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 saveDecryptedTextDisplay
β decrypts on displayUnlockLockboxAction
β 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 useEncryptedTextInput
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
withEncryptedTextInput
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 withspatie/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
- Go to the Lockbox widget in your Filament panel.
- Click Generate Lockbox Key.
- Set a crypto password, register a passkey, or enable TOTP.
- 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
π License
MIT Β© N3XT0R