What’s behind Laravel Encryption/Decryption

Image for post
Image for post

My system is safe, it uses encryption.

Laravel encryption/decryption fundamentals

$encrypter = new Illuminate\Encryption\Encrypter('1234567812345678', 'AES-128-CBC');$encrypted = $encrypter->encrypt('Hello world');dump($encrypted);// prints something similar to "eyJpdiI6ImdMd2dWcW5jMXBrUDBranRJZXQ5MEE9PSIsInZhbHVlIjoiNnhTODBSclB3ZVp3SFRRUWFWTHpReFQwYWQ1aXVmTmhXOXV5WHM2TzR1WT0iLCJtYWMiOiIwODQyZDhiMzZlNDQwZTZjYTRiYmI2MGE0MTgzNzk5NGNkZTU1Yzc5NDIyYzdjYmYwNzk2ZTA5MGNjYjc4MGYzIn0="$decrypted = $encoder->decrypt($encrypted);dump($decrypted); // prints "Hello world" again

How encrpytion works

What’s in the result?

$encrypted = $encrypter->encrypt('Hello world');$decodedEncrypted = base64_decode($encrypted);
{   
"iv":"gLwgVqnc1pkP0kjtIet90A==",
"value":"6xS80RrPweZwHTQQaVLzQxT0ad5iufNhW9uyXs6O4uY=",
"mac":"0842d8b36e440e6ca4bbb60a41837994cde55c79422c7cbf0796e090cc"
}

How encryption works — looking at the code

public function encrypt($value, $serialize = true)
{
$iv = random_bytes(openssl_cipher_iv_length($this->cipher));
$value = \openssl_encrypt(
$serialize ? serialize($value) : $value,
$this->cipher, $this->key, 0, $iv
);
if ($value === false) {
throw new EncryptException('Could not encrypt the data.');
}
$mac = $this->hash($iv = base64_encode($iv), $value); $json = json_encode(compact('iv', 'value', 'mac'), JSON_UNESCAPED_SLASHES); if (json_last_error() !== JSON_ERROR_NONE) {
throw new EncryptException('Could not encrypt the data.');
}
return base64_encode($json);
}
protected function hash($iv, $value)
{
return hash_hmac('sha256', $iv.$value, $this->key);
}

How decryption works — in depth

public function decrypt($payload, $unserialize = true)
{
$payload = $this->getJsonPayload($payload);
$iv = base64_decode($payload['iv']);// Here we will decrypt the value. If we are able to successfully decrypt it
// we will then unserialize it and return it out to the caller. If we are
// unable to decrypt this value we will throw out an exception message.
$decrypted = \openssl_decrypt(
$payload['value'], $this->cipher, $this->key, 0, $iv
);
if ($decrypted === false) {
throw new DecryptException('Could not decrypt the data.');
}
return $unserialize ? unserialize($decrypted) : $decrypted;
}

Why is it secure?

$encrypted2 = $encrypter->encrypt('Hello hacker');$decodedEncrypted2 = json_decode(base64_decode($encrypted2), true);dump('DECODED ENCRYPTED 2: ');
var_dump($decodedEncrypted2);
// swapping the ciphered data and try to decipher
try {
$tampered = $decodedEncrypted;
$tampered['value'] = $decodedEncrypted2['value'];
$encrypter->decrypt(base64_encode(json_encode($tampered)));
} catch (\Illuminate\Contracts\Encryption\DecryptException $exception) {
dump($exception->getMessage());
}
// swapping the iv and try to decipher
try {
$tampered = $decodedEncrypted;
$tampered['iv'] = $decodedEncrypted2['iv'];
$encrypter->decrypt(base64_encode(json_encode($tampered)));
} catch (\Illuminate\Contracts\Encryption\DecryptException $exception) {
dump($exception->getMessage());
}
// swapping the MAC and try to decipher
try {
$tampered = $decodedEncrypted;
$tampered['mac'] = $decodedEncrypted2['mac'];
$encrypter->decrypt(base64_encode(json_encode($tampered)));
} catch (\Illuminate\Contracts\Encryption\DecryptException $exception) {
dump($exception->getMessage());
}

Conclusion

Written by

Ph.D. in computer science, from Palermo, Italy. Involved in all kind of technological stuffs, both sw and hw, applied to a wide range of fields.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store