What encryption algorithm is best for encrypting c

2019-01-08 03:35发布

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 this question:

You should not store any data that needs encrypting in your cookie. Instead, store a good sized (128 bits/16 bytes) random key in the cookie and store the information you want to keep secure on the server, identified by the cookie's key.



I'm looking for information about 'the best' encryption algorithm for encrypting cookies.

I hava the following requirements:

  • It must be fast
    encrypting and decrypting the data will be done for (nearly) every request

  • It will operate on small data sets, typically strings of around 100 character or less

  • It must be secure, but it's not like we're securing banking transactions

  • We need to be able to decrypt the information so SHA1 and the like are out.

Now I've read that Blowfish is fast and secure, and I've read that AES is fast and secure. With Blowfish having a smaller block size.

I think that both algorithms provide more than adequate security? so the speed would then become the decisive factor. But I really have no idea if those algorithm are suited for small character string and if there are maybe better suited algorithm for encrypting cookies.

So my question is:
What encryption algorithm is best for encrypting cookie data?

Update
To be more precise, we want to encrypt 2 cookie: one with session information and the other with 'remeber me' information.

The platform is PHP as apache module on Linux on a VPS.

Update 2
I agree with cletus that storing any information in a cookie is insecure.

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.

So we at least want to encrypt all data in the cookie so that it:
a) malicious users can't read it's contents,
b) malicious users can't fabricate their own cookie or tamper with it.

(All data from cookies is sanitized and checked for validity before we do anything with it, but that's another story)

The session cookie contains a sessionId/timestamp nothing more. It could probably be used without encryption, but I see no harm in encrypting it? (other than computation time).

So given that we have to store some data on in a cookie, what is the best way to encrypt it?

Update 3
The responses to this question made me reconsider the chosen approach. I can indeed do the same without the need for encryption. Instead of encrypting the data, I should only send out data that is meaningless without it's context and cannot be guessed.

However, I'm also at a loss:
I thought that encryption enabled us send data out in to the BigBadWorld™, and still be (fairly) sure that nobody could read or tamper with the it...
Wasn't that the whole point of encryption?

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

What am I missing??

12条回答
倾城 Initia
2楼-- · 2019-01-08 04:03

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.

查看更多
Ridiculous、
3楼-- · 2019-01-08 04:09

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.

查看更多
兄弟一词,经得起流年.
4楼-- · 2019-01-08 04:10

As pointed out a few times in previous comments, you must apply integrity protection to any ciphertext that you send out to the user and accept back. Otherwise the protected data can be modified, or the encryption key recovered.

Especially the PHP world is full of bad examples that ignore this (see PHP cryptography - proceed with care) but this does apply to any language.

One of few good examples I've seen is PHP-CryptLib which uses combined encryption-authentication mode to do the job. For Python pyOCB offers similar functionality.

查看更多
孤傲高冷的网名
5楼-- · 2019-01-08 04:11

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.

查看更多
Root(大扎)
6楼-- · 2019-01-08 04:12

Why do you want to encrypt the cookie?

As I see it, there are two cases: either you give the client the key, or you don't.

If you don't give the key to the client, then why are you giving them the data? Unless you're playing some weird game with breaking weak encryption (which you're explicitly not), you might as well store the data on the server.

If you do hand the client the key, then why do you encrypt it in the first place? If you don't encrypt the communication of the key, then encrypting the cookie is moot: a MITM can look at the cookie and send you any cookie he wants. If you use an encrypted channel to the client, why the extra overhead of encrypting the stored data?

If you're worried about other users on the client's machine reading the cookie, give up and assume the browser sets good permission bits :)

查看更多
倾城 Initia
7楼-- · 2019-01-08 04:13

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');
查看更多
登录 后发表回答