1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org) |
4
|
|
|
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) |
5
|
|
|
* |
6
|
|
|
* Licensed under The MIT License |
7
|
|
|
* For full copyright and license information, please see the LICENSE.txt |
8
|
|
|
* Redistributions of files must retain the above copyright notice. |
9
|
|
|
* |
10
|
|
|
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) |
11
|
|
|
* @link http://cakephp.org CakePHP(tm) Project |
12
|
|
|
* @since 3.1.6 |
13
|
|
|
* @license http://www.opensource.org/licenses/mit-license.php MIT License |
14
|
|
|
*/ |
15
|
|
|
namespace Cake\Utility; |
16
|
|
|
|
17
|
|
|
use RuntimeException; |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* Cookie Crypt Trait. |
21
|
|
|
* |
22
|
|
|
* Provides the encrypt/decrypt logic for the CookieComponent. |
23
|
|
|
* |
24
|
|
|
* @link http://book.cakephp.org/3.0/en/controllers/components/cookie.html |
25
|
|
|
*/ |
26
|
|
|
trait CookieCryptTrait |
27
|
|
|
{ |
28
|
|
|
/** |
29
|
|
|
* Valid cipher names for encrypted cookies. |
30
|
|
|
* |
31
|
|
|
* @var array |
32
|
|
|
*/ |
33
|
|
|
protected $_validCiphers = ['aes', 'rijndael']; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* Returns the encryption key to be used. |
37
|
|
|
* |
38
|
|
|
* @return string |
39
|
|
|
*/ |
40
|
|
|
abstract protected function _getCookieEncryptionKey(); |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* Encrypts $value using public $type method in Security class |
44
|
|
|
* |
45
|
|
|
* @param string $value Value to encrypt |
46
|
|
|
* @param string|bool $encrypt Encryption mode to use. False |
47
|
|
|
* disabled encryption. |
48
|
|
|
* @param string|null $key Used as the security salt only in this time for tests if specified. |
49
|
|
|
* @return string Encoded values |
50
|
|
|
*/ |
51
|
|
|
protected function _encrypt($value, $encrypt, $key = null) |
52
|
|
|
{ |
53
|
|
|
if (is_array($value)) { |
54
|
|
|
$value = $this->_implode($value); |
55
|
|
|
} |
56
|
|
|
if ($encrypt === false) { |
57
|
|
|
return $value; |
58
|
|
|
} |
59
|
|
|
$this->_checkCipher($encrypt); |
|
|
|
|
60
|
|
|
$prefix = "Q2FrZQ==."; |
61
|
|
|
$cipher = null; |
62
|
|
|
if (!isset($key)) { |
63
|
|
|
$key = $this->_getCookieEncryptionKey(); |
64
|
|
|
} |
65
|
|
|
if ($encrypt === 'rijndael') { |
66
|
|
|
$cipher = Security::rijndael($value, $key, 'encrypt'); |
67
|
|
|
} |
68
|
|
|
if ($encrypt === 'aes') { |
69
|
|
|
$cipher = Security::encrypt($value, $key); |
70
|
|
|
} |
71
|
|
|
return $prefix . base64_encode($cipher); |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
/** |
75
|
|
|
* Helper method for validating encryption cipher names. |
76
|
|
|
* |
77
|
|
|
* @param string $encrypt The cipher name. |
78
|
|
|
* @return void |
79
|
|
|
* @throws RuntimeException When an invalid cipher is provided. |
80
|
|
|
*/ |
81
|
|
|
protected function _checkCipher($encrypt) |
82
|
|
|
{ |
83
|
|
|
if (!in_array($encrypt, $this->_validCiphers)) { |
84
|
|
|
$msg = sprintf( |
85
|
|
|
'Invalid encryption cipher. Must be one of %s.', |
86
|
|
|
implode(', ', $this->_validCiphers) |
87
|
|
|
); |
88
|
|
|
throw new RuntimeException($msg); |
89
|
|
|
} |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* Decrypts $value using public $type method in Security class |
94
|
|
|
* |
95
|
|
|
* @param array $values Values to decrypt |
96
|
|
|
* @param string|bool $mode Encryption mode |
97
|
|
|
* @return string decrypted string |
98
|
|
|
*/ |
99
|
|
|
protected function _decrypt($values, $mode) |
100
|
|
|
{ |
101
|
|
|
if (is_string($values)) { |
102
|
|
|
return $this->_decode($values, $mode); |
|
|
|
|
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
$decrypted = []; |
106
|
|
|
foreach ($values as $name => $value) { |
107
|
|
|
$decrypted[$name] = $this->_decode($value, $mode); |
|
|
|
|
108
|
|
|
} |
109
|
|
|
return $decrypted; |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* Decodes and decrypts a single value. |
114
|
|
|
* |
115
|
|
|
* @param string $value The value to decode & decrypt. |
116
|
|
|
* @param string|false $encrypt The encryption cipher to use. |
117
|
|
|
* @return string Decoded value. |
118
|
|
|
*/ |
119
|
|
|
protected function _decode($value, $encrypt) |
120
|
|
|
{ |
121
|
|
|
if (!$encrypt) { |
|
|
|
|
122
|
|
|
return $this->_explode($value); |
123
|
|
|
} |
124
|
|
|
$this->_checkCipher($encrypt); |
125
|
|
|
$prefix = 'Q2FrZQ==.'; |
126
|
|
|
$value = base64_decode(substr($value, strlen($prefix))); |
127
|
|
|
if ($encrypt === 'rijndael') { |
128
|
|
|
$value = Security::rijndael($value, $this->_getCookieEncryptionKey(), 'decrypt'); |
129
|
|
|
} |
130
|
|
|
if ($encrypt === 'aes') { |
131
|
|
|
$value = Security::decrypt($value, $this->_getCookieEncryptionKey()); |
132
|
|
|
} |
133
|
|
|
return $this->_explode($value); |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
/** |
137
|
|
|
* Implode method to keep keys are multidimensional arrays |
138
|
|
|
* |
139
|
|
|
* @param array $array Map of key and values |
140
|
|
|
* @return string A json encoded string. |
141
|
|
|
*/ |
142
|
|
|
protected function _implode(array $array) |
143
|
|
|
{ |
144
|
|
|
return json_encode($array); |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
/** |
148
|
|
|
* Explode method to return array from string set in CookieComponent::_implode() |
149
|
|
|
* Maintains reading backwards compatibility with 1.x CookieComponent::_implode(). |
150
|
|
|
* |
151
|
|
|
* @param string $string A string containing JSON encoded data, or a bare string. |
152
|
|
|
* @return array Map of key and values |
153
|
|
|
*/ |
154
|
|
|
protected function _explode($string) |
155
|
|
|
{ |
156
|
|
|
$first = substr($string, 0, 1); |
157
|
|
|
if ($first === '{' || $first === '[') { |
158
|
|
|
$ret = json_decode($string, true); |
159
|
|
|
return ($ret !== null) ? $ret : $string; |
160
|
|
|
} |
161
|
|
|
$array = []; |
162
|
|
|
foreach (explode(',', $string) as $pair) { |
163
|
|
|
$key = explode('|', $pair); |
164
|
|
|
if (!isset($key[1])) { |
165
|
|
|
return $key[0]; |
166
|
|
|
} |
167
|
|
|
$array[$key[0]] = $key[1]; |
168
|
|
|
} |
169
|
|
|
return $array; |
170
|
|
|
} |
171
|
|
|
} |
172
|
|
|
|
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.