PHP sending encrypted data via the URL
Asked Answered
P

4

12

I'm trying to send encrypted data over the url to another site (using file_get_contents("anotherUrl.php?hash=$encryptedString"). The problem is, sometimes, the encryption contains some special characters, like +, and this causes the decryption to fail.

Here are my encryption / decryption methods:

public function encrypt($string, $key)
{
    return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($key), $string, MCRYPT_MODE_CBC, md5(md5($key))));
}

public function decrypt($encrypted, $key)
{
    return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5($key), base64_decode($encrypted), MCRYPT_MODE_CBC, md5(md5($key))), "\0");
}

Here's an example encrypted string which contains a +, and I'm guessing that this causes the decryption to fail.

oWCrVPaS+5GbxcQFc0fulUk/zRAkDD60av4zlPiWskE=

Any ideas how I should solve this? I've tried to do urlencode() and urldecode() on the hash, however that also seems to cause the encryption to break. Is there a way to change the encryption algorithm to get it to only return url safe characters?

Psychoanalysis answered 16/11, 2013 at 3:3 Comment(4)
Just a side question, why are you performing two successive md5 operations on the key? What do you hope to achieve from that?Gauge
@CPUTerminator Actually I've copied the function exactly as is from another answer here on SO, I've not made any changes to it.Psychoanalysis
Ehh... I don't see any point in that. If the key is weak (i.e not from a cryptographically strong random number generator) you should not be using md5 as an key-strengthening algorithm (see PBKDF#2, bcrypt or scrypt). If your key is already strong, you're just wasting processor cycles.Gauge
Where did you get the cryptography code? It's not secure.Electrothermal
W
18

Take a look at this thread:

Passing base64 encoded strings in URL

Essentially you DO want to urlencode() before sending the string, however you do NOT want to urldecode() at the other end.

Waverley answered 16/11, 2013 at 3:6 Comment(3)
Thanks, you're correct. It works with one way url encoding. ( There should be no url decode function if its not supposed to be decoded, but that's PHP for you).Psychoanalysis
There are plenty of other times where urldecode() is needed, but this is not one of them. Glad to help.Waverley
The urlencode is necessary since you are building a query string here. On the other side PHP takes that query string and urldecodes that for you, writing the result into $_GET. This is the reason for the asymmetry. If you were to parse the query string yourself, you would also have to do the urldecode yourself.Bummalo
S
8

In order to solve this problem I now use the following (after 3 hours of pain), and it works great.

Feel free to copy and paste

function encrypt($pure_string) {
    $dirty = array("+", "/", "=");
    $clean = array("_PLUS_", "_SLASH_", "_EQUALS_");
    $iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
    $_SESSION['iv'] = mcrypt_create_iv($iv_size, MCRYPT_RAND);
    $encrypted_string = mcrypt_encrypt(MCRYPT_BLOWFISH, $_SESSION['encryption-key'], utf8_encode($pure_string), MCRYPT_MODE_ECB, $_SESSION['iv']);
    $encrypted_string = base64_encode($encrypted_string);
    return str_replace($dirty, $clean, $encrypted_string);
}

function decrypt($encrypted_string) { 
    $dirty = array("+", "/", "=");
    $clean = array("_PLUS_", "_SLASH_", "_EQUALS_");

    $string = base64_decode(str_replace($clean, $dirty, $encrypted_string));

    $decrypted_string = mcrypt_decrypt(MCRYPT_BLOWFISH, $_SESSION['encryption-key'],$string, MCRYPT_MODE_ECB, $_SESSION['iv']);
    return $decrypted_string;
}
Sideband answered 28/4, 2014 at 17:59 Comment(1)
mcrypt_get_iv_size(), mcrypt_create_iv(), mcrypt_encrypt() and mcrypt_decrypt() are all deprecated in php7.1 to onwards.Greff
F
4

Instead of using Base64 for encoding your data you can also use Base32 (RFC 4648) which is URL-safe because it only uses letters A–Z (case-insensitive) and the digits 2–7. There is already a PHP library for encoding/decoding. Note that Base32 takes ~20% more space than Base64.

You can also use URLcrypt which is a handy library helping you with encryption and Base32 encoding.

Fp answered 28/10, 2014 at 16:3 Comment(0)
H
0
class Encryption {
    var $skey   = "SuPerEncKey2010"; // 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);
    }
}
Houdon answered 23/8, 2019 at 6:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.