PHPackages                             illuma-law/laravel-vault-cipher - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Security](/categories/security)
4. /
5. illuma-law/laravel-vault-cipher

ActiveLibrary[Security](/categories/security)

illuma-law/laravel-vault-cipher
===============================

Tenant-aware streaming encryption for Laravel.

v0.1.4(1mo ago)062MITPHPPHP ^8.3CI failing

Since Apr 20Pushed 1mo agoCompare

[ Source](https://github.com/illuma-law/laravel-vault-cipher)[ Packagist](https://packagist.org/packages/illuma-law/laravel-vault-cipher)[ RSS](/packages/illuma-law-laravel-vault-cipher/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (16)Versions (6)Used By (0)

Laravel Vault Cipher
====================

[](#laravel-vault-cipher)

[![Latest Version on Packagist](https://camo.githubusercontent.com/31d6837bca8fead2973a31e08a0f86781db1e7197ee0b39c02e7d978ee44468c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f696c6c756d612d6c61772f6c61726176656c2d7661756c742d6369706865722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/illuma-law/laravel-vault-cipher)[![GitHub Tests Action Action Status](https://camo.githubusercontent.com/a86d111f0efa6d799788adfc2a41ad153c73f1d3d6a88e9797afb2da635a41ef/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f696c6c756d612d6c61772f6c61726176656c2d7661756c742d6369706865722f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/illuma-law/laravel-vault-cipher/actions/workflows/run-tests.yml)[![Total Downloads](https://camo.githubusercontent.com/8df050edf2d7e482e844669131ef203f67855f9ec7b7c6992a8d7537c1825063/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f696c6c756d612d6c61772f6c61726176656c2d7661756c742d6369706865722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/illuma-law/laravel-vault-cipher)

Tenant-aware streaming encryption for Laravel applications.

In multi-tenant (B2B) applications, sharing a single application-wide encryption key (the standard Laravel `APP_KEY`) creates a massive blast radius if compromised. Vault Cipher solves this by encrypting each tenant's data with their own unique encryption key.

Features
--------

[](#features)

- **Tenant-Specific Keys:** Encrypt and decrypt data dynamically using unique keys per tenant.
- **File Streaming Encryption:** Securely encrypt large files (e.g., PDFs, videos) on the fly without exhausting PHP memory limits.
- **Eloquent Casts:** Drop-in `TenantEncrypted` casts that automatically resolve the correct key based on the model's relationship.
- **Provider Interface:** You control how tenant keys are fetched and stored (Database, HashiCorp Vault, AWS KMS, etc.).

Installation
------------

[](#installation)

You can install the package via composer:

```
composer require illuma-law/laravel-vault-cipher
```

Publish the config file:

```
php artisan vendor:publish --tag="vault-cipher-config"
```

Configuration
-------------

[](#configuration)

The configuration file allows you to define:

- `chunk_size`: The chunk size in bytes for streaming encryption (default: 64KB).
- `default_disk`: The default filesystem disk for encrypted files (default: `local`).
- `key_provider`: The class responsible for resolving tenant keys.

### The Key Provider

[](#the-key-provider)

You must create a class that implements the `TenantKeyProvider` interface to tell the package how to resolve an encryption key for a given tenant ID:

```
namespace App\Services;

use IllumaLaw\VaultCipher\Contracts\TenantKeyProvider;
use App\Models\Tenant;

class MyTenantKeyProvider implements TenantKeyProvider
{
    public function getKey(int|string $tenantId): string
    {
        // Example: Retrieve the key from the database and decrypt it using the master APP_KEY
        $tenant = Tenant::findOrFail($tenantId);
        return decrypt($tenant->encrypted_data_key);
    }
}
```

Then, register your provider in `config/vault-cipher.php`:

```
    'key_provider' => \App\Services\MyTenantKeyProvider::class,
```

The package provides a `VaultKeyGenerator` to create compatible encryption keys:

```
use IllumaLaw\VaultCipher\Support\VaultKeyGenerator;

// Returns a base64-encoded 32-byte key (AES-256 compatible)
$team->encryption_key = VaultKeyGenerator::generate();
```

Usage &amp; Integration
-----------------------

[](#usage--integration)

### String Encryption

[](#string-encryption)

You can encrypt simple strings dynamically using the Facade:

```
use IllumaLaw\VaultCipher\Facades\TenantEncryptionManager;

$tenantId = 123;
$encrypted = TenantEncryptionManager::encryptString($tenantId, 'highly sensitive medical data');

$decrypted = TenantEncryptionManager::decryptString($tenantId, $encrypted);
```

### File Streaming Encryption

[](#file-streaming-encryption)

Storing large files securely requires streaming. Vault Cipher chunk-encrypts the file in memory while writing it to disk.

```
use IllumaLaw\VaultCipher\Facades\TenantEncryptionManager;

$tenantId = 123;

// Stream content directly to an encrypted file on your configured disk
TenantEncryptionManager::store($tenantId, 'contracts/agreement-1.pdf', $binaryContent);

// Retrieve and stream the decrypted content back (e.g., for downloading)
$content = TenantEncryptionManager::get($tenantId, 'contracts/agreement-1.pdf');
```

For streaming operations that require temporary access to decrypted files:

```
use IllumaLaw\VaultCipher\Facades\TenantEncryptionManager;

// Decrypts to a temp path, executes callback, then cleans up the temp file
TenantEncryptionManager::usingDecryptedTempPath(
    tenantId: $tenantId,
    path: 'contracts/agreement-1.pdf',
    callback: function (string $tempPath) {
        // Process the decrypted file (e.g., pass to OCR, thumbnail generation, etc.)
        return processFile($tempPath);
    },
    disk: 's3'
);
```

You can also encrypt existing files already present on the disk in place:

```
TenantEncryptionManager::encryptExistingPath($tenantId, 'existing/unencrypted_file.txt');
```

### Eloquent Casts

[](#eloquent-casts)

For database columns, use the provided Eloquent casts to automate encryption and decryption when saving or retrieving models.

```
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use IllumaLaw\VaultCipher\Casts\TenantEncrypted;
use IllumaLaw\VaultCipher\Casts\TenantEncryptedArray;
use IllumaLaw\VaultCipher\Contracts\TenantCipherable;

class Document extends Model implements TenantCipherable
{
    protected $casts = [
        'content' => TenantEncrypted::class,
        'metadata' => TenantEncryptedArray::class, // Handles arrays/JSON
    ];

    /**
     * Required by TenantCipherable so the Cast knows which key to use.
     */
    public function getTenantIdForCipher(): int|string|null
    {
        // Return the foreign key or relation ID that identifies the tenant
        return $this->team_id;
    }
}
```

If your model doesn't implement `TenantCipherable`, the cast will attempt to look for a `team_id` or `tenant_id` property automatically as a fallback.

### Key Rotation

[](#key-rotation)

When rotating tenant encryption keys, you need to re-encrypt existing data. The package provides `TenantKeyRotator` for this purpose:

```
use IllumaLaw\VaultCipher\Facades\TenantEncryptionManager;
use IllumaLaw\VaultCipher\Support\TenantKeyRotator;

// Build encrypters from raw keys during rotation
$oldKey = base64_decode($team->encryption_key);
$newKey = base64_decode(VaultKeyGenerator::generate());

$rotator = new TenantKeyRotator(
    oldEncrypter: TenantEncryptionManager::encrypterForRawKey($oldKey),
    newEncrypter: TenantEncryptionManager::encrypterForRawKey($newKey),
    oldFileEncrypter: TenantEncryptionManager::fileEncrypterForRawKey($oldKey),
    newFileEncrypter: TenantEncryptionManager::fileEncrypterForRawKey($newKey),
);

// Re-encrypt a string value (handles passthrough if decryption fails)
$reEncrypted = $rotator->rotateString($ciphertext);

// Re-encrypt a file on disk (detects chunk vs string encryption)
$rotator->rotateFileOnDisk($disk, 'contracts/agreement-1.pdf');
```

Testing
-------

[](#testing)

Run the test suite:

```
composer test
```

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance91

Actively maintained with recent releases

Popularity12

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity42

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~2 days

Total

5

Last Release

44d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/2affac64f2726a640084b203503518ca01f582536d60a0a299b614486ed95aaa?d=identicon)[miguelenes](/maintainers/miguelenes)

---

Top Contributors

[![miguelenes](https://avatars.githubusercontent.com/u/1568086?v=4)](https://github.com/miguelenes "miguelenes (12 commits)")

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/illuma-law-laravel-vault-cipher/health.svg)

```
[![Health](https://phpackages.com/badges/illuma-law-laravel-vault-cipher/health.svg)](https://phpackages.com/packages/illuma-law-laravel-vault-cipher)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3325.1M337](/packages/psalm-plugin-laravel)[spatie/laravel-health

Monitor the health of a Laravel application

88011.3M149](/packages/spatie-laravel-health)[laravel/ai

The official AI SDK for Laravel.

9782.1M153](/packages/laravel-ai)[clickbar/laravel-magellan

This package provides functionality for working with the postgis extension in Laravel.

436834.4k1](/packages/clickbar-laravel-magellan)[simplestats-io/laravel-client

Analytics for Laravel. Track visitors, registrations, and payments. Discover which channels actually drive revenue, not just traffic. Server-side, GDPR compliant, ad-blocker proof.

5019.3k](/packages/simplestats-io-laravel-client)[pressbooks/pressbooks

Pressbooks is an open source book publishing tool built on a WordPress multisite platform. Pressbooks outputs books in multiple formats, including PDF, EPUB, web, and a variety of XML flavours, using a theming/templating system, driven by CSS.

45344.0k1](/packages/pressbooks-pressbooks)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
