Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Aescrypt Laravel Package

dolphiq/laravel-aescrypt

dolphiq/laravel-aescrypt brings AES Crypt compatible file encryption to Laravel. It offers straightforward facades and helpers to encrypt or decrypt files using AES-256, making secure, standards-compatible file storage easy to add to any Laravel application.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install and publish config

    composer require dolphiq/laravel-aescrypt
    php artisan vendor:publish --tag=aescrypt-config
    

    The package is a thin wrapper around MySQL's AES_ENCRYPT / AES_DECRYPT, so the first thing to verify is the key and cipher in config/aescrypt.php. Put the key in .env (AESCRYPT_KEY=...) and never commit it — the whole point is that ciphertext is useless without it.

  2. Make the columns binary-safe. Encrypted output is raw binary. Use VARBINARY (preferred) or BLOB/TEXT, not VARCHAR with a utf8 collation. Leave headroom for block padding:

    $table->binary('ssn')->nullable();      // or $table->string('ssn') is wrong
    

    If you are adding encryption to an existing table, plan a migration + backfill rather than an in-place column type change on a large table.

  3. Attach the trait to the model and declare which attributes are encrypted (confirm the exact property/trait names against the README — the concept is the same across versions):

    use Dolphiq\AesCrypt\Traits\AesCrypt;
    
    class Customer extends Model
    {
        use AesCrypt;
    
        protected $encryptable = ['ssn', 'phone'];
    }
    

    The trait hooks getAttribute/setAttribute, so $customer->ssn = '123-45-6789' writes ciphertext and reading it back returns plaintext.

  4. First realistic use case: you have PII (SSNs, phone numbers, medical notes) that must be encrypted at rest, and you still want to be able to query it from SQL — reporting, support tooling, or an admin search screen. That is the niche this package fills; it is not a drop-in replacement for Laravel's encrypted cast.

  5. Where to look first, in order: the README's query examples → config/aescrypt.php → the trait source (getAttribute, setAttribute, any query scope) → your MySQL version (SELECT VERSION()). The MySQL version matters more than you think (see Gotchas).

Implementation Patterns

Basic CRUD is transparent. Create, update, and read work through Eloquent as normal:

$customer = Customer::create([
    'name' => 'Jane Doe',
    'ssn'  => '123-45-6789',   // encrypted on save
]);

echo $customer->ssn;           // decrypted on read

Querying encrypted columns. You cannot do where('ssn', $value) — the column holds ciphertext. Use the DB function, ideally through whatever scope the trait provides:

Customer::whereRaw('AES_DECRYPT(ssn, ?) = ?', [config('aescrypt.key'), $ssn])->first();

Be explicit that this is a full table scan. For any table that grows past a few thousand rows, add a deterministic blind-index column and query that instead:

// migration
$table->string('ssn_hash', 64)->index();

// model
$customer->ssn_hash = hash_hmac('sha256', $ssn, config('aescrypt.index_key'));

Then where('ssn_hash', hash_hmac(...)) uses the index, and you only fall back to AES_DECRYPT for display.

Partial search / admin filters. AES_DECRYPT(col, key) LIKE ? works but is the worst-case query. Push these to a read replica or an offline export job, and cap result sets. For fuzzy matching, decrypt in a queued job into a search index rather than hitting MySQL per keystroke.

Reporting and exports. Use selectRaw to decrypt only the columns you need:

Customer::select('id', 'name')
    ->selectRaw('AES_DECRYPT(ssn, ?) as ssn', [config('aescrypt.key')])
    ->get();

Never SELECT * into a CSV dump without decrypting deliberately — you will hand someone raw binary.

Validation and form requests operate on plaintext before the model sees it, so Rule::unique('customers', 'ssn') will silently fail (it compares plaintext against ciphertext). Swap it for a hash-column check.

Key rotation. Store a key_version column per row, keep the old key in config, and decrypt with the row's version. Re-encrypt lazily on read/write in a job, then drop the old key. Doing it in one ALTER/mass update is a maintenance window you don't want.

Serialization. Check toArray()/JSON resources explicitly in a test. The trait usually handles attributesToArray, but if you have custom $appends or accessors that read the raw attribute, you'll leak base64/binary into API responses.

Gotchas and Tips

  • MySQL only. Tests running on SQLite or Postgres will error out (no such function: AES_ENCRYPT). Configure a MySQL service container in CI, or mock the trait in feature tests. Do not let this slip into phpunit.xml defaults.

  • MySQL version drift. AES_ENCRYPT changed key handling in MySQL 5.6.17; data encrypted on an older server may be undecryptable on a newer one. Pin your server version and document it.

  • It's ECB mode, no IV, no authentication. MySQL's AES_ENCRYPT is deterministic and unauthenticated. Identical plaintexts produce identical ciphertext, and tampering isn't detected. This is acceptable for "encrypted at rest against a stolen disk/dump" — it is not equivalent to Laravel's encrypted cast, which uses AES-256-CBC with a MAC. Don't use this for secrets where integrity matters.

  • The key shows up in query logs. Any whereRaw/selectRaw with the key bound in leaks it into the general log, slow query log, performance_schema, Telescope, Debugbar, and DB::listen output. Disable those in production, or accept that anyone with log access has the key. This is the single biggest operational risk of the package.

  • Eloquent bypasses. These skip mutators entirely and write plaintext:

    • DB::table('customers')->insert(...)
    • Customer::where(...)->update([...])
    • upsert, insertOrIgnore
    • raw SQL in migrations/seeders

    Grep your codebase for these on encrypted tables. Seeders are the usual culprit.

  • updateOrCreate/firstOrCreate silently duplicate. The lookup where('ssn', ...) compares plaintext to ciphertext and returns nothing, so you insert a second row. Use the hash column for the match.

  • Cast conflicts. Don't put Laravel's 'encrypted' cast on the same attribute as the trait — it'll double-encrypt. Also watch ordering with array/json casts: the trait must decrypt to a string before the cast decodes it.

  • Column sizing. MySQL pads to the AES block size (16 bytes), so a 9-byte SSN can occupy 16+ bytes. Size VARBINARY generously (e.g. VARBINARY(255)) or you'll get silent truncation on longer plaintexts.

  • Debugging. From the MySQL client, SELECT HEX(ssn) FROM customers LIMIT 1; confirms you're storing binary, and SELECT AES_DECRYPT(ssn, 'key') FROM customers; confirms the key is right. If you see base64 garbage, your column is VARCHAR with a charset and MySQL mangled it.

  • Backups. Dumps contain ciphertext but the key lives in .env. Back up the key in a separate secret store — losing it means losing the data, with no recovery path.

  • Extension points. If the trait's query helpers don't fit, override getAttribute/setAttribute in a base model, or wrap the whereRaw call in a local scope (scopeWhereEncrypted) so the key binding lives in one place. That scope is also the right place to swap in the hash-index path later.

  • Queues are generally fine with SerializesModels (the job stores the model ID and reloads it), but if you serialize the model manually or pass plaintext PII in a job payload, that plaintext sits in your jobs table in the clear.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package