1 | <?php namespace Comodojo\Cookies; |
||
2 | |||
3 | use \phpseclib\Crypt\AES; |
||
4 | use \Comodojo\Exception\CookieException; |
||
5 | |||
6 | /** |
||
7 | * AES-encrypted cookie |
||
8 | * |
||
9 | * @package Comodojo Spare Parts |
||
10 | * @author Marco Giovinazzi <[email protected]> |
||
11 | * @license MIT |
||
12 | * |
||
13 | * LICENSE: |
||
14 | * |
||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||
21 | * THE SOFTWARE. |
||
22 | */ |
||
23 | |||
24 | class EncryptedCookie extends AbstractCookie { |
||
25 | |||
26 | /* |
||
27 | * AES key |
||
28 | * |
||
29 | * @var int |
||
30 | */ |
||
31 | private $key = null; |
||
32 | |||
33 | /** |
||
34 | * Encrypted cookie constructor |
||
35 | * |
||
36 | * Setup cookie name and key |
||
37 | * |
||
38 | * @param string $name |
||
39 | * @param string $key |
||
40 | * @param int $max_cookie_size |
||
41 | * |
||
42 | * @throws CookieException |
||
43 | */ |
||
44 | 42 | public function __construct($name, $key, $max_cookie_size = null) { |
|
45 | |||
46 | 42 | if ( empty($key) OR !is_scalar($key) ) throw new CookieException("Invalid secret key"); |
|
47 | |||
48 | 42 | parent::__construct($name, $max_cookie_size); |
|
49 | |||
50 | 42 | } |
|
51 | |||
52 | /** |
||
53 | * {@inheritdoc} |
||
54 | */ |
||
55 | public function setValue($value, $serialize = true) { |
||
56 | |||
57 | if ( !is_scalar($value) && $serialize === false ) throw new CookieException("Cannot set non-scalar value without serialization"); |
||
58 | |||
59 | if ( $serialize === true ) $value = serialize($value); |
||
60 | |||
61 | $cipher = new AES(AES::MODE_ECB); |
||
62 | 24 | ||
63 | $cipher->setKeyLength(256); |
||
64 | 24 | ||
65 | $cipher->setKey(self::encryptKey($this->key)); |
||
66 | 24 | ||
67 | // added base64 encoding to avoid problems with binary data |
||
68 | 24 | ||
69 | $cookie_value = base64_encode($cipher->encrypt($value)); |
||
70 | 24 | ||
71 | if ( strlen($cookie_value) > $this->max_cookie_size ) throw new CookieException("Cookie size larger than ".$this->max_cookie_size." bytes"); |
||
72 | 24 | ||
73 | $this->value = $cookie_value; |
||
74 | |||
75 | return $this; |
||
76 | 24 | ||
77 | } |
||
78 | 24 | ||
79 | /** |
||
80 | 18 | * {@inheritdoc} |
|
81 | */ |
||
82 | 18 | public function getValue($unserialize = true) { |
|
83 | |||
84 | $cipher = new AES(AES::MODE_ECB); |
||
85 | |||
86 | $cipher->setKeyLength(256); |
||
87 | |||
88 | $cipher->setKey(self::encryptKey($this->key)); |
||
89 | |||
90 | // added base64 encoding to avoid problems with binary data |
||
91 | |||
92 | $encoded_cookie = base64_decode($this->value); |
||
93 | 18 | ||
94 | if ( $encoded_cookie === false ) throw new CookieException("Cookie data cannot be decoded"); |
||
95 | 18 | ||
96 | $cookie = $cipher->decrypt($encoded_cookie); |
||
97 | 18 | ||
98 | if ( $cookie === false ) throw new CookieException("Cookie data cannot be dectypted"); |
||
0 ignored issues
–
show
introduced
by
![]() |
|||
99 | 18 | ||
100 | return ($unserialize === true) ? unserialize($cookie) : $cookie; |
||
101 | |||
102 | } |
||
103 | 18 | ||
104 | /** |
||
105 | 18 | * Static method to quickly create a cookie |
|
106 | * |
||
107 | 18 | * @param string $name |
|
108 | * The cookie name |
||
109 | 18 | * |
|
110 | * @param string $key |
||
111 | 18 | * |
|
112 | * @param array $properties |
||
113 | * Array of properties cookie should have |
||
114 | * |
||
115 | * @return EncryptedCookie |
||
116 | * @throws CookieException |
||
117 | */ |
||
118 | public static function create($name, $key, array $properties = [], $serialize = true) { |
||
119 | |||
120 | try { |
||
121 | |||
122 | $class = get_called_class(); |
||
123 | |||
124 | $cookie = new $class($name, $key); |
||
125 | |||
126 | CookieTools::setCookieProperties($cookie, $properties, $serialize); |
||
127 | |||
128 | 6 | } catch (CookieException $ce) { |
|
129 | |||
130 | throw $ce; |
||
131 | |||
132 | 6 | } |
|
133 | |||
134 | 6 | return $cookie; |
|
135 | |||
136 | 6 | } |
|
137 | |||
138 | 6 | /** |
|
139 | * Static method to quickly get a cookie |
||
140 | * |
||
141 | * @param string $name |
||
142 | * The cookie name |
||
143 | * |
||
144 | 6 | * @param string $key |
|
145 | * |
||
146 | * @return EncryptedCookie |
||
147 | * @throws CookieException |
||
148 | */ |
||
149 | public static function retrieve($name, $key) { |
||
150 | |||
151 | try { |
||
152 | |||
153 | $class = get_called_class(); |
||
154 | |||
155 | $cookie = new $class($name, $key); |
||
156 | |||
157 | $return = $cookie->load(); |
||
158 | |||
159 | 6 | } catch (CookieException $ce) { |
|
160 | |||
161 | throw $ce; |
||
162 | |||
163 | 6 | } |
|
164 | |||
165 | 6 | return $return; |
|
166 | |||
167 | 6 | } |
|
168 | |||
169 | 6 | /** |
|
170 | * Hash the key to generate a valid aes key value |
||
171 | 6 | * |
|
172 | * @param string $key |
||
173 | * |
||
174 | * @return string |
||
175 | */ |
||
176 | protected static function encryptKey($key) { |
||
177 | |||
178 | return hash('sha256', $key); |
||
179 | |||
180 | } |
||
181 | |||
182 | } |
||
183 |