3

I'm using Laravel 5, and for a project, for which one of the tenants is that emails stored in the system must be encrypted. I am using Laravel 5's Crypt:: facade, and the relevant encrypt() and decrypt() methods.

The problem lies in that the encrypted value seems to differ, even if given the same string. At first I thought it could be to do with VARCHAR field max lengths, however both the hash values come back under the 255 length set on the field.

Take for example, this dump;

PHP

    $hash1 = 'eyJpdiI6InJFNTFkdktpVU9cL1wvRTJPVk94SURiUT09IiwidmFsdWUiOiJIZVh4Y1NyUGpVcTVFVTNSbWdUNnJCUWRHSGZTcnFTQWJKa1h0Q1wvMEVtZnFuM3dDeFwvXC9hdUs4enFXXC94dEJ0cSIsIm1hYyI6IjFjNjZjODFjMjI5NTQ0NmVhZDUwODQzODE0OTQ4NTdjMzAxNTQ5Y2ZjY2M4YzRiODU0ZjIwNDhmMDA0Yjc4OWQifQ';
    $hash2 = 'eyJpdiI6ImRBVWNKVTlJZVFmckk2T0c4cXNObFE9PSIsInZhbHVlIjoidElqcE5TMUFwVHZXeW12R3hKMFVFWlR0WmgxOFRBbW5cL2V3dUJ6VndsdktLYjVGR2JQQWpSUUNUWDBJbU5OQWEiLCJtYWMiOiI3MjM3ODNiMzc0NDJlNDVhYzFkOTBmMjhhOTk0MTUyM2FlNzM5ZGE4ODE3MTJlMDM5NWZiMzViZjM5OTA0MGRhIn0=';
    $dump = [
    'hash1' => $hash1,
    'hash2' => $hash2,
    'string1' => Crypt::decrypt($hash1),
    'string2' => Crypt::decrypt($hash2)
    ];
    return $dump;

Dumped Object

hash1: "eyJpdiI6InJFNTFkdktpVU9cL1wvRTJPVk94SURiUT09IiwidmFsdWUiOiJIZVh4Y1NyUGpVcTVFVTNSbWdUNnJCUWRHSGZTcnFTQWJKa1h0Q1wvMEVtZnFuM3dDeFwvXC9hdUs4enFXXC94dEJ0cSIsIm1hYyI6IjFjNjZjODFjMjI5NTQ0NmVhZDUwODQzODE0OTQ4NTdjMzAxNTQ5Y2ZjY2M4YzRiODU0ZjIwNDhmMDA0Yjc4OWQifQ"
hash2: "eyJpdiI6ImRBVWNKVTlJZVFmckk2T0c4cXNObFE9PSIsInZhbHVlIjoidElqcE5TMUFwVHZXeW12R3hKMFVFWlR0WmgxOFRBbW5cL2V3dUJ6VndsdktLYjVGR2JQQWpSUUNUWDBJbU5OQWEiLCJtYWMiOiI3MjM3ODNiMzc0NDJlNDVhYzFkOTBmMjhhOTk0MTUyM2FlNzM5ZGE4ODE3MTJlMDM5NWZiMzViZjM5OTA0MGRhIn0="
string1: "[email protected]"
string2: "[email protected]"

Dots are inputted in place of characters for privacy, but they are exactly the same. The only other thing I can possibly think about is maybe some kind of charset formatting?

Any help resolving this would be greatly appreciated!

Regards.

6
  • 1
    Wait, what's the issue then if the decrypted hashes end up being identical? Commented Apr 8, 2015 at 15:19
  • If the key is different, then the encrypted value will be different; and the keys shouldn't always be the same otherwise it becomes predictable and easily breakable. That's the whole point Commented Apr 8, 2015 at 15:21
  • @MarkBaker Apologies, I don't know much about encryption in general - I thought that the same value would be given both ways. The point was that these values had to be stored in a database table, but be a retrieval point for rows of data, I'll have to figure out another more feasible method now :). Commented Apr 8, 2015 at 15:27
  • Can you post your current query? Why can't you select the value using a different column? Commented Apr 8, 2015 at 15:37
  • 'SELECT * FROM users WHERE email = '#hashvalue' LIMIT 1 is effectively it, although using Laravel's Eloquent ORM. It's for password resetting, so the only viable option to guarantee that an email with a password reset token is sent to the right email address, is to match the user inputted email address against the email value. I have just tried to use bcrypt(), which from what I understand, is one way encryption, but the results still remain the same. Commented Apr 8, 2015 at 16:09

1 Answer 1

5

If I understand your question, it's why does the encrypted results differ, even with the same input and the same key?

(You mention these being hashes, but Crypt::encrypt() and decrypt() are for symmetric encryption)

Laravel Crypt uses CBC mode by default. That means it generates a random IV every time you encrypt something, to ensure the output is always different.

Without using a mode like CBC, you risk leaking information. If I know that [email protected] always encrypts to eyJpdiI6InJFNTFkdktpVU9cL1wvRTJPVk94SURiUT09IiwidmFsdWUiOiJIZVh4Y1NyUGpVcTVFVTNSbWdUNnJCUWRHSGZTcnFTQWJKa1h0Q1wvMEVtZnFuM3dDeFwvXC9hdUs4enFXXC94dEJ0cSIsIm1hYyI6IjFjNjZjODFjMjI5NTQ0NmVhZDUwODQzODE0OTQ4NTdjMzAxNTQ5Y2ZjY2M4YzRiODU0ZjIwNDhmMDA0Yjc4OWQifQ, then even without knowing your encryption key, I still know something about your messages (who it's being sent to, for example).

You can see a great example of the risk here.

Edit: If this is for password storage, you should not be using encrypt() and decrypt(). You should use bcrypt() or PBKDF2. Otherwise, assuming a compromise, an attacker could just decrypt all your users passwords.

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

1 Comment

Laravel's Hash facade has a convenient make method, so you just call Hash::make($string) when you want to generate e.g. a password for a User. That's also what the built-in Auth class uses to check passwords on submit.

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.