Tyler Lazenby
Tyler Lazenby

Reputation: 451

Unable to decrypt cookie

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'));
    }
}

EDIT - SHOWING UPDATED FUNCTIONS that don't store binary

/**
 * 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

Answers (1)

Luke Joshua Park
Luke Joshua Park

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

Related Questions