Application->ConfigValue('RandomString'); } $this->_config = Array ( 'secret' => substr($secret, 0, 32), // used cipher only allows 256bit (or less) key length 'cipher' => MCRYPT_RIJNDAEL_256, 'mode' => MCRYPT_MODE_CBC, 'vector' => static::_vector(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC) ); $plain_text_cookies = (string)$this->Application->ConfigValue('PlainTextCookies'); if ( $plain_text_cookies ) { $plain_text_cookies = array_filter(array_map('trim', explode(',', $plain_text_cookies))); $this->_plainTextCookies = array_unique(array_merge($this->_plainTextCookies, $plain_text_cookies)); } } /** * Determines if cookie should be processed or passed through as is * * @param string $cookie_name * @return bool * @access protected */ protected function _isPassThrough($cookie_name) { return in_array($cookie_name, $this->_plainTextCookies); } /** * Generates encryption vector and returns it * * @param string $cipher * @param string $mode * @return string * @access protected */ protected static function _vector($cipher, $mode) { if ( static::$_vector ) { return static::$_vector; } $size = static::_vectorSize($cipher, $mode); return static::$_vector = mcrypt_create_iv($size, MCRYPT_DEV_URANDOM); } /** * Returns vector size for given cipher and encryption mode * * @param string $cipher * @param string $mode * @return int * @access protected */ protected static function _vectorSize($cipher, $mode) { return mcrypt_get_iv_size($cipher, $mode); } /** * Encrypts a cookie * * @param string $cookie_name * @param mixed $plain_value * @return string * @access public */ public function encrypt($cookie_name, $plain_value) { if ( $this->_isPassThrough($cookie_name) ) { return $plain_value; } $cipher = $this->_config['cipher']; $secret = $this->_config['secret']; $mode = $this->_config['mode']; $vector = $this->_config['vector']; $data = Array ($cookie_name => $plain_value); $encrypted = mcrypt_encrypt($cipher, $secret, serialize($data), $mode, $vector); return base64_encode($encrypted) . base64_encode($vector); } /** * Decrypts a cookie * * @param string $cookie_name * @param string $encrypted_value * @return mixed * @access public */ public function decrypt($cookie_name, $encrypted_value) { if ( $this->_isPassThrough($cookie_name) ) { return $encrypted_value; } $cipher = $this->_config['cipher']; $secret = $this->_config['secret']; $mode = $this->_config['mode']; $vector_size = static::_vectorSize($cipher, $mode); $base64_vector_size = strlen(base64_encode(str_repeat(' ', $vector_size))); $vector = $this->_safeBase64Decode(substr($encrypted_value, -$base64_vector_size)); $data = $this->_safeBase64Decode(substr($encrypted_value, 0, -$base64_vector_size)); if ( $vector === false || $data === false || strlen($vector) != $vector_size ) { // non-encrypted or malformed cookie value given return ''; } // non-serialized array is decrypted in case of decrypting old cookies after a secret change $decrypted = trim(mcrypt_decrypt($cipher, $secret, $data, $mode, $vector)); $data = kUtil::IsSerialized($decrypted) ? unserialize($decrypted) : Array (); // check if cookie value was actually copied from other cookie return isset($data[$cookie_name]) ? $data[$cookie_name] : ''; } /** * Safely decodes base64-encoded string * * @param string $encoded_string * @return string|bool * @access protected */ protected function _safeBase64Decode($encoded_string) { $decoded_string = base64_decode($encoded_string); if ( (string)base64_encode($decoded_string) !== (string)$encoded_string ) { return false; } return $decoded_string; } }