16

we need to read Cakephp 2 user cookies in Cakephp 3. But it seems like during update, CakeCookie tag was removed from cookies. So each Cakephp cookie is seperate. Regarding to here, Cakephp 3 can read old cookies if they were written with AES. But in old cakephp, default option was cipher and our cookies were written with cipher. So we can't read old cookies now.

It's an option to read old cookies in Cakephp 2 and update them with AES. But when we update to Cakephp 3, there will be users that has Cakephp 2 cookies. So we need to check this inside Cakephp 3.

We're planning that, in cakephp 3, read old cookies with cipher, and write their values to new cookies. We used code from Security cipher method, and created following code.

Problem is, this code works well for strings, but it fails on some of the nested arrays. Problem can be plus sign, or any other encoding issues. Sometimes it works, sometimes it doesn't.

I shared our code to show our process. You can propose another way to convert old cookies.

if (isset($_COOKIE['CakeCookie'])) {
    if (is_array($_COOKIE['CakeCookie'])) {
        foreach ($_COOKIE['CakeCookie'] as $key => $value) {
            $valueDecr=$this->decryptSaltedData($value);
            $this->Cookie->configKey($key, ['expires' => '+60 days']);
            $this->Cookie->write($key, $valueDecr);

            $this->Cookie->delete("CakeCookie[$key]");
            unset($_COOKIE['CakeCookie'][$key]);
            setcookie("CakeCookie[$key]", "aaa", time()-3600, '/');
            setcookie("CakeCookie[$key]", "aaa", time()-3600, '/', '.example.com');
        }
    }
}

public function decryptSaltedData($data) {
    $data2 = substr($data, 8);
    $text = base64_decode($data2);
    $key = Security::salt();

    $cipherSeed='45454545454545454545';
    srand($cipherSeed);

    $out = '';
    $keyLength = strlen($key);
    for ($i = 0, $textLength = strlen($text); $i < $textLength; $i++) {
        $j = ord(substr($key, $i % $keyLength, 1));
        while ($j--) {
            rand(0, 255);
        }
        $mask = rand(0, 255);
        $out .= chr(ord(substr($text, $i, 1)) ^ $mask);
    }
    srand();

    $first = substr($out, 0, 1);
    if ($first === '{' || $first === '[') {
        $decoded = json_decode($out, true);
        if($decoded !== null) $out = $decoded;
    }
    return $out;
}

Solution:

After more tests we found out that the problem exists from a browser extension that changes cookies. So code above works well for converting Cakephp 2 cookies.

floriank
  • 25,546
  • 9
  • 42
  • 66
trante
  • 33,518
  • 47
  • 192
  • 272
  • 2
    You may get (better) answers if you'd add examples of problematic cookies so that people can reproduce the issue. – ndm Jul 25 '15 at 13:36
  • Can you provide a cookie that fails as well as one that does not? Also, is the problem with the decryptSaltedData function or the foreach part? Or both? As far as I know you can put multi dimensional arrays into the values, but I'm not sure how they are encrypted there. Perhaps only the values and not the keys are encrypted like in the base-array? – Canis Jul 29 '15 at 21:17
  • Why not just create a custom component using CakPHP 2 security class? see http://api.cakephp.org/2.7/source-class-Security.html#21-384 for the source code and just grab what you need to be able to decrypt old cipher – Chris Aug 01 '15 at 13:34

0 Answers0