可能的重复: PHP 2-way加密:我需要存储可以检索的密码

我计划在我的网站上为我的用户存储国外帐户信息,又名rapidshare用户名和密码等…我想保证信息的安全,但我知道如果我散列了他们的信息,我就不能检索它以供以后使用。

Base64是可解密的,所以直接关闭没有意义。 我的想法是打乱用户并在它被base64ed之前和之后传递即使在你解密它之后,如果你试图解密,你会得到一些有趣的文本。是否有一个php函数,它接受的值将对字符串进行唯一的打乱,并在稍后重新输入值时解除打乱?

有什么建议吗?


当前回答

安全警告:此代码不安全。除了容易受到选择密文攻击之外,它对unserialize()的依赖使其容易受到PHP对象注入的攻击。

要处理字符串/数组,我使用这两个函数:

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;
}

它很灵活,因为你可以通过URL存储/发送字符串或数组,因为字符串/数组在加密之前是序列化的。

其他回答

即使您可以访问代码,对数据库中的数据进行加密/解密的最佳方法是使用两个不同的密码:每个用户的私有密码(user-pass)和所有用户的私有代码(system-pass)。

场景

user-pass与md5一起存储在数据库中,用于验证每个用户登录到系统。这个用户通行证对于每个用户都是不同的。 数据库中的每个用户条目都有一个用于数据加密/解密的系统密码。这个system-pass对于每个用户都是相同的。 每当用户从系统中删除时,所有在旧系统密码下加密的数据都必须在新的系统密码下再次加密,以避免安全问题。

安全警告:此代码不安全。

工作示例

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

查看mycrypt(): http://us.php.net/manual/en/book.mcrypt.php

如果你使用postgres有pgcrypto用于数据库级加密。(便于搜索和分类)

在处理加密时,有一件事你应该非常清楚:

试图变得聪明,发明自己的东西通常会给你留下一些不安全的东西。

最好使用PHP附带的一种加密扩展。

安全警告:这个类不安全。它使用的是Rijndael256-ECB,这在语义上并不安全。仅仅因为“它有效”并不意味着“它是安全的”。此外,由于没有使用适当的填充,它会剥离后面的空间。

最近发现这个类,它的工作就像一个梦!

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);
    }
}

我们称它为:

$str = "My secret String";

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

echo "$encoded<p>$decoded";