novay/kunci-sql

Seamless encryption for Laravel Eloquent models using Kunci.

1.0 2025-08-12 18:57 UTC

This package is auto-updated.

Last update: 2025-08-12 18:58:35 UTC


README

A Laravel package for automatic database column encryption with support for deterministic encryption to enable searchable encrypted fields. Makes Eloquent models encrypt attributes transparently without manual query changes. It works transparently through your Eloquent models.

Key Features

  • Automatic encryption when saving encrypted attributes.
  • Automatic decryption when accessing encrypted attributes.
  • Support for deterministic encryption (encryptDeterministic) on searchable columns for consistent searching.
  • Automatic query builder modification to support encrypted searches.
  • Artisan commands for re-encrypting and re-decrypting encrypted columns.
  • Easily integrates with Eloquent models using a trait.

Installation

Install the package using Composer:

composer require novay/kunci-sql

After installation, apply the HasEncryptedAttributes trait to any model you want to encrypt:

use Novay\KunciSql\Traits\HasEncryptedAttributes;

class Todo extends Model
{
    use HasEncryptedAttributes;

    // Define the attributes to be encrypted
    protected array $encrypted = [
        'description' => ['searchable' => true], # Deterministic encryption for searching columns
        'secret_note' # Standard encryption
    ];
}

Usage

Defining encrypted attributes

Add the $encrypted property to your model using the following format:

protected array $encrypted = [
    'field_name' => [], # Regular encryption
    'searchable_field' => ['searchable' => true], # Deterministic encryption for searchable columns
];

Note: Deterministic encryption produces the same ciphertext for the same plaintext. This enables exact-match searching, but it can be a security risk if used on highly sensitive data with low cardinality.

Automatic encryption/decryption

  • When you save a model, all attributes listed in the $encrypted property will be automatically encrypted.
  • When you access these attributes, they will be automatically decrypted before being returned.

Automatic searchable queries with deterministic encryption

With deterministic encryption, you can perform searches with a where clause as you normally would. Kunci-SQL will encrypt the search value behind the scenes.

Example:

// Behind the scenes, the search value will be encrypted deterministically
$results = Todo::where('description', 'Todo 1')->get();

If description is marked with searchable => true, the search will work with deterministic ciphertext matching.

Important: Currently, operators like LIKE are not supported for searchable columns, as deterministic encryption only works for exact-value matching.

Artisan Commands

To manage existing data, you can use the following Artisan commands:

Re-encrypt Data

This command will re-encrypt the data in the specified column.

php artisan kunci-sql:re-encrypt {table} {column} [--searchable]

Example:

# Re-encrypts the 'description' column in the 'todo' table with deterministic encryption
php artisan kunci-sql:re-encrypt todo description --searchable

Re-decrypt Data

This command will re-decrypt the data in the specified column.

php artisan kunci-sql:re-decrypt {table} {column}

Configuration

  • Use the --searchable flag on commands to specify columns using deterministic encryption.
  • Ensure your encryption key configuration in config/kunci-sql.php is set properly.

HasEncryptedAttributes Trait

This trait is the core of the Kunci-SQL package. It is responsible for:

  • getAttribute($key) Automatically decrypting values when they are accessed.
  • setAttribute($key, $value) Automatically encrypting values when they are set.

Complete Model Example

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Novay\KunciSql\Traits\HasEncryptedAttributes;

class Todo extends Model
{
    use HasEncryptedAttributes;

    protected $table = 'todo';

    protected $fillable = ['description', 'done'];

    protected array $encrypted = [
        'description' => ['searchable' => true],
    ];
}

License

This package is licensed under the MIT License.