A powerful Laravel package for encrypting Eloquent model attributes using the Hill Cipher algorithm with multi-language support.
- π Hill Cipher Encryption: Advanced matrix-based encryption algorithm
- π Multi-language Support: English, Kurdish, and Arabic character sets
- π Automatic Encryption/Decryption: Seamless model attribute handling
- β Validation Rules: Built-in unique and exists validation for encrypted fields
- π¨ Blade Directives: Easy encryption/decryption in views
- π Key Rotation: Re-encrypt data with new keys using console commands
- β‘ Performance Optimized: Chunked processing for large datasets
Install the package via Composer:
composer require hamoi1/eloquent-encryptablePublish the configuration file:
php artisan vendor:publish --provider="Hamoi1\EloquentEncryptAble\EloquentEncryptAbleServiceProvider" --tag="config"After publishing, configure your encryption settings in config/eloquent-encryptable.php:
<?php
return [
/*
|--------------------------------------------------------------------------
| Hill Cipher Key Matrix
|--------------------------------------------------------------------------
|
| The key matrix for the Hill cipher encryption. Must be a square matrix
| (2x2 or 3x3) and invertible. The matrix should be provided as a JSON string.
|
*/
'key' => '[[3,2],[5,7]]', // 2x2 matrix example
/*
|--------------------------------------------------------------------------
| Previous Key Matrix
|--------------------------------------------------------------------------
|
| Used for key rotation. Store your previous key here when updating
| the main key to allow re-encryption of existing data.
|
*/
'previous_key' => null,
/*
|--------------------------------------------------------------------------
| Models to Re-encrypt
|--------------------------------------------------------------------------
|
| List of model classes that should be processed during key rotation.
|
*/
'models' => [
// App\Models\User::class,
// App\Models\Customer::class,
],
];- Size: 2x2 or 3x3 square matrix
- Invertible: Must have a determinant that is coprime with the alphabet size
- Format: JSON string representation of the matrix
Example valid matrices:
// 2x2 matrix
'key' => '[[3,2],[5,7]]'
// 3x3 matrix
'key' => '[[6,24,1],[13,16,10],[20,17,15]]'Add the EncryptAble trait to your Eloquent model and define the $encryptAble property:
<?php
namespace App\Models;
use Hamoi1\EloquentEncryptAble\Traits\EncryptAble;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
use EncryptAble;
protected $fillable = [
'name', 'email', 'phone', 'address'
];
/**
* The attributes that should be encrypted.
*
* @var array
*/
protected $encryptAble = [
'phone', 'address'
];
}Now your specified attributes will be automatically encrypted when saving and decrypted when retrieving:
// Create a new user - phone and address will be encrypted automatically
$user = User::create([
'name' => 'John Doe',
'email' => '[email protected]',
'phone' => '+1234567890',
'address' => '123 Main Street'
]);
// Retrieve user - phone and address will be decrypted automatically
$user = User::find(1);
echo $user->phone; // +1234567890 (decrypted)
echo $user->address; // 123 Main Street (decrypted)The package provides custom validation rules for encrypted fields:
Ensure encrypted field values are unique:
use Hamoi1\EloquentEncryptAble\Rules\EncryptAbleUniqueRule;
public function rules()
{
return [
'phone' => [
'required',
new EncryptAbleUniqueRule('users', 'phone')
],
// For updates, exclude current record
'email' => [
'required',
new EncryptAbleUniqueRule('users', 'email', [
'column' => 'id',
'value' => $this->user->id
])
],
];
}Validate that encrypted field value exists:
use Hamoi1\EloquentEncryptAble\Rules\EncryptAbleExistRule;
public function rules()
{
return [
'parent_phone' => [
'required',
new EncryptAbleExistRule('users', 'phone')
],
];
}Use convenient Blade directives in your views:
{{-- Decrypt a value --}}
@decrypt($user->phone)
{{-- Decrypt with default value --}}
@decrypt($user->phone, 'N/A')
{{-- Encrypt a value --}}
@encrypt('sensitive data')Example in a Blade template:
<div class="user-info">
<p><strong>Name:</strong> {{ $user->name }}</p>
<p><strong>Phone:</strong> @decrypt($user->phone, 'Not provided')</p>
<p><strong>Address:</strong> @decrypt($user->address)</p>
</div>When rotating encryption keys, use the console command to re-encrypt existing data:
php artisan eloquent-encryptable:re-encryptThis command will:
- Load models from the configuration
- Decrypt data using the previous key
- Re-encrypt using the new key
- Show progress bars and timing information
- Process data in chunks for memory efficiency
Access the encryption service directly:
use Hamoi1\EloquentEncryptAble\Services\EloquentEncryptAbleService;
$service = app(EloquentEncryptAbleService::class);
// Encrypt a string
$encrypted = $service->encrypt('sensitive data');
// Decrypt a string
$decrypted = $service->decrypt($encrypted);
// Decrypt using previous key (for key rotation)
$decrypted = $service->decrypt($encrypted, true);Process multiple model attributes:
$data = [
'phone' => '+1234567890',
'address' => '123 Main Street',
'ssn' => '123-45-6789'
];
$fields = ['phone', 'address', 'ssn'];
// Encrypt multiple fields
$encrypted = $service->encryptModelData($data, $fields);
// Decrypt multiple fields
$decrypted = $service->decryptModelData($encrypted, $fields);
// Re-encrypt with new key
$reEncrypted = $service->reEncryptModelData($encrypted, $fields);Generate a random invertible key matrix:
// This will throw an exception with a suggested matrix if current key is invalid
try {
$service = app(EloquentEncryptAbleService::class);
$service->encrypt('test');
} catch (InvalidArgumentException $e) {
echo $e->getMessage(); // Contains the suggested matrix
}| Method | Description |
|---|---|
bootEncryptAble() |
Automatically encrypts/decrypts model attributes |
| Method | Parameters | Description |
|---|---|---|
encrypt(string $word) |
$word - Text to encrypt |
Encrypts a string using Hill cipher |
decrypt(string $encrypted, bool $previousKey = false) |
$encrypted - Encrypted text$previousKey - Use previous key |
Decrypts a string |
encryptModelData(array $data, array $fields) |
$data - Model data$fields - Fields to encrypt |
Encrypts specified model fields |
decryptModelData(array $data, array $fields) |
$data - Model data$fields - Fields to decrypt |
Decrypts specified model fields |
reEncryptModelData(array $data, array $fields) |
$data - Model data$fields - Fields to re-encrypt |
Re-encrypts using new key |
| Rule | Constructor Parameters | Description |
|---|---|---|
EncryptAbleUniqueRule |
$table, $column, $except = [] |
Validates uniqueness of encrypted field |
EncryptAbleExistRule |
$table, $column, $except = [] |
Validates existence of encrypted field |
1. Invalid Key Matrix Error
InvalidArgumentException: Invalid Hill cipher key matrix in .env file.
Solution: Ensure your key matrix is:
- A valid JSON string
- Square (2x2 or 3x3)
- Invertible (determinant coprime with alphabet size)
2. Memory Issues with Large Datasets
Fatal error: Allowed memory size exhausted
Solution: The re-encrypt command processes data in chunks of 100. For very large datasets, consider:
- Increasing PHP memory limit
- Processing models individually
- Running during off-peak hours
3. Character Encoding Issues
Encrypted text appears garbled
Solution: Ensure your database columns support UTF-8 encoding:
ALTER TABLE users MODIFY COLUMN address TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;Enable debug logging by adding to your model:
protected static function bootEncryptAble()
{
parent::bootEncryptAble();
if (config('app.debug')) {
\Log::info('Encrypting model: ' . static::class);
}
}We welcome contributions! Please follow these guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Follow the development setup below
- Make your changes and add tests
- Ensure all tests pass and code follows PSR-12 standards
- Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
-
Clone the repository
git clone https://github.com/hamoi1/eloquent-encryptable.git cd eloquent-encryptable -
Install dependencies
composer install
-
Set up testing environment
# Copy the example environment file cp .env.example .env -
Create test configuration Create
config/eloquent-encryptable.phpfor testing:<?php return [ 'key' => '[[3,2],[5,7]]', 'previous_key' => '[[2,3],[1,4]]', 'models' => [ 'App\\Models\\TestUser', ], ];
eloquent-encryptable/
βββ src/
β βββ Console/
β β βββ Commands/
β β βββ ReEncryptDataCommand.php
β βββ Rules/
β β βββ EncryptAbleExistRule.php
β β βββ EncryptAbleUniqueRule.php
β βββ Services/
β β βββ EloquentEncryptAbleService.php
β βββ Traits/
β β βββ EncryptAble.php
β βββ EloquentEncryptAbleServiceProvider.php
βββ config/
β βββ eloquent-encryptable.php
βββ composer.json
βββ README.md
When adding new features:
- Create tests first (TDD approach)
- Follow existing patterns in the codebase
- Update documentation in README.md
- Add PHPDoc comments for all public methods
- Consider backward compatibility
This package is open-sourced software licensed under the MIT license.