What encryption algorithm is best for encrypting cookies?

后端 未结 13 1058
感动是毒
感动是毒 2020-11-30 17:29

Since this question is rather popular, I thought it useful to give it an update.

Let me emphasise the correct answer as given by AviD to

13条回答
  •  时光取名叫无心
    2020-11-30 17:42

    Fast, Encrypted Cookies with Libsodium

    If you need fast, secure encrypted cookies in PHP, check out how Halite implements them. Halite relies on the libsodium PECL extension to provide secure cryptography.

    store('index', $any_value);
    $some_value = $cookie->fetch('other_index');
    

    If you cannot install PECL extensions, ask your sysadmin or hosting provider to do it for you. If they refuse, you still have options.


    Secure Encrypted Cookies in PHP, Hold the Salt Please

    The other answers instruct you to encrypt your data with openssl or mcrypt, but they're missing a crucial step. If you want to safely encrypt data in PHP, you must authenticate your messages.

    Using the OpenSSL extension, the process you would need to follow looks like this:


    Preamble

    • (Before you even think about encryption) Generate a 128-bit, 192-bit, or 256-bit random string. This will be your master key.

      Do not use a human-readable password. If you, for some reason, must use a human-readable password, ask Cryptography SE for guidance.

      If you need special attention, my employer offers technology consulting services, including development of cryptography features.

    Encryption

    1. Generate a random Initialization Vector (IV) or nonce. e.g. random_bytes(openssl_cipher_iv_length('aes-256-cbc'))
    2. Use HKDF or a similar algorithm for splitting your master key into two keys:
      1. An encryption key ($eKey)
      2. An authentication key ($aKey)
    3. Encrypt your string with openssl_encrypt() with your IV and an appropriate modate (e.g. aes-256-ctr) using your encryption key ($eKey) from step 2.
    4. Compute an authentication tag of your ciphertext from step 3, using a keyed hash function such as HMAC-SHA256. e.g. hash_hmac('sha256', $iv.$ciphertext, $aKey). It's very important to authenticate after encryption, and to encapsulate the IV/nonce as well.
    5. Package the authentication tag, IV or nonce, and ciphertext together and optionally encode it with bin2hex() or base64_encode(). (Warning: This approach might leak cache-timing information.)

    Decryption

    1. Split your key, as per step 2 in encryption. We need the same two keys during decryption!
    2. (Optionally, decode and) unpack the MAC, IV, and ciphertext from the packed message.
    3. Verify the authentication tag by recalculating the HMAC of the IV/nonce and ciphertext with the user-provided HMAC by using hash_equals().
    4. If and only if step 3 passes, decrypt the ciphertext using $eKey.

    If you want to see how this all looks together, see this answer which has sample code.

    If this sounds like too much work, use defuse/php-encryption or zend-crypt and call it a day.


    Remember Me Cookies

    However, we have a requirement to implement a 'remeber me' feature. The accepted way to go about this is by setting a cookie. If the client presents this cookie, he or she is allowed access the system with (almost) equal rights as if he/she presented the valid username password combination.

    Encryption is actually not the correct tool for this job. You want to follow this process for secure remember me cookies in PHP:

    Generating a Remember Me Token

    1. Generate two random strings:
      1. A selector which will be used for database lookups. (The purpose of a random selector instead of just a sequential ID is to not leak how many active users are on your website. If you're comfortable leaking this information, feel free to just use a sequential ID.)
      2. A validator which will be used to authenticate the user automatically.
    2. Calculate a hash of validator (a simple SHA-256 hash will suffice).
    3. Store the selector and the hash of the validator in a database table reserved for automatic logins.
    4. Store the selector and validator in a cookie on the client.

    Redeeming a Remember Me Token

    1. Split the incoming cookie into the selector and validator.
    2. Perform a database lookup (use prepared statements!) based on selector.
    3. If a row is found, calculate a hash of the validator.
    4. Compare the hash calculated in step 3 with the hash stored in the database, once again using hash_equals().
    5. If step 4 returns true, log the user in to the appropriate account.

    This is the strategy that Gatekeeper adopted for long-term user authentication and it is the most secure strategy proposed to date for satisfying this requirement.

提交回复
热议问题