Reputation: 451
I have a need to encrypt cookies on my site. Lets assume that the data that I wanted to encrypt is my session ID for simplicity.
Here is how I would generate my cookie and encrypt it using PHP openSSL, and decrypt it.
/**
* Encrypt any cookie
* @param $content
* @param $key_name
* @param $iv_name
* @return string
*/
function encrypt_cookie(string $content, string $key_name, string $iv_name): string
{
$method = 'AES-256-CFB';
$ivLength = openssl_cipher_iv_length($method);
$needStrong = true;
$keyLength = 256;
if (!isset($_SESSION[$key_name])) {
$key = openssl_random_pseudo_bytes($keyLength, $needStrong);
$_SESSION[$key_name] = $key;
} else {
$key = $_SESSION[$key_name];
}
$iv = openssl_random_pseudo_bytes($ivLength, $needStrong);
$_SESSION[$iv_name] = $iv;
return openssl_encrypt($content, $method, $key, $options=OPENSSL_RAW_DATA, $iv);
}
/**
* Decrypt any cookie
* @param string $cookie_name
* @param string $key_name
* @param $iv_name
* @return string
*/
function decrypt_cookie(string $cookie_name, string $key_name, $iv_name): string
{
$data = $_COOKIE[$cookie_name];
$method = 'AES-256-CFB';
$key = $_SESSION[$key_name];
$options = OPENSSL_RAW_DATA;
$iv = $_SESSION[$iv_name];
return openssl_decrypt($data, $method, $key, $options, $iv);
}
/**
* Create the cookie and set its value to an
* encrypted version of my session ID
*/
function cooking_snickerdoodles(): void
{
$cookie_name = "sugar_cookie";
$content = session_id();
$key_name = 'timeout_cookie_key';
$iv_name = 'sugar_cookie_iv';
$hex = encrypt_cookie($content, $key_name, $iv_name);
setcookie($cookie_name, $hex);
}
The encryption works great. It outputs something and I can read it if I convert it using bin2hex()
. However my decryption method isn't working at all. I checked in my browser developer tools and 'sugar_cookie' is shown as one of the cookies.
When I try to echo out the result of decrypt_cookie()
I am getting absolutely nothing, even if I pass it into bin2hex
.
This next code isn't really important but it is what I am using to make sure that the session data matches the cookie data:
function has_the_cookie($cookie_name): bool
{
if (isset($_COOKIE[$cookie_name])) {
return true;
} else {
return false;
}
}
function cookie_tastes_right(): bool
{
$crumbs = $_COOKIE['sugar_cookie'];
$whole_cookie = decrypt_cookie($crumbs, $_SESSION['timeout_cookie_key'], $_SESSION['sugar_cookie_iv']);
if ($whole_cookie === session_id()) {
return true;
} else {
return false;
}
}
function confirm_cookie_in_bag(): void
{
if (!has_the_cookie('sugar_cookie') || !cookie_tastes_right()) {
end_session();
redirect_to(url_for('admin/login.php'));
}
}
/**
* Encrypt any cookie
* @param $content
* @param $key_name
* @param $iv_name
* @return string
*/
function encrypt_cookie(string $content, string $key_name, string $iv_name): string
{
$method = 'AES-256-CFB';
$ivLength = openssl_cipher_iv_length($method);
$needStrong = true;
$keyLength = 256;
if (!isset($_SESSION[$key_name])) {
$key = openssl_random_pseudo_bytes($keyLength, $needStrong);
$_SESSION[$key_name] = $key;
} else {
$key = $_SESSION[$key_name];
}
$iv = openssl_random_pseudo_bytes($ivLength, $needStrong);
$_SESSION[$iv_name] = $iv;
return bin2hex(openssl_encrypt($content, $method, $key, $options=OPENSSL_RAW_DATA, $iv));
}
/**
* Decrypt any cookie
* @param string $cookie_name
* @param string $key_name
* @param $iv_name
* @return string
*/
function decrypt_cookie(string $cookie_name, string $key_name, $iv_name): string
{
$data = hex2bin($_COOKIE[$cookie_name]);
$method = 'AES-256-CFB';
$key = $_SESSION[$key_name];
$options = OPENSSL_RAW_DATA;
$iv = $_SESSION[$iv_name];
//ECHO and exit for demo purposes only
echo bin2hex(openssl_decrypt($data, $method, $key, $options, $iv));
exit;
}
Upvotes: 0
Views: 1537
Reputation: 9806
You're using OPENSSL_RAW_DATA
- the output from this call won't be hex, it will be binary. Storing raw binary in a cookie is a no-go! You'd probably prefer base64 over hex, which is the default behaviour.
Upvotes: 1