14

I am encrypting/decrypting the DB field values in Laravel through accessors and mutators, which is working fine in normal eloquent transactions.

class Person extends Model
{
    use Notifiable;
    protected $table = 'person';

    public function getFirstNameAttribute($value)
    {
        return Crypt::decryptString($value);
    }
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $guarded = array();

    protected function user()
    {
        return $this->belongsTo('App\Models\User', 'useraccount_id', 'id');
    }
}

But the encryption and decryption not working under the following conditions

  1. Eloquent relationships
  2. DB raw queries

Working

$person = Person::find($person_id);
$person->firstName;

Not Working

$user = User::find($user_id);
$user->person->firstName;
7
  • You might want to checkout github.com/delatbabel/elocryptfive Commented Feb 14, 2018 at 11:22
  • Yes I tried that plugin and that too not working Commented Feb 14, 2018 at 11:29
  • How are you calling that method can you show the code please Commented Feb 14, 2018 at 11:32
  • Working ********** $person = Person::find($person_id); $person->firstName; Not Working ************** $user = User::find($user_id); $user->person->firstName; Commented Feb 14, 2018 at 11:42
  • What's the error ? Commented Feb 14, 2018 at 12:02

3 Answers 3

6

You can do it with laravel's Crypt Facades. please follow this example.

use Illuminate\Support\Facades\Crypt;

$encrypted = Crypt::encryptString('Hello world.');

$decrypted = Crypt::decryptString($encrypted);

I implemented from this article link : https://hackthestuff.com/article/laravel6-encryption-and-decryption-model-data-using-crypt-class

Sign up to request clarification or add additional context in comments.

Comments

4

Based on Iman his answer i changed the trait so it works with the casts array from Laravel self.

<?php
namespace App\Library\Traits;

use Illuminate\Support\Facades\Crypt;
trait Encryptable
{
    /**
     * If the attribute is in the encryptable array
     * then decrypt it.
     *
     * @param  $key
     *
     * @return $value
     */
    public function getAttribute($key)
    {
        $value = parent::getAttribute($key);

        if (isset($this->casts[$key]) && $value !== '' && !is_null($value) && $this->casts[$key] == 'encrypt') {
            $value = decrypt($value);
        }
        return $value;
    }
    /**
     * If the attribute is in the encryptable array
     * then encrypt it.
     *
     * @param $key
     * @param $value
     */
    public function setAttribute($key, $value)
    {
        if (isset($this->casts[$key]) && $value !== '' && !is_null($value) && $this->casts[$key] == 'encrypt') {
            $value = encrypt($value);
        }
        return parent::setAttribute($key, $value);
    }
    /**
     * When need to make sure that we iterate through
     * all the keys.
     *
     * @return array
     */
    public function attributesToArray()
    {
        $attributes = parent::attributesToArray();
        foreach ($this->casts as $key => $value) {
            if($value == 'encrypt') {
                if (isset($attributes[$key]) && $attributes[$key] !== '' && !is_null($attributes[$key])) {
                    $attributes[$key] = decrypt($attributes[$key]);
                }
            }
        }
        return $attributes;
    }
}

Comments

0
<?php

namespace App\Traits;

use Illuminate\Support\Facades\Crypt;

trait Encryptable
{
    protected function encryptValue($value)
    {
        $key = env('SALT_KEY'); // Replace this with your actual salt key
        $cipher = 'AES-128-CBC';
        $ivlen = openssl_cipher_iv_length($cipher);
        $iv = openssl_random_pseudo_bytes($ivlen);
        $ciphertext_raw = openssl_encrypt($value, $cipher, $key, OPENSSL_RAW_DATA, $iv);
        $hmac = hash_hmac('sha256', $ciphertext_raw, $key, true);
        $ciphertext = base64_encode($iv . $hmac . $ciphertext_raw);

        return $ciphertext;
    }

    protected function decryptValue($value)
    {
        $key = env('SALT_KEY'); // Replace this with your actual salt key
        $cipher = 'AES-128-CBC';
        $c = base64_decode($value);
        $ivlen = openssl_cipher_iv_length($cipher);
        $iv = substr($c, 0, $ivlen);
        $hmac = substr($c, $ivlen, 32);
        $ciphertext_raw = substr($c, $ivlen + 32);
        $original_plaintext = openssl_decrypt($ciphertext_raw, $cipher, $key, OPENSSL_RAW_DATA, $iv);
        $calcmac = hash_hmac('sha256', $ciphertext_raw, $key, true);

        return hash_equals($hmac, $calcmac) ? $original_plaintext : null;
    }


    public function setAttribute($key, $value)
    {
        if ($this->isEncryptableAttribute($key)) {
            $value = $this->encryptValue($value);
        }

        return parent::setAttribute($key, $value);
    }

    public function getAttribute($key)
    {
        $value = parent::getAttribute($key);

        if ($this->isEncryptableAttribute($key) && !empty($value)) {
            $value = $this->decryptValue($value);
        }

        return $value;
    }

    protected function isEncryptableAttribute($key)
    {
        return in_array($key, $this->encryptable ?? []);
    }
}

First you make the traits with your own salt that is in the .env file named as SALT_KEY for better security and then you can use this trait in your model like this:

 use HasFactory,Encryptable;

    protected $fillable = [
        'name', 'description', 'status',
    ];

    protected $encryptable = ['name','description'];

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.