. */ namespace SP\Core\Crypt; use Defuse\Crypto\Exception\CryptoException; use Defuse\Crypto\Exception\EnvironmentIsBrokenException; use Defuse\Crypto\Key; use SP\Http\Request; /** * Class SecureKeyCookie * * @package SP\Core\Crypt */ final class SecureKeyCookie extends Cookie { /** * Nombre de la cookie */ const COOKIE_NAME = 'SYSPASS_SK'; /** * Llave usada para encriptar los datos * * @var Key */ private $securedKey; /** * @var string */ private $cypher; /** * @param Request $request * * @return SecureKeyCookie */ public static function factory(Request $request): SecureKeyCookie { $self = new self(self::COOKIE_NAME, $request); $self->cypher = $self->getCypher(); return $self; } /** * Devolver la llave de cifrado para los datos de la cookie * * @return string */ public function getCypher(): string { return sha1($this->request->getHeader('User-Agent') . $this->request->getClientAddress()); } /** * Obtener una llave de encriptación * * @return Key|false|string */ public function getKey() { $cookie = $this->getCookie(); if ($cookie !== false) { $data = $this->getCookieData($cookie, $this->cypher); if ($data !== false) { /** @var Vault $vault */ $vault = unserialize($data, ['allowed_classes' => Vault::class]); if ($vault !== false && ($vault instanceof Vault) === true ) { try { $this->securedKey = Key::loadFromAsciiSafeString($vault->getData($this->cypher)); return $this->securedKey; } catch (CryptoException $e) { logger($e->getMessage(), 'EXCEPTION'); } return false; } } else { logger('Cookie verification error', 'ERROR'); } } elseif (($this->securedKey instanceof Key) === true) { return $this->securedKey; } return $this->saveKey() ? $this->securedKey : false; } /** * Guardar una llave de encriptación * * @return Key|false */ public function saveKey() { try { if ($this->setCookie($this->sign($this->generateSecuredData()->getSerialized(), $this->cypher)) === false) { logger('Could not generate session\'s key cookie', 'ERROR'); unset($this->securedKey); return false; } logger('Generating a new session\'s key cookie'); return true; } catch (CryptoException $e) { logger($e->getMessage(), 'EXCEPTION'); } return false; } /** * @return Vault * @throws CryptoException * @throws EnvironmentIsBrokenException */ public function generateSecuredData(): Vault { $this->securedKey = Key::createNewRandomKey(); return (new Vault()) ->saveData($this->securedKey->saveToAsciiSafeString(), $this->cypher); } /** * @return Key */ public function getSecuredKey(): Key { return $this->securedKey; } }