How to secure variable send through URL? - php

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;

Related

PHP encryption empty string

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);
// ^^^^^

PHP Soap fill header credentials

I'm connecting by Soap to a webservice and I need to fill the header credentials in order to login.
$user_id = 'MyUserId';
$unique_key = $this->getUniqueKey();
$base_password = $this->getFieldBase('MyPassword', $uniqueKey);
$base_date = $this->getFieldBase(gmdate('Y-m-d\TH:i:s\.00\Z'), $unique_key);
$nonce = $this->getFieldNonce($unique_key, '.myPemFile.pem');
<wss:UsernameToken>
<wss:Username>' . $user_id . '</wss:Username>
<wss:Password>' . $base_password . '</wss:Password>
<wss:Nonce>' . $nonce . '</wss:Nonce>
<wss:Created>' . $base_date . '</wss:Created>
</wss:UsernameToken>
All values (except username) as to follow a structure.
I have this working for a 5.6 PHP project but now I need to adapt it to a PHP 7 project, and that means I can no longer use mcrypt_encrypt() because it's deprecated and therefore I need to use openssl_encrypt()
My current functions are:
private function getFieldBase($data, $key)
{
$ivsize = openssl_cipher_iv_length('AES-128-ECB');
$iv = openssl_random_pseudo_bytes($ivsize);
$ciphertext = openssl_encrypt($data, 'AES-128-ECB', $key, 0, $iv);
return trim(base64_encode($ciphertext));
}
private function getFieldNonce($data, $pbkey)
{
openssl_public_encrypt($data, $crypttext, openssl_pkey_get_public(file_get_contents($pbkey)));
return base64_encode($crypttext);
}
private function getUniqueKey()
{
return substr(md5(uniqid(microtime())), 0, 16);
}
The problem is that when connecting to the Webservice I receive the error:
Rejected: Error: The key session is invalid. It was not
possible to decipher the field Created
Which tells me that my getFieldBase() function is wrong.
Solved.
The parameter RAW_OUTPUT must be true within the function openssl_encrypt.
private function getFieldBase($data, $key)
{
$ivsize = openssl_cipher_iv_length('AES-128-ECB');
$iv = openssl_random_pseudo_bytes($ivsize);
$ciphertext = openssl_encrypt($data, 'AES-128-ECB', $key, TRUE, $iv);
return base64_encode($ciphertext);
}

Hide url path from user

For security purpose I don't want that my users can read a url to access to a picture for example.
Actually I have
https://files.domain.com/TERFD/TES/photos/20150729-0961577ba8bc6c31e7339acf0c53969a170609038345c3a0602d646a48067c10-ANnKb.jpeg?uid=3&token=360d641dc692041cbea673a
But I prefer that the user can read the picture's path or the token
So that, I wrote the following functions :
public function encrypt($data) {
$key = "df456gfd";
$data = serialize($data);
$td = mcrypt_module_open(MCRYPT_DES,"",MCRYPT_MODE_ECB,"");
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td,$key,$iv);
$data = base64_encode(mcrypt_generic($td, '!'.$data));
mcrypt_generic_deinit($td);
return $data;
}
public function decrypt($data) {
$key = "df456gfd";
$td = mcrypt_module_open(MCRYPT_DES,"",MCRYPT_MODE_ECB,"");
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td,$key,$iv);
$data = mdecrypt_generic($td, base64_decode($data));
mcrypt_generic_deinit($td);
if (substr($data,0,1) != '!')
return false;
$data = substr($data,1,strlen($data)-1);
return unserialize($data);
}
My URL is now:
https://files.domain.com/NcGDHiMnmM3fYW2W03ulyJdlCp6FaXCYDlxzWe74zH63+YpfUSPuKnxWIG1C1WNNjw/jU7coduYchvf44Lh4yiVdcL7uyx4vA4oOj14keiohQ9geIYVxsa4n07E0TXbstSETbhqGejE03Ai5hGcJEa7U/aA7z1fRkQEAxepH9j6yu+tQZESp3dXg7JUvVffI9lbpPtbGLj8=
I can decrypt it from files.domain.com and return the requested file.
Is it a good practice ?
Thx
You're actually just slowing down your application with this practice. Honestly, you're making it too complex. Why not use something like base64_encode() and base64_decode(). These functions are actually faster than your decryption and encryption functions.

Passing and protecting $_GET[] variables from one server to another

I want to pass some variable to the URL using PHP $_GET['']; for example:
I have a form on a landing page with five input fields: Name, Surname, Email, Confirm-Email, Phone I pick these variables up now I want to add these to a Base URL so that they can be picked up by another web page.
My question is how safe is this and what is the best method to protect these variables or perhaps make them invisible under the new url...?
I could use php curl() or sockets but the server where I want to send the data to does not allow me to so thats why I want to use $_GET['']'
You should not use $_GET if you want to make your data secure.
There is no option using which you can make $_GET secure or invisible.
You should use $_POST for sending data to other url if you do not want to make your data visible and secure.
Even your data is not stored by browser when you use post method and it is more difficult to hack.
It's unsafe, as URI parameters can be edited by anyone and anything. Best method to "protect" those is to encrypt them when sending (which means the recipient must be able to decrypt them) combined with a checksum to make sure none of the parameters were altered. Another type of protection is not using HTTP but using HTTPS instead, of course.
Both GET and POST is unsafe if you're not using HTTPS.
So if you have to use GET to submit your form, a verify token is suggeseted. Like OAuth, server will return the data through GET, but there's a access_token to protect data.
Encode your variables first, then decode it on the other server. this way no one can easily revert it. Make sure to change var $skey = "SecretKey0001"; to something else.
<?php
class Encryption {
var $skey = "SecretKey0001"; // you can change it
public function safe_b64encode($string) {
$data = base64_encode($string);
$data = str_replace(array('+','/','='),array('-','_',''),$data);
return $data;
}
public function safe_b64decode($string) {
$data = str_replace(array('-','_'),array('+','/'),$string);
$mod4 = strlen($data) % 4;
if ($mod4) {
$data .= substr('====', $mod4);
}
return base64_decode($data);
}
public function encode($value){
if(!$value){return false;}
$text = $value;
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $this->skey, $text, MCRYPT_MODE_ECB, $iv);
return trim($this->safe_b64encode($crypttext));
}
public function decode($value){
if(!$value){return false;}
$crypttext = $this->safe_b64decode($value);
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$decrypttext = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $this->skey, $crypttext, MCRYPT_MODE_ECB, $iv);
return trim($decrypttext);
}
}
$data_array['Name'] = 'Name';
$data_array['Surname'] = 'Surname';
$data_array['Email'] = 'Email';
$data_array['Confirm-Email'] = 'Confirm-Email';
$data_array['Phone'] = 'Phone';
$data_json = json_encode($data_array);
$encrypt = new Encryption;
$encoded_vars = $encrypt->encode($data_json);
$BASE_URL = 'http://example.com?data=' . $encoded_vars;
echo $BASE_URL;
echo "<br>";
// reverse
$decrypt = new Encryption;
echo $decoded_vars = $decrypt->decode($encoded_vars);
echo "<br>";
$data = json_decode(urldecode($decoded_vars), true);
echo "<br>";
print_r($data);
?>
DEMO: http://sandbox.onlinephpfunctions.com/code/ef1acdcad0272d5d99e21b07183a479f564ac64c

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