php encrypting and decrypting cookies - php

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?

Related

Why AES Decrypt code doesn't work in php 7.2

I used AES for encrypt the post parameters that send from java to server with volley. so I used below's class in my server for decrypt the post parammeters .
<?php
class MCrypt {
private $hex_iv = '31323334353637383930616263646566'; # converted Java byte code in to HEX and placed it here
private $key = '0FDOUZ.Qz'; #Same as in JAVA
function __construct() {
$this->key = hash('sha256', $this->key, true);
//echo $this->key.'<br/>';
}
function encrypt($str) {
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
mcrypt_generic_init($td, $this->key, $this->hexToStr($this->hex_iv));
$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$pad = $block - (strlen($str) % $block);
$str .= str_repeat(chr($pad), $pad);
$encrypted = mcrypt_generic($td, $str);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return base64_encode($encrypted);
}
function decrypt($code) {
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
mcrypt_generic_init($td, $this->key, $this->hexToStr($this->hex_iv));
$str = mdecrypt_generic($td, base64_decode($code));
$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return $this->strippadding($str);
}
/*
For PKCS7 padding
*/
private function addpadding($string, $blocksize = 16) {
$len = strlen($string);
$pad = $blocksize - ($len % $blocksize);
$string .= str_repeat(chr($pad), $pad);
return $string;
}
private function strippadding($string) {
$slast = ord(substr($string, -1));
$slastc = chr($slast);
$pcheck = substr($string, -$slast);
if (preg_match("/$slastc{" . $slast . "}/", $string)) {
$string = substr($string, 0, strlen($string) - $slast);
return $string;
} else {
return false;
}
}
function hexToStr($hex)
{
$string='';
for ($i=0; $i < strlen($hex)-1; $i+=2)
{
$string .= chr(hexdec($hex[$i].$hex[$i+1]));
}
return $string;
}
}
?>
Also I used below's code in newuser.php file .
<?php
.....
//decrypt
$encryption = new MCrypt();
$phone= $encryption->decrypt($phoneenc);
$password= $encryption->decrypt($passwordenc);
$serialdivice= $encryption->decrypt($serialdiviceenc);
$sequretyQustion= $encryption->decrypt($sequretyQustionenc);
$sequretyAnsewr= $encryption->decrypt($sequretyAnsewrenc);
.... ?>
Before Update php to php7.2 my code worked correctly . But for now It get error for decrypt method when I updated php . so How can i fix it?
I used openssl for both java and php .It's working correctly now.

Decrypted string is sometimes not same as encrypted source

class Auth extends MySQLi {
public function aes_enc($encrypt, $mc_key, $iv) {
$passcrypt = trim(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, substr($mc_key, 0, 32), trim($encrypt), MCRYPT_MODE_CBC, $iv));
return $passcrypt;
}
public function aes_dec($decrypt, $mc_key, $iv) {
$decrypted = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, substr($mc_key, 0, 32), trim($decrypt), MCRYPT_MODE_CBC, $iv));
return $decrypted;
}
public function salt() {
return str_shuffle('abcdefghijklmnoprsquvzyx0123456789-.,;:_<>');
}
public function iv() {
return mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_RAND);
}
}
And on test.php, following code:
<?
require('Auth.php');
$Auth = new Auth;
$str = "verygudlongpassword";
for ($i = 0; $i < 1000; $i++) {
$salt = sha1($Auth->salt());
$iv = $Auth->iv();
$enc = $Auth->aes_enc($str, $salt, $iv);
$dec = $Auth->aes_dec($enc, $salt, $iv);
if ($str != $dec) {
echo $salt . "<br>\n";
}
}
?>
Sometimes, $dec != $str. Why is this happening? I am not even saving anything into DB atm, so it's not that.
Thanks for help.
i dont really have anything more to say, but site isnt letting me post. (nvm that part)
After reviewing your code and playing with it locally. It would appear that your decryption leaves some whitespace on the decrypted text. I removed the trim() function from all locations except the return value from aes_dec() and the code now encrypts/decrypts your string successfully 1000 times.
So it would seem trimming was the problem and the solution.
class Auth extends MySQLi {
public function aes_enc($encrypt, $mc_key, $iv)
{
$passcrypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, substr($mc_key, 0, 32), $encrypt, MCRYPT_MODE_CBC, $iv);
return $passcrypt;
}
public function aes_dec($decrypt, $mc_key, $iv)
{
$decrypted = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, substr($mc_key, 0, 32), $decrypt, MCRYPT_MODE_CBC, $iv));
return $decrypted;
}
public function salt()
{
return str_shuffle('abcdefghijklmnoprsquvzyx0123456789-.,;:_<>');
}
public function iv()
{
return mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_RAND);
}
}
$Auth = new Auth;
$str = "verygudlongpassword";
for ($i = 0; $i < 1000; $i++) {
$salt = sha1($Auth->salt());
$iv = $Auth->iv();
$enc = $Auth->aes_enc($str, $salt, $iv);
$dec = $Auth->aes_dec($enc, $salt, $iv);
if ($str != $dec) {
echo "Decryption failed!<br>\n";
} else {
echo "Decryption success! String: $dec<br>\n";
}
}

Simple PHP Encryption / Decryption (Mcrypt, AES)

I'm looking for a simple yet cryptographically strong PHP implementation of AES using Mcrypt.
Hoping to boil it down to a simple pair of functions, $garble = encrypt($key, $payload) and $payload = decrypt($key, $garble).
I'm recently learning about this subject, and am posting this answer as a community wiki to share my knowledge, standing to be corrected.
Mcrypt Documentation
It's my understanding that AES can be achieved using Mcrypt with the following constants as options:
MCRYPT_RIJNDAEL_128 // as cipher
MCRYPT_MODE_CBC // as mode
MCRYPT_MODE_DEV_URANDOM // as random source (for IV)
During encryption, a randomized non-secret initialization vector (IV) should be used to randomize each encryption (so the same encryption never yields the same garble). This IV should be attached to the encryption result in order to be used later, during decryption.
Results should be Base 64 encoded for simple compatibility.
Implementation:
<?php
define('IV_SIZE', mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC));
function encrypt ($key, $payload) {
$iv = mcrypt_create_iv(IV_SIZE, MCRYPT_DEV_URANDOM);
$crypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $payload, MCRYPT_MODE_CBC, $iv);
$combo = $iv . $crypt;
$garble = base64_encode($iv . $crypt);
return $garble;
}
function decrypt ($key, $garble) {
$combo = base64_decode($garble);
$iv = substr($combo, 0, IV_SIZE);
$crypt = substr($combo, IV_SIZE, strlen($combo));
$payload = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $crypt, MCRYPT_MODE_CBC, $iv);
return $payload;
}
//:::::::::::: TESTING ::::::::::::
$key = "secret-key-is-secret";
$payload = "In 1435 the abbey came into conflict with the townspeople of Bamberg and was plundered.";
// ENCRYPTION
$garble = encrypt($key, $payload);
// DECRYPTION
$end_result = decrypt($key, $garble);
// Outputting Results
echo "Encrypted: ", var_dump($garble), "<br/><br/>";
echo "Decrypted: ", var_dump($end_result);
?>
Output looks like this:
Encrypted: string(152) "4dZcfPgS9DRldq+2pzvi7oAth/baXQOrMmt42la06ZkcmdQATG8mfO+t233MyUXSPYyjnmFMLwwHxpYiDmxvkKvRjLc0qPFfuIG1VrVon5EFxXEFqY6dZnApeE2sRKd2iv8m+DiiiykXBZ+LtRMUCw=="
Decrypted: string(96) "In 1435 the abbey came into conflict with the townspeople of Bamberg and was plundered."
Add function to clean control characters (�).
function clean($string) {
return preg_replace('/[\x00-\x09\x0B\x0C\x0E-\x1F\x7F]/', '', $string);
}
echo "Decrypted: ", clean($end_result);
Sentrapedagang.com
Simple and Usable:
$text= 'Hi, i am sentence';
$secret = 'RaNDoM cHars!##$%%^';
$encrypted = simple_encrypt($text, $secret);
$decrypted = simple_decrypt($encrypted_text, $secret);
codes:
function simple_encrypt($text_to_encrypt, $salt) {
return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, pack('H*', $salt), $text_to_encrypt, MCRYPT_MODE_CBC, $iv = mcrypt_create_iv($iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_RAND))));
}
function simple_decrypt($encrypted, $salt) {
return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, pack('H*', $salt), base64_decode($encrypted), MCRYPT_MODE_CBC, $iv = mcrypt_create_iv($iv_size=mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_RAND)));
}
Class Mycrypt
Try using this class. Here. All you need to pass is key and string.
class MCrypt
{
const iv = 'fedcba9876543210';
/**
* #param string $str
* #param bool $isBinary whether to encrypt as binary or not. Default is: false
* #return string Encrypted data
*/
public static function encrypt($str, $key="0123456789abcdef", $isBinary = false)
{
$iv = self::iv;
$str = $isBinary ? $str : utf8_decode($str);
$td = mcrypt_module_open('rijndael-128', ' ', 'cbc', $iv);
mcrypt_generic_init($td, $key, $iv);
$encrypted = mcrypt_generic($td, $str);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return $isBinary ? $encrypted : bin2hex($encrypted);
}
/**
* #param string $code
* #param bool $isBinary whether to decrypt as binary or not. Default is: false
* #return string Decrypted data
*/
public static function decrypt($code, $key="0123456789abcdef", $isBinary = false)
{
$code = $isBinary ? $code : self::hex2bin($code);
$iv = self::iv;
$td = mcrypt_module_open('rijndael-128', ' ', 'cbc', $iv);
mcrypt_generic_init($td, $key, $iv);
$decrypted = mdecrypt_generic($td, $code);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return $isBinary ? trim($decrypted) : utf8_encode(trim($decrypted));
}
private static function hex2bin($hexdata)
{
$bindata = '';
for ($i = 0; $i < strlen($hexdata); $i += 2) {
$bindata .= chr(hexdec(substr($hexdata, $i, 2)));
}
return $bindata;
}
}
How To Use
$var = json_encode(['name'=>['Savatar', 'Flash']]);
$encrypted = MCrypt::encrypt();
$decrypted = MCrypt::decrypt($encrypted);

3DES PHP Encryption Not Decrypting Properly

I'm using the following code to encrypt information that will be passed to an external site on the end of the link URL. Right now it's able to do the encrypting and decrypting itself, but when I go to online Decryptors (online-domain-tools.com, tools4noobs.com) I'm seeing extra symbols added or it's not showing the right content whatsoever. Of course I'm new to this. What I have, I have pieced together from other questions (php-equivalent-for-java-triple-des-encryption-decryption, php-equivalent-encryption-decryption-tripledes, php-encrypt-decrypt-with-tripledes-pkcs7-and-ecb). Thanks for any help or direction!
I can only use 3DES with CBC.
PHP Code:
$key = "12AB12AB12AB12AB12AB12AB";
$iv = "12AB12AB";
$cipher = mcrypt_module_open(MCRYPT_3DES, '', 'cbc', '');
// MESSAGE
$message = "email=billysmith#afakeemail.com&account=987654321&role=2";
echo 'Message::: ' .$message .'<br />';
// ENCRYPTED
$encrypted = Encryptor($message);
echo 'Encrypted::: ' .$encrypted .'<br />';
// DECRYPTED
$decrypted = Decryptor($encrypted);
echo 'Decrypted::: ' .$decrypted .'<br />';
function Encryptor($buffer) {
global $key, $iv, $cipher;
// get the amount of bytes to pad
$extra = 8 - (strlen($buffer) % 8);
// add the zero padding
if($extra > 0) {
for($i = 0; $i < $extra; $i++) {
$buffer .= "\0";
}
}
mcrypt_generic_init($cipher, $key, $iv);
$result = bin2hex(mcrypt_generic($cipher, $buffer));
mcrypt_generic_deinit($cipher);
return $result;
}
function Decryptor($buffer) {
global $key, $iv, $cipher;
mcrypt_generic_init($cipher, $key, $iv);
$result = rtrim(mdecrypt_generic($cipher, hex2bin($buffer)), "\0");
mcrypt_generic_deinit($cipher);
return $result;
}
function hex2bin($data)
{
$len = strlen($data);
return pack("H" . $len, $data);
}
To be short: Your code is correct. You can't test your encryption with provided tools.
Both tools do not allow to enter your IV.
The IV should be unique and can be transferred publicly.
Using wrong IV by decoding gives you wrong part at the beginning of decrypted data.
Here is OO version. It uses zero padding (built in PHP), like your code. It also makes no padding **, if the original message is already aligned.
<?php
$key = "12AB12AB12AB12AB12AB12AB";
$iv = "12AB12AB";
// MESSAGE
$message = "email=billysmith#afakeemail.com&account=987654321&role=22";
echo 'Message::: ' . $message . PHP_EOL;
$cryptor = new Crypt3Des();
$encryptedMessage = $cryptor->encrypt($message, $key, $iv);
echo 'Encrypted::: ' . bin2hex($encryptedMessage) . PHP_EOL;
$decryptedMessage = $cryptor->decrypt($encryptedMessage, $key, $iv);
echo 'Decrypted::: ' . $decryptedMessage . PHP_EOL;
class Crypt3Des
{
private $cipher;
public function __construct()
{
$this->cipher = mcrypt_module_open(MCRYPT_3DES, '', 'cbc', '');
}
public function encrypt($data, $key, $iv)
{
mcrypt_generic_init($this->cipher, $key, $iv);
$result = mcrypt_generic($this->cipher, $data);
mcrypt_generic_deinit($this->cipher);
return $result;
}
public function decrypt($encryptedData, $key, $iv)
{
mcrypt_generic_init($this->cipher, $key, $iv);
$result = mdecrypt_generic($this->cipher, $encryptedData);
mcrypt_generic_deinit($this->cipher);
$result = rtrim($result, "\0");
return $result;
}
}
// Before 5.4.0
if (!function_exists('hex2bin')) {
function hex2bin($data)
{
$len = strlen($data);
return pack("H" . $len, $data);
}
}

Encryption in PHP leaves unwanted characters

I have made an encryption function which encrypts a simple value and stores it in the database. Here is the code to encrypt and decrypt:
public function encrypt($string){
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$value = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $this->key256, $string, MCRYPT_MODE_ECB, $iv);
$value = base64_encode($value);
return $value;
}
public function decrypt($string){
$value = base64_decode($string);
$value = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $this->key256, $value, MCRYPT_MODE_ECB);
return $value;
}
When I encrypt a simple value such as 'Michael' and decrypt again, I get the value:
Michael���������
Is there a reason I get all those question marks or a way to get rid of them?
In my experience, those extra character are NULL-bytes used for padding, that has been preserved after decryption.
You should try changing your decrypt() function to:
public function decrypt($string){
$value = base64_decode($string);
$value = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $this->key256, $value, MCRYPT_MODE_ECB);
return trim($value, "\0");
}
use bin2hex() instead of bas64_encode() and you can use the hex2bin() before decryption instead of base64_decode()
protected function hex2bin($hexdata)
{
$bindata = '';
for ($i = 0; $i < strlen($hexdata); $i += 2) {
$bindata .= chr(hexdec(substr($hexdata, $i, 2)));
}
return $bindata;
}
Ofcourse you can use hex2bin() in PHP., this custom code is for compatibility with Java like platforms.
I do it this way. May be you can give a try.
Thanks

Categories