Search code examples
phpencryptionlaravelutf-8mcrypt

Error trying to store encrypted string in Laravel


I am implementing a reversible encryption algorithm based on an example at http://www.edzynda.com/create-a-self-destructing-encrypted-message-app-in-laravel-part-1/

I have put the code inside a model event function:

public static function boot()
{
    parent::boot();

    // Setup event bindings...

    static::creating(function($account)
    {
        /* encrypt password and save iv */
        $encryption = self::encrypt($account->db_password);  // or: Input::get('db_password')
        $account->db_password = $encryption['encrypted_string'];
        $account->iv = $encryption['iv'];

        Log::debug($account);

        //print_r ($encryption);

    });


}

public static function encrypt($string) 
{
    // Generate an IV
    $iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_CFB);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_DEV_URANDOM);


    // Encrypt the string
    $encrypted_string = mcrypt_encrypt(MCRYPT_BLOWFISH, $_ENV['ACCOUNT_KEY'], $string, MCRYPT_MODE_CFB, $iv);

    return ['encrypted_string' => $encrypted_string, 'iv' => $iv];
}

In my database seeder, I am calling Model::create to make the string is encrypted before saving. This is called from my tests. However, I am getting

  [ErrorException]
  json_encode(): Invalid UTF-8 sequence in argument

I've made sure that the column type is binary.

Extra info: when I perform mb_detect_encoding on either value ($iv or $string) I get either UTF-8, or nothing, I guess depending not the random characters that appear in the result.


Solution

  • My solution: for storage and transportation, the encrypted string and IV need to be base64 encoded.

    The relevant line above changed to:

    return [
                'encrypted_string' => base64_encode($encrypted_string), 
                'iv' => base64_encode($iv)
            ];
    

    and of course base64_decode must be used before decrypting the string with the stored IV value.