PHP encryption empty string - php

I have this code
define('CRYPTKEY','rx4/YK51nJo7LuRnZAz/jpXZbCunkNplneL6ugkBs5g=');
define('CRYPTALGO','aes-256-cbc');
public function crypt($text){
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
$encryption_key = base64_decode(CRYPTKEY);
$cryptedid = openssl_encrypt ($newid,CRYPTALGO,$encryption_key,0,$iv);
return base64_encode($cryptedid.'::'.$iv);
}
public function decrypt($text){
$encryption_key = base64_decode(CRYPTKEY);
list($encrypted_data, $iv) = explode('::', base64_decode($text), 2);
return openssl_decrypt($encrypted_data,CRYPTALGO,$encryption_key,0,$iv);
}
CRYPTKEY was created like this :
base64_encode(openssl_random_pseudo_bytes(32));
But I keep having a empty string as decoded text ....
Somebody can help me to figure out why ?

You are not using $text anywhere in your crypt() function. Thus you encrypt an empty ('non-existing') string.
You'll have to change $newid (in crypt()) to $text to make it work. Like this:
$cryptedid = openssl_encrypt($text,CRYPTALGO,$encryption_key,0,$iv);
// ^^^^^

Related

mcrypt_decrypt is returning a null repsonse

I can encrypt strings in php but I cannot decrypt my strings in php when calling the decrypt function, I get a null response. What am I doing wrong? my code is below.
<?php
$txt = "Hello";
$mykey = "mysecretkey12345";
$iv_to_pass_to_decryption = 'mysecretpass23456';
function encrypt($text, $key)
{
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), MCRYPT_RAND);
$iv_to_pass_to_decryption = base64_encode($iv);
return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CBC, $iv));
}
function decrypt($text, $key, $ivdecrypt)
{
$text = base64_decode($text);
$ivdecrypt = base64_decode($ivdecrypt);
return base64_decode(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CBC, $ivdecrypt));
}
$encryptdata = encrypt($txt, $mykey); // encrypt works fine
$decryptdata = decrypt($encryptdata, $mykey, $iv_to_pass_to_decryption); // Im getting null response from decrypt
echo 'Encrypt: ' . $encryptdata . ' Decrypt: ' . $decryptdata;
?>
Example echo output is:
Encrypt: j42DGZVT/cKIWEe5p3289aWGOZCtZ8yN3MuUidi2InM= Decrypt:
There are two issues I see:
a) The encrypt function assigns the iv to a local variable. You can make it global by including global $iv_to_pass_to_decryption;at the beginning of the encrypt function.
b) In the return statement of the decrypt function you base_decode the message. But you don't encode it going in. Just remove the base64_decode after return.

PHP replace mcrypt_cbc with mcrypt_generic

I have functions in PHP (5.3) and I had to upgrade PHP to be able to use current SDKs. Now I get follwoing Error:
Deprecated: Function mcrypt_cbc() is deprecated
I looked into the new mcrypt_generic as http://php.net/manual/de/function.mcrypt-cbc.php tells me and I tried to convert it but I never get the same result as with the old functions. Can anyone help me with converting. It already took me a long time to create the first functions because I am not into that crypting things a lot and now I am having a hard time to get it right.
Thank you very much!!!
function decode ($string)
{
$skey = "testKey";
$siv = "testSIV";
$keyArray = utf8_encode($skey);
$toEncryptArray = base64_decode($string);
$iv = utf8_encode($siv);
$dec = mcrypt_cbc(MCRYPT_3DES, $keyArray, $toEncryptArray, MCRYPT_DECRYPT, $iv);
$dec = utf8_decode($dec);
return $dec;
}
function encode($string)
{
$skey = "testKey";
$siv = "testSIV";
$keyArray = utf8_encode($skey);
$toEncryptArray = utf8_encode($string);
$iv = utf8_encode($siv);
$enc = mcrypt_cbc(MCRYPT_3DES, $keyArray, $toEncryptArray, MCRYPT_ENCRYPT, $iv);
$enc = base64_encode($enc);
return $enc;
}

How to secure variable send through URL?

I'm using PHP and CI framework, I want to send variable through URL but I want it to be somewhat encrypted.
For example i want to send variable named id:
www.trythis.com/site?id=123
I want it to be
www.trythis.com/site?id=VkxSiOW31S
The encrypted text is just an example.
How can I do that? or is there CI function that can do this?
Note: I already try base64_encode but it somehow can't be used in CI due to its special characters such as ==.
CodeIgniter has Encryption Class. You can use that class to encrypt and decrypt. To configure follow the steps
Setting your Key
$config['encryption_key'] = "YOUR KEY";
Initializing the Class
$this->load->library('encrypt');
To encode use
$id = '123';
$encrypted_id = $this->encrypt->encode($id);
//$url = 'www.trythis.com/site?id=' . $encrypted_id;
And to decode
//$encrypted_id = $_GET['id'];
$decrypted_id = $this->encrypt->decode($encrypted_id);
I made this class for the same purpose:
class Cypher
{
public $encrypted;
public $decrypted;
public function __construct($_value) {
$this->encrypted = $this->encrypting($_value);
$this->decrypted = $this->decrypting($_value);
}
private function encrypting($_value) {
$key = pack('H*', "bcb04b7e103a0cd8b54763051cef08bc55abe029fdebae5e1d417e2ffb2a00a3");
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$utf8 = utf8_encode($_value);
$cipher = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $utf8, MCRYPT_MODE_CBC, $iv);
$cipher = $iv.$cipher;
$base64 = base64_encode($_value);
return $base64;
}
private function decrypting($_value) {
return base64_decode($_value);
}
}
Let's try your example:
$cypher = new Cypher('123');
header("location: www.trythis.com/site?id=".$cypher -> encrypted);
On www.trythis.com/site page:
$id = isset($_GET['id']) ? new Cypher($_GET['id']) : "";
echo $id -> decrypted;

php: how to generate different output for same string

Is there some way to generate different output for same given string, here is example:
echo md5('test');
That always generates same fb469d7ef430b0baf0cab6c436e70375 for the given input. How do I generate different encrypted text each time and be able to decrypt it later if needed ?
I have seen functions such as md5, base64_encode, crypt, sha1, etc but they generate same output and secondly I cannot decrypt later if needed.
P.S: I know I can go with one way encryption and compare encrypted texts but for a particular scenario, I have requirement to be able to decrypt text completely if needed later however I am not able to figure out if there is some way or function in php for it.
Any help will be greatly appreciated. Thanks
To encrypt the same plaintext so that it generates different ciphertext you change the key (and/or Initialization Vector (IV) depending on the mode of the algorithm, like CBC).
Example:
$string = 'Some Secret thing I want to encrypt';
$iv = '12345678';
$passphrase = '8chrsLng';
$encryptedString = encryptString($string, $passphrase, $iv);
// Expect: 7DjnpOXG+FrUaOuc8x6vyrkk3atSiAf425ly5KpG7lOYgwouw2UATw==
function encryptString($unencryptedText, $passphrase, $iv) {
$enc = mcrypt_encrypt(MCRYPT_BLOWFISH, $passphrase, $unencryptedText, MCRYPT_MODE_CBC, $iv);
return base64_encode($enc);
}
Both the same IV and the passphrase must be used when decrypting in CBC mode. The passphrase MUST be kept a secret (from eavesdroppers) while the IV can be transmitted in the clear.
You CAN (but should not) use the same passphrase for every message/data but you should ALWAYS change the IV for each message/data.
This is the basics of encryption but depending on you needs you may need to modify your architecture to keep the system secure.
md5 is a hash method, not an encryption.
in short. there is no "good" way back from md5.
base64_encode and base64_decode and be used to transport messages, but it is no decryption.
please google on the topic RSA, ROT-13 or basic encryption with php.
I have created this class (Thanks to #Sani Huttunen for the idea) for the purpose. It allows to have differ text generated each time even for same input text and decodes it successfully as well.
class Encoder
{
private static $prefix = '#!#';
public static function php_aes_encrypt($text, $key)
{
if (!trim($text)) {
return '';
}
$iv = self::generateRandomString();
$key = self::mysql_aes_key($key);
$pad_value = 16 - (strlen($text) % 16);
$text = str_pad($text, (16 * (floor(strlen($text) / 16) + 1)), chr($pad_value));
$ciphertext = mcrypt_encrypt(
MCRYPT_RIJNDAEL_128,
$key,
$text,
MCRYPT_MODE_CBC,
$iv
);
$ciphertext = self::getPrefix() . base64_encode($ciphertext . $iv);
return $ciphertext;
}
public static function php_aes_decrypt($text, $key)
{
$text = str_replace(self::getPrefix(), '', $text);
$text = base64_decode($text);
if (!trim($text)) {
return '';
}
$iv = substr($text, -16);
$text = str_replace($iv, '', $text);
$key = self::mysql_aes_key($key);
$text = mcrypt_decrypt(
MCRYPT_RIJNDAEL_128,
$key,
$text,
MCRYPT_MODE_CBC,
$iv
);
return rtrim($text, "\0..\16");
}
private static function mysql_aes_key($key)
{
$new_key = str_repeat(chr(0), 16);
for ($i = 0, $len = strlen($key); $i < $len; $i ++) {
$new_key[$i % 16] = $new_key[$i % 16] ^ $key[$i];
}
return $new_key;
}
private static function getPrefix()
{
return base64_encode(self::$prefix);
}
public static function isEncrypted($ciphertext)
{
$isEncrypted = (false !== strpos($ciphertext, self::getPrefix()));
return $isEncrypted;
}
private static function generateRandomString()
{
return substr(sha1(rand()), 0, 16);
}
}
Usage:
$encrypted = Encoder::php_aes_encrypt('my test string', 'key');
echo $encrypted . '<br>';
echo Encoder::php_aes_decrypt($encrypted, 'key');

Using defined security variables inside a function

I found out that I should not use global variables like global $auth_key for sensitive data's (Correct me if that's not true.) so I wanted to use defined variables for storing security keys.
Inside config.php salt keys are defined.
define('AUTH_KEY','::~K~UC*[tlu4Eq/]Lm|h');
define('SECURE_AUTH_KEY', 'QsTMvbV+tuU{K26!]J2');
In encryption.php contains the encryption functions where AUTH_KEY and SECURE_AUTH_KEY will be used inside.
function encrypt_text($value) {
if(!$value) return false;
$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, **AUTH_KEY_HERE**, $value, MCRYPT_MODE_ECB, **SECURE_AUTH_KEY_HERE**);
return trim(base64_encode($crypttext));
}
function decrypt_text($value) {
if(!$value) return false;
$crypttext = base64_decode($value);
$decrypttext = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, **AUTH_KEY_HERE**, $crypttext, MCRYPT_MODE_ECB, **SECURE_AUTH_KEY_HERE**);
return trim($decrypttext);
}
Is there a way to do that? or any other solutions you can recommend? Please note that these keys are real important for encryption of sensitive informations.
Also, a another question, what is the maximum length of keys to be used on mcrypt?
Thank you and looking forward for reply of yours.
as a rule: the logner the key, the stonger the encryption. Secondly, don't use ECB unless your data is very short, you ought to use CBC or something stronger. Third: use a salt or initialization vector. Lastly read this: https://www.owasp.org/index.php/Cryptographic_Storage_Cheat_Sheet
Using a constant is just like using a variable except there is no dollar sign.
$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, AUTH_KEY, $value, MCRYPT_MODE_ECB, SECURE_AUTH);
There is nothing inherently more secure in this approach over using the global key word. Though this approach is preferred. By using a constant you are saying this is a static value I will use across the application. Having to use global on the other hand is often just a result of bad design or laziness. It leads to code that is hard to follow, abusing what scoping tries to accomplish.
Key length is dependent on the encryption algorithm used. RTM.
Yes you can use the define variable like you are doing, see the example
define('AUTH_KEY','::~K~UC*[tlu4Eq/]Lm|h');
function abc()
{
echo AUTH_KEY;
}
abc(); // ::~K~UC*[tlu4Eq/]Lm|h
http://codepad.viper-7.com/tUAg6D
Although choosing constants would be preferable over plain variables, this kind of information is better stored inside a configuration file rather than your code.
Also, for better reuse and avoid having those global values lying around it would be a better idea to encapsulate the functionality:
class MyCrypto
{
private $key;
private $cipher;
private $mode;
public function __construct($key, $cipher, $mode = "cbc")
{
$this->key = $key;
$this->cipher = $cipher;
$this->mode = $mode;
}
public function generate_salt()
{
return mcrypt_create_iv(
mcrypt_get_iv_size($this->cipher, $this->mode),
MCRYPT_DEV_URANDOM
);
}
public function encrypt($data) { ... }
public function decrypt($data) { ... }
}
I've added a salt generator function to be used for every encryption operation;
Lastly, I would recommend using CBC mode - MCRYPT_MODE_CBC.
Update (27/09/17):
Since mcrypt_encrypt is DEPRECATED as of PHP 7.1.0. Ive added a simple encrypt/decrypt using openssl.
function encrypt($string, $key = 'PrivateKey', $secret = 'SecretKey', $method = 'AES-256-CBC') {
// hash
$key = hash('sha256', $key);
// create iv - encrypt method AES-256-CBC expects 16 bytes
$iv = substr(hash('sha256', $secret), 0, 16);
// encrypt
$output = openssl_encrypt($string, $method, $key, 0, $iv);
// encode
return base64_encode($output);
}
function decrypt($string, $key = 'PrivateKey', $secret = 'SecretKey', $method = 'AES-256-CBC') {
// hash
$key = hash('sha256', $key);
// create iv - encrypt method AES-256-CBC expects 16 bytes
$iv = substr(hash('sha256', $secret), 0, 16);
// decode
$string = base64_decode($string);
// decrypt
return openssl_decrypt($string, $method, $key, 0, $iv);
}
$str = 'Encrypt this text';
echo "Plain: " .$str. "\n";
// encrypt
$encrypted_str = encrypt($str);
echo "Encrypted: " .$encrypted_str. "\n";
// decrypt
$decrypted_str = decrypt($encrypted_str);
echo "Decrypted: " .$decrypted_str. "\n";
In your example, you are using the same initialization vector **SECURE_AUTH_KEY_HERE** when you can allow PHP to create the iv for you this way you only need 1 SECURE_KEY defined.
<?php
define('SECURE_KEY',md5('your secret key'));
/**
* Encrypt a value
*/
function encrypt($str){
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
return mcrypt_encrypt(MCRYPT_RIJNDAEL_256, SECURE_KEY, $str, MCRYPT_MODE_ECB, $iv);
}
/**
* Decrypt a value
*/
function decrypt($str){
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, SECURE_KEY, $str, MCRYPT_MODE_ECB, $iv));
}
//32
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
//Create an initialization vector (IV) from a random source
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
echo decrypt(encrypt('Encrypt me'));
?>

Categories