Instantly share code, notes, and snippets.
Last active
December 11, 2015 07:38
-
Star
1
(1)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save kafene/4567560 to your computer and use it in GitHub Desktop.
Cookies, Sessions, and Encryption in PHP - http://my.opera.com/mcovey/blog/2013/01/18/cookies-sessions-and-encryption-in-php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Just to make things easier: | |
function get_cookie_encryption_key() { | |
return 'this is an example.'; | |
} | |
function encrypt_data($data, $key) { | |
$key = mb_substr($key, 0, mcrypt_get_key_size('rijndael-256', 'cbc')); | |
$iv_size = mcrypt_get_iv_size('rijndael-256', 'cbc'); | |
$iv = mcrypt_create_iv($iv_size, \MCRYPT_DEV_URANDOM); | |
$encrypted = mcrypt_encrypt('rijndael-256', $key, $data, 'cbc', $iv); | |
$encrypted = base64_encode($encrypted); | |
return sprintf('%s|%s', $encrypted, base64_encode($iv)); | |
} | |
function decrypt_data($data, $key) { | |
$key = mb_substr($key, 0, mcrypt_get_key_size('rijndael-256', 'cbc')); | |
list($data, $iv) = explode('|', $data); // sscanf for '%s|%s' didn't work :( | |
$data = base64_decode($data); | |
$iv = base64_decode($iv); | |
return trim(mcrypt_decrypt('rijndael-256', $key, $data, 'cbc', $iv), "\0"); | |
} | |
function set_encrypted_cookie($name, $value, $expires = '+30 Days') { | |
if(false === $value) { | |
$expires = 0; | |
} else { | |
$expires = time() + strtotime($expires, 0); | |
$value = json_encode(array($expires, $value)); | |
$value = encrypt_data( | |
$value | |
, get_cookie_encryption_key() | |
); | |
} | |
// You might want to do this: | |
// $_COOKIE[$key] = $value; | |
setcookie($name, $value, $expires, '/', null, false, true); | |
} | |
function get_encrypted_cookie($name, $expires = '+30 Days') { | |
if(isset($_COOKIE[$name])) { | |
$cookie = decrypt_data( | |
$_COOKIE[$name] | |
, get_cookie_encryption_key() | |
); | |
$value = json_decode($cookie, true); | |
return ($value && time() < $value[0]) | |
? $value[1] | |
: false; | |
} | |
} | |
function encrypted_cookie_session_start() { | |
if(session_status() == \PHP_SESSION_ACTIVE) { return; } | |
session_set_cookie_params(2592000, '/', null, false, true); | |
$void = function() { return true; }; | |
session_set_save_handler( | |
$void, $void | |
, 'get_encrypted_cookie' | |
, 'set_encrypted_cookie' | |
, $void, $void | |
); | |
if(function_exists('session_register_shutdown')) { | |
session_register_shutdown(); | |
} else { | |
register_shutdown_function('session_write_close'); | |
} | |
session_start(); | |
} | |
/* ***************************************************************************** | |
/* *** TESTS ******************************************************************* | |
***************************************************************************** */ | |
// For testing, in case php.ini differs | |
ini_set('assert.active', 1); | |
ini_set('assert.warning', 1); | |
ini_set('display_errors', 1); | |
error_reporting(-1); | |
// allow sending headers after using "echo" | |
ob_start(); | |
register_shutdown_function('ob_end_flush'); | |
// Should print two different strings, both of which contain "Hello!!", | |
// encrypted with the same key, using different IVs. | |
$enc1 = encrypt_data('Hello!!', get_cookie_encryption_key()); | |
$enc2 = encrypt_data('Hello!!', get_cookie_encryption_key()); | |
assert('$enc1 != $enc2'); // It is possible, but very unlikely that this will fail. | |
echo $enc1.'<br>'.$enc2.'<br><br>'; // Should print 2 base64 (+ `|`) lines | |
$one = encrypt_data('hello', get_cookie_encryption_key()); | |
$two = encrypt_data('hello', get_cookie_encryption_key()); | |
$one_res = decrypt_data($one, get_cookie_encryption_key()); | |
$two_res = decrypt_data($two, get_cookie_encryption_key()); | |
assert('$one_res === $two_res;'); | |
echo $one_res.' '.$two_res.'<br><br>'; // should print "hello hello" | |
// will check this later on | |
set_encrypted_cookie('username', 'jack_the_ripper'); | |
// This will print the contents of all cookies PHP can see. | |
// The first time the page is loaded, the above cookie should be absent, | |
// unless you uncomment the line in set_encrypted_cookie() | |
// that explicitly adds the value to $_COOKIE, | |
// as the cookie is sent after PHP has rendered the page. | |
echo '<pre>'; | |
var_dump($_COOKIE); | |
echo '</pre><br><br>'; | |
// Should print "jack_the_ripper" after the first load | |
$username = get_encrypted_cookie('username'); | |
if(isset($_COOKIE['username'])) | |
assert('$username === "jack_the_ripper";'); | |
echo $username.'<br><br>'; | |
// Start the encrypted cookie session and test it. | |
encrypted_cookie_session_start(); | |
if(!isset($_SESSION['name']) || !isset($_SESSION['password'])) { | |
$_SESSION['name'] = 'hello'; | |
$_SESSION['password'] = 'world'; | |
} else { | |
$result = $_SESSION['name'].' '.$_SESSION['password']; | |
assert('$result === "hello world";'); | |
echo $result; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment