Skip to content

Hamoi1/eloquent-encryptable

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

31 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ” Eloquent Encryptable

Laravel PHP Hill Cipher

A powerful Laravel package for encrypting Eloquent model attributes using the Hill Cipher algorithm with multi-language support.

License Version Laravel Version


✨ Features

  • πŸ”’ 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

πŸ“‹ Table of Contents


πŸš€ Installation

Install the package via Composer:

composer require hamoi1/eloquent-encryptable

Publish the configuration file:

php artisan vendor:publish --provider="Hamoi1\EloquentEncryptAble\EloquentEncryptAbleServiceProvider" --tag="config"

βš™οΈ Configuration

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,
    ],
];

πŸ”‘ Key Matrix Requirements

  • 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]]'

πŸ“– Usage

Basic Usage

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)

Validation Rules

The package provides custom validation rules for encrypted fields:

Unique Rule

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
            ])
        ],
    ];
}

Exists Rule

Validate that encrypted field value exists:

use Hamoi1\EloquentEncryptAble\Rules\EncryptAbleExistRule;

public function rules()
{
    return [
        'parent_phone' => [
            'required',
            new EncryptAbleExistRule('users', 'phone')
        ],
    ];
}

Blade Directives

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>

Console Commands

Re-encrypt Data

When rotating encryption keys, use the console command to re-encrypt existing data:

php artisan eloquent-encryptable:re-encrypt

This command will:

  1. Load models from the configuration
  2. Decrypt data using the previous key
  3. Re-encrypt using the new key
  4. Show progress bars and timing information
  5. Process data in chunks for memory efficiency

πŸ”§ Advanced Usage

Manual Encryption/Decryption

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);

Batch Operations

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);

Custom Key Matrix Generation

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
}

πŸ“š API Reference

EncryptAble Trait

Method Description
bootEncryptAble() Automatically encrypts/decrypts model attributes

EloquentEncryptAbleService

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

Validation Rules

Rule Constructor Parameters Description
EncryptAbleUniqueRule $table, $column, $except = [] Validates uniqueness of encrypted field
EncryptAbleExistRule $table, $column, $except = [] Validates existence of encrypted field

πŸ” Troubleshooting

Common Issues

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;

Debug Mode

Enable debug logging by adding to your model:

protected static function bootEncryptAble()
{
    parent::bootEncryptAble();
    
    if (config('app.debug')) {
        \Log::info('Encrypting model: ' . static::class);
    }
}

🀝 Contributing

We welcome contributions! Please follow these guidelines:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Follow the development setup below
  4. Make your changes and add tests
  5. Ensure all tests pass and code follows PSR-12 standards
  6. Commit your changes (git commit -m 'Add amazing feature')
  7. Push to the branch (git push origin feature/amazing-feature)
  8. Open a Pull Request

Development Setup

  1. Clone the repository

    git clone https://github.com/hamoi1/eloquent-encryptable.git
    cd eloquent-encryptable
  2. Install dependencies

    composer install
  3. Set up testing environment

    # Copy the example environment file
    cp .env.example .env
  4. Create test configuration Create config/eloquent-encryptable.php for testing:

    <?php
    return [
        'key' => '[[3,2],[5,7]]',
        'previous_key' => '[[2,3],[1,4]]',
        'models' => [
            'App\\Models\\TestUser',
        ],
    ];

Project Structure

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

Adding New Features

When adding new features:

  1. Create tests first (TDD approach)
  2. Follow existing patterns in the codebase
  3. Update documentation in README.md
  4. Add PHPDoc comments for all public methods
  5. Consider backward compatibility

πŸ“„ License

This package is open-sourced software licensed under the MIT license.

About

encrypt and decrypt model fields using the Hill Cipher algorithm in your Laravel application

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages