What encryption algorithm is best for encrypting cookies?

后端 未结 13 1042
感动是毒
感动是毒 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:33

    Security Warning: These two functions are not secure. They're using ECB mode and fail to authenticate the ciphertext. See this answer for a better way forward.

    For those reading through wanting to use this method in PHP scripts. Here is a working example using 256bit Rijndael (not AES).

    function encrypt($text, $salt) 
    { 
        return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $salt, $text, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND)))); 
    } 
    
    function decrypt($text, $salt) 
    { 
        return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $salt, base64_decode($text), MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND))); 
    }
    

    Then to save the cookie

    setcookie("PHPSESSION", encrypt('thecookiedata', 'longsecretsalt'));
    

    and to read on the next page:

    $data = decrypt($_COOKIE['PHPSESSION'], 'longsecretsalt');
    
    0 讨论(0)
  • 2020-11-30 17:33

    If you encrypt the cookie, the server still has to decode it to read it (to check for same key), therefore any encrypted cookie is pointless, because if stolen (and un-edited) it will still lead the hacker right to your account. Its just as unsafe as no encrypted at all.

    I believe the real issue of someone stealing your cookie is the connection between the server and client. Use SSL connection provided by your host.

    As for your cookie, you need to make a long random id per user in the database, (have it change every log on) and just set that as the cookie or session. The cookie that contains the key can be checked via php and if it is equal to an account or table in your database, dump the data on the web page like normal.

    0 讨论(0)
  • 2020-11-30 17:36

    While both a very strong ones, AES is a standard.

    As for security of small chunks of data: the smaller - the better. The less encrypted data is exposed, the longer you can use the key. There is always a theoretical limit of how much data can be encrypted within one key of given algorithm without exposing system to risks.

    0 讨论(0)
  • 2020-11-30 17:36

    In addition, I have tried the mcrypt_encrypt and one thing please keep in mind. If you do base64_encode(mcrypt_encrypt(...)).

    and then later, you do base64_decode and output the encrypted data (echo). You probably will be screwed and not seeing anything. However, if you do mcrypt_decrypt( ... base64_decode($value) ). You will see the original data.

    0 讨论(0)
  • 2020-11-30 17:41

    You can achieve what you want securely by using AES in EAX mode. The ciphertext will be larger than the plaintext; that's normal for secure encryption.

    The attacker will of course know the length of your plaintext from the ciphertext, but they shouldn't be able to determine anything else.

    Generate AES keys randomly.

    Be sure and use a fresh nonce for each encryption, and use the "associated data" field to ensure that a thing you encrypted for one purpose isn't presented as being for another (so things like the user name and cookie name could go in there)

    the reactions below push toward: Do not trust encryption to accomplish security.

    More "if you're not an encryption expert you'll underestimate how easy it is to get wrong". For example, AFAICT no-one else in this thread has discussed chaining modes or message integrity, which covers two common beginner's mistakes.

    0 讨论(0)
  • 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.

    <?php
    use \ParagonIE\Halite\Cookie;
    use \ParagonIE\Halite\Symmetric\Key;
    use \ParagonIE\Halite\Symmetric\SecretKey;
    
    // You can also use Key::deriveFromPassword($password, $salt, Key::CRYPTO_SECRETBOX);
    $encryption_key = new SecretKey($some_constant_32byte_string_here);
    
    $cookie = new Cookie($encryption_key);
    
    $cookie->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.

    0 讨论(0)
提交回复
热议问题