Does Security:cipher encrypted result depend on the server?

427 views Asked by At

I'm working in a cakephp application where I use Security::cipher in order to encrypt some data. It works perfectly but I've moved files and DB to another server and now the encrypted result is different. I've tried with some simple lines:

$security = new Security;
$code = $security->cipher('1234', Configure::read('Security.cipherSeed'));

When I print $code, the value is different in both servers. I've configured the same Security.cipherSeed in both core.php files. Is Security::cipher function using some server value to encrypt?

Thank you.

1

There are 1 answers

2
ircmaxell On BEST ANSWER

Well, looking at this bug, it does appear to be an issue.

Digging into the source code, this line is what makes it work:

srand(Configure::read('Security.cipherSeed'));

Now, why does that work? Because rand() implements a pseudo-random algorithm. So for any given known seed, you can theoretically produce the same series of random output. To see if this will work, let's look at the PHP source code for rand(), specifically the internal php_rand function:

PHPAPI long php_rand(TSRMLS_D)
{
    long ret;

    if (!BG(rand_is_seeded)) {
            php_srand(GENERATE_SEED() TSRMLS_CC);
    }

We know this isn't the problem, since we're manually seeding (unless we have the suhosin patch installed on the server, then it will always reseed and hence not work).

#ifdef ZTS
    ret = php_rand_r(&BG(rand_seed));
#else
# if defined(HAVE_RANDOM)
    ret = random();
# elif defined(HAVE_LRAND48)
    ret = lrand48();
# else
    ret = rand();
# endif
#endif

Woah, did you see what happened? Depending on the server specification, is can use one of 4 different random libraries (rand(), random(), lrand48() or it's own internal random function php_rand_r)! That's why it's not portable across server installs.

Instead, use a real encryption library such as MCrypt or GPG.

Edit: I've submitted a bug report on this topic to cake.