0

I wrote a little class to send private data with the url (can't use cookies/sessions or anything else for it). I encrypt/decrypt it with PHP's mcrypt and also base64-en/decoded it for use in the url.

Unfortunately I still end up with wrong results from time to time. I noticed that this always happens when at least a + appears in the url. I also played around with rawurlencode and urlencode/ urldecode, without success. I also tried strtr() the encrypted data, but somehow the + still appear. Anyone got an idea ?

Here's my class:

class crypto 
{
    public function __construct()
    {
        $this->iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
        $this->iv = mcrypt_create_iv($this->iv_size, MCRYPT_RAND);
        $this->llave = 'da332sdf9'; 
    }

    public function make_crypt($string)
    {   
        $crypt = mcrypt_encrypt(MCRYPT_BLOWFISH, $this->llave, $string, MCRYPT_MODE_ECB, $this->iv);
        $crypt = rawurlencode(base64_encode($crypt));
        $crypt = strtr($crypt, '+/', '-_');     
        return $crypt;
    }

    public function get_crypt($data)
    {   
        $crypt = strtr($crypt, '-_', '+/');     
        $data = base64_decode($data);
        $decrypted = mcrypt_decrypt (MCRYPT_BLOWFISH, $this->llave, $data, MCRYPT_MODE_ECB, $this->iv);
        return $decrypted;
    }
}
Anonymous
  • 3,679
  • 6
  • 29
  • 40
  • You should run both the IV and the encrypted text through rawurlencode (not urlencode) before sticking it into the link. Maybe look [there](http://stackoverflow.com/a/5758002/461212) – hornetbzz Apr 24 '12 at 11:39
  • 1
    A little sidenote, since you are using ECB mode then you can ignore IV entirely. It is not used in ECB mode. IV is only used in CBC mode. – kingmaple Apr 24 '12 at 11:43

2 Answers2

1

What do you mean you tried URL encoding 'without success'? URL encoding the value does work, otherwise the function would be broken. I use it in my framework and have no errors.

Are you sure you are encoding the crypted value? Don't encode the entire URL.

kingmaple
  • 4,200
  • 5
  • 32
  • 44
  • I'm only encoding the encrypted value. Somehow the `+` won't disappear :( – Anonymous Apr 24 '12 at 11:39
  • Can you show code that builds your URL? Because bug must be there. rawurlencode() does encode + sign. – kingmaple Apr 24 '12 at 11:44
  • AAAARRRRRGH! While wanting to post the code that builds my URL, I saw that I put a wrong `urldecode()` in front of it in my rage of fixing. Later I only sat in front of the crypto class and ignored that. Now it logically works. Thanks for that little hint ;) – Anonymous Apr 24 '12 at 11:51
1

Observations

$crypt = strtr($crypt, '-_', '+/'); ?? where is crypt defined ???

rawurlencode where is the decoding ....

I always prefer to HEX so that i don't have to worry about url safe characters

Sample Test your current class would Fail

$crypt = new Crypto ();
echo "<pre>";
for($i = 0; $i < 10; $i ++) {
    $pass = generatePassword ( mt_rand ( 5, 10 ) );
    $test = $crypt->make_crypt ( $pass );
    $output = $crypt->get_crypt ( $test );

    if ($pass == $output) {
        echo " $pass ($test) = $output \n";
    } else {
        var_dump ( $pass, $output );
        echo " $pass ($test) != $output \n";
    }
}

Solution

class Crypto {

    private $iv_size;
    private $iv;
    private $llave;

    public function __construct() {
        $this->iv_size = mcrypt_get_iv_size ( MCRYPT_BLOWFISH, MCRYPT_MODE_ECB );
        $this->iv = mcrypt_create_iv ( $this->iv_size, MCRYPT_RAND );
        $this->llave = 'da332sdf9';
    }

    public function make_crypt($string) {
        $crypt = mcrypt_encrypt ( MCRYPT_BLOWFISH, $this->llave, $string, MCRYPT_MODE_ECB, $this->iv );
        return bin2hex ( $crypt );
    }

    public function get_crypt($data) {
        $data = pack ( "H*", $data );
        $decrypted = mcrypt_decrypt ( MCRYPT_BLOWFISH, $this->llave, $data, MCRYPT_MODE_ECB, $this->iv );
        return trim ( $decrypted );
    }
}

Solution Output

 tXHhC8fk4 (b929695d39555523348051a72d15baaf) = tXHhC8fk4 
 drKH9 (909994926fe5cd30) = drKH9 
 mNwh6K (10af1bb381338943) = mNwh6K 
 CJZvqwGX (aa705c290759b18d) = CJZvqwGX 
 Jt4W7j (bc7ee842041b9860) = Jt4W7j 
 tgCHXyPvm (9f46b74ef59ee70da1dda30b3e52fe92) = tgCHXyPvm 
 LYxhVj (9e2079cff9d54007) = LYxhVj 
 kR8WLwh3T (3e4606d65defc74f3c82af5fb095f41d) = kR8WLwh3T 
 Z8NqWM6RHj (1d9eea2358674d78cc43e024cba5ba48) = Z8NqWM6RHj 
 TtqRf7M (09ef38114bb729c4) = TtqRf7M 

Function Used to generate Data

function generatePassword($length = 8) {
    $password = "";
    $possible = "2346789bcdfghjkmnpqrtvwxyzBCDFGHJKLMNPQRTVWXYZ";
    $maxlength = strlen ( $possible );
    if ($length > $maxlength) {
        $length = $maxlength;
    }
    $i = 0;
    while ( $i < $length ) {
        $char = substr ( $possible, mt_rand ( 0, $maxlength - 1 ), 1 );
        if (! strstr ( $password, $char )) {
            $password .= $char;
            $i ++;
        }

    }
    return $password;

}
Baba
  • 94,024
  • 28
  • 166
  • 217