Wednesday, May 30, 2012

Best way to use PHP to encrypt and decrypt?


I plan to store foreign account information for my users on my website, aka rapidshare username and passwords, etc... I want to keep information secure, but i know that if i md5 their information, i can't retrieve it later to use.



Base64 is decrypt-able so theres no point using that just plain off. My idea is to scramble the user and pass before and after it gets base64ed that way even after you decrypt it, you get some funny looking text if you try to decrypt. Is there a php function that accepts values that will make an unique scramble of a string and de-scramble it later when the value is reinputed?



Any suggestions?



(btw, i've already pretty much secured myself from sql injects by disallowing many symbols in the URI and cleaning out any retreived variables)


Source: Tips4all

7 comments:

  1. You should not encrypt passwords, instead you should hash them using an algorithm like bcrypt. Still, here is how you would encrypt/decrypt:

    $key = 'password to (en/de)crypt';
    $string = ' string to be encrypted '; // note the spaces


    To Encrypt:

    $encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($key), $string, MCRYPT_MODE_CBC, md5(md5($key))));


    To Decrypt:

    $decrypted = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5($key), base64_decode($encrypted), MCRYPT_MODE_CBC, md5(md5($key))), "\0");




    Demo at IDEOne.com:

    echo 'Encrypted:' . "\n";
    var_dump($encrypted); // "ey7zu5zBqJB0rGtIn5UB1xG03efyCp+KSNR4/GAv14w="

    echo "\n";

    echo 'Decrypted:' . "\n";
    var_dump($decrypted); // " string to be encrypted "

    ReplyDelete
  2. working example

    define('SALT', 'whateveryouwant');

    function encrypt($text)
    {
    return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, SALT, $text, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND))));
    }

    function decrypt($text)
    {
    return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, SALT, base64_decode($text), MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND)));
    }

    $encryptedmessage = encrypt("your message");
    echo decrypt($encryptedmessage);

    ReplyDelete
  3. Found this class recently, it works like a dream!

    class Encryption {
    var $skey = "yourSecretKey"; // 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);
    }
    }


    And to call it:

    $str = "my string i want to keep secret";

    $converter = new Encryption;
    $encoded = $converter->encode($str );
    $decoded = $converter->decode($encode);

    echo "$encoded<p>$decoded";

    ReplyDelete
  4. One thing you should be very aware of when dealing with encryption:

    Trying to be clever and inventing your own thing usually will leave you with something insecure.

    You'd probably be best off using one of the cryptography extensions that come with PHP.

    ReplyDelete
  5. To handle a string / array I use these two functions:

    function encryptStringArray ($stringArray, $key = "Your secret salt thingie") {
    $s = strtr(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($key), serialize($stringArray), MCRYPT_MODE_CBC, md5(md5($key)))), '+/=', '-_,');
    return $s;
    }

    function decryptStringArray ($stringArray, $key = "Your secret salt thingie") {
    $s = unserialize(rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5($key), base64_decode(strtr($stringArray, '-_,', '+/=')), MCRYPT_MODE_CBC, md5(md5($key))), "\0"));
    return $s;
    }


    It's flexible as in you can store/send via URL a string or array because the string/array is serialzed before encryption.

    ReplyDelete
  6. Check out mycrypt(): http://us.php.net/manual/en/book.mcrypt.php

    And if you're using postgres there's pgcrypto for database level encryption. (makes it easier to search and sort)

    ReplyDelete
  7. This will only give you marginal protection. If the attacker can run arbitrary code in your application they can get at the passwords in exactly the same way your application can. You could still get some protection from some SQL injection attacks and misplaced db backups if you store a secret key in a file and use that to encrypt on the way to the db and decrypt on the way out. But you should use bindparams to completely avoid the issue of SQL injection.

    If decide to encrypt, you should use some high level crypto library for this, or you will get it wrong. You'll have to get the key-setup, message padding and integrity checks correct, or all your encryption effort is of little use. GPGME is a good choice for one example. Mcrypt is too low level and you will probably get it wrong.

    ReplyDelete