Possible Duplicate:
PHP 2-way encryption: I need to store passwords that can be retrieved
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 hash their information, I can't retrieve it for later use.
Base64 is decrypt-able so there's 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?
This question is related to
php
mcrypt
encryption
scramble
Security warning: This code is not secure.
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);
Security Warning: This class is not secure. It's using Rijndael256-ECB, which is not semantically secure. Just because "it works" doesn't mean "it's secure". Also, it strips tailing spaces afterwards due to not using proper padding.
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 secret String";
$converter = new Encryption;
$encoded = $converter->encode($str );
$decoded = $converter->decode($encoded);
echo "$encoded<p>$decoded";
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.
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)
Securiy Warning: This code is insecure. In addition to being vulnerable to chosen-ciphertext attacks, its reliance on
unserialize()
makes it vulnerable to PHP Object Injection.
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.
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.
The best idea to encrypt/decrypt your data in the database even if you have access to the code is to use 2 different passes a private password (user-pass
) for each user and a private code for all users (system-pass
).
Scenario
user-pass
is stored with md5 in the database and is being used to validate each user to login to the system. This user-pass is different for each user.system-pass
for the encryption/decryption of the data. This system-pass is the same for each user.Source: Stackoverflow.com