Zabezpečenie dát ukladaných do cookies v PHP | devLife.eu
Nov
20th

Zabezpečenie dát ukladaných do cookies v PHP

Zaradené do PHP | Publikoval rado


PHP logoPri vývoji php web aplikácií sa niekedy môže stať, že potrebujete uložiť nejaké dáta do cookies a zároveň ich potrebujete zabezpečiť. Zabezpečenie môže predstavovať buď úplne schovanie dát pred užívateľom (zašifrovanie) alebo len v zabezpečení autenticity dát (tzn, že neboli pozmenené).

V oboch prípadoch bude lepšie, ak si na prístup k dátam vytvorite triedu, ktorá sa už o správne uloženie do prehliadača postará. V základe môže php kód vyzerať následovne:

class SecureCookies {
	private static $secretKey = 'Tajne heslo';
	private static $iv = 'asdklssd5SSlkc0cxkEdcx2s8C9qkzxg'; // initialize vector aka seed
	private static $expire = 2592000; // 30 days
	private static $valid = null; // used for signing

	static function get($key) { ... }
	static function set($key, $data) { ... }
}

Pre načítanie alebo uloženie dát potom stačí zavolať:

SecureCookies::get('username');
SecureCookies::set('username', 'Fred');

Čo sa týka implementácie, tak prvou možnosťou, ako cookies zabezpečiť je ich zašifrovať. Na to je vhodné využiť šifrovaciu knižnicu mcrypt v php, ktorá obsahuje väčšinu bežne používaných šifier.

Zabezpečenie cookies bude spočívať v ich zakryptovaní. Teda, každá cookie bude samostatne zašifrovaná. Problém ale nastáva pri dešifrovaní, pretože funkcie mcrypt nevie rozoznať, čí dešifrovanie prebehlo správne alebo nie. To sa dá jednoducho vyriešiť pridaním reťazca na začiatok a potom jeho kontrolou. Príklad implementácie môže byť následovný:

	/**
	 * Gets secure data from cookie or false if no cookie or bad decrypted.
	 * @param $key
	 * @return string | false
	 */
	static function get($key) {
		if (!isset($_COOKIE[$key])) {
			return false;
		}
		else {
			$data = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, self::$secretKey, base64_decode($_COOKIE[$key]), MCRYPT_MODE_CBC, self::$iv));
			if (strpos($data, '_OK_') === 0) {
				return substr($data, 4);
			}
			else {
				return false;
			}
		}
		return $key;
	}

	/**
	 * Sets and encrypts data to cookie.
	 * @param string $key
	 * @param string $data
	 */
	static function set($key, $data) {
		$data = '_OK_'. $data;
		$dataEnc = trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, self::$secretKey, $data, MCRYPT_MODE_CBC, self::$iv)));
		setcookie($key, $dataEnc, time()+self::$expire, '/');
		$_COOKIE[$key] = $dataEnc;
	}

Druhou možnosťou je tzv. podpisovanie dát (digest, sign). Princíp spočíva v tom, že samotné dáta budú uložené priamo v cookie (bez šifrovania) ale pridá sa k ním ďalšia cookie, ktorá bude obsahovať podpis. Podpis nieje nič iné, ako všetky cookie spojené dohromady zahashované pomocou tajného hesla.

Na zahashovanie je možné využiť mnoho funkcií. Od štandardných md5 a sha1 cez hash_hmac až po OpenSSL. OpenSSL a hash_hmac priamo podporujú hashovanie pomocou kľúča (salt). Pre iné stačí kľúč pripojiť priamo k hashovaným dátam.

Najväčším problémom pre podpisovanie je to, ktoré cookies a v akom poradí zaradiť do podpisu. Nie je možné zobrať všetky, pretože niektoré môžu byť menené inou aplikáciou (napr Google Analytics). Vyriešiť sa to dá buď ukladaním názvov a poradia cookies alebo definovaním v php kóde.

Samotné vytváranie podpisu je jednoduché:

// gets key=>value pairs of all cookies to sign
$cookieDataArray = self::getCookiesToSign();

// create signature
$signature = join('|', $cookieDataArray);

// hash signature
$hashedSignature = hash_hmac('sha256', $signature, self::$secretKey);

Vytvorenú signatúru stačí uložiť do cookie:

// store signature
setcookie('signature', $hashedSignature, time()+self::$expire, '/');

Alebo overiť pri inicializácií, či sú data platné:

// check if signature is valid
if ($_COOKIE['signature'] != $hashedSignature) {
	// cookies are not valid
	...
}

To by bolo pre teraz všetko. Pokiaľ vás niečo k tejto téme zaujalo alebo máte nejaké pripomienky, pokojne dole pridajte komentár.

Be Sociable, Share!


Pridať komentár