0

I have the following class that I am trying to use to encrypt and decrypt my cookies. I need to store user id in cookies for the Keep Me Logged In feature so that the user stays logged in even if he closes the browser and returns later. The following function that I am using is working fine for the encryption. However, it's not working for decryption. I got this class from this question.

$key = 'alabooencryptionkey';
$iv = AES256Encryption::generateIv();

class AES256Encryption {
  public const BLOCK_SIZE = 8;
  public const IV_LENGTH = 16;
  public const CIPHER = 'AES256';

  public static function generateIv(bool $allowLessSecure = false): string {
    $success = false;
    $random = openssl_random_pseudo_bytes(openssl_cipher_iv_length(static::CIPHER));
    if(!$success) {
      if (function_exists('sodium_randombytes_random16')) {
        $random = sodium_randombytes_random16();
      }else{
        try {
          $random = random_bytes(static::IV_LENGTH);
        }catch (Exception $e) {
          if($allowLessSecure) {
            $permitted_chars = implode('',
              array_merge(
                  range('A', 'z'),
                  range(0, 9),
                  str_split('~!@#$%&*()-=+{};:"<>,.?/\'')
              )
            );
            $random = '';
            for($i = 0; $i < static::IV_LENGTH; $i++) {
              $random .= $permitted_chars[mt_rand(0, (static::IV_LENGTH) - 1)];
            }
          }else{
            throw new RuntimeException('Unable to generate initialization vector (IV)');
          }
        }
      }
    }
    return $random;
  }

  protected static function getPaddedText(string $plainText): string {
    $stringLength = strlen($plainText);
    if($stringLength % static::BLOCK_SIZE) {
      $plainText = str_pad($plainText, $stringLength + static::BLOCK_SIZE - $stringLength % static::BLOCK_SIZE, "\0");
    }
    return $plainText;
  }

  public static function encrypt(string $plainText, string $key, string $iv): string {
    $plainText = static::getPaddedText($plainText);
    return base64_encode(openssl_encrypt($plainText, static::CIPHER, $key, OPENSSL_RAW_DATA, $iv));
  }

  public static function decrypt(string $encryptedText, string $key, string $iv): string {
    return openssl_decrypt(base64_decode($encryptedText), static::CIPHER, $key, OPENSSL_RAW_DATA, $iv);
  }
}

I am using it here for encrypting my cookie which works fine.

function setLoginCookieSession($user){
  global $key, $iv;
  $_SESSION['newchatapp'] = $user;
  setcookie("newchatapp", AES256Encryption::encrypt($user, $key, $iv), time()+3600*24*365*10, '/');
}

And here for decrypting which is not working. It returns nothing.

function sessionUser(){
  global $key, $iv;
  // return (isset($_SESSION['newchatapp']))?$_SESSION['newchatapp']:AES256Encryption::decrypt($_COOKIE['newchatapp'], $key, $iv);
  return AES256Encryption::decrypt($_COOKIE['newchatapp'], $key, $iv);
}

Even if I manually input try to decode the encrypted string it still returns nothing.

echo AES256Encryption::decrypt('ianXhsXhh6MWAHliZoshEA%3D%3D', $key, $iv);

This means that the decryption is not working at all. What can I do to make it work?

Shubham Jha
  • 53
  • 1
  • 8
  • Why not just generate a cryptographically secure token and store that in your user record. No need for encryption or decryption, and you can revoke it if necessary without affecting the user account. See [this answer](https://stackoverflow.com/a/18890309/14853083) – Tangentially Perpendicular May 14 '21 at 04:13
  • If the browser throws away the cookie when it closes your user won't remain logged in either. – Code4R7 May 14 '21 at 05:03
  • @Code4R7 I will be converting the app into webview to be used as an android application so I will make sure that it uses the settings I prescribe into the webview for keeping the cookies and never destroying it unless the user logs out. Hence, that's manageable. So now, if you can help me with the real issue I will be glad :) – Shubham Jha May 14 '21 at 15:45
  • How would you simulate WebView on a client device while PHP runs on a server? Anyhow, I think it's not worth your time since the script from 2010 looks rather outdated, you're probably better off with [this](https://gist.github.com/joashp/a1ae9cb30fa533f4ad94) example, which I'm going to try too. – Code4R7 May 14 '21 at 18:03
  • I ended up with [this](https://stackoverflow.com/questions/3422759/php-aes-encrypt-decrypt/46872528#46872528) SO answer which does not have the security flaw and utilizes openssl_random_pseudo_bytes(). – Code4R7 May 14 '21 at 18:22
  • Does this answer your question? [PHP AES encrypt / decrypt](https://stackoverflow.com/questions/3422759/php-aes-encrypt-decrypt) – Code4R7 May 14 '21 at 18:27
  • @Code4R7 There are ways by which you can run a PHP driven website in a WebView. One method is using Android studio. The actual website will be running on the server as usual but android studio will convert it into a mobile based application. You can say you get a private browser loaded with your own web app. – Shubham Jha May 14 '21 at 22:14

0 Answers0