使用PHP加密和解密密码的最佳方法?

jie*_*exi 216 php encryption scramble mcrypt

可能重复:
PHP双向加密:我需要存储可以检索的密码

我计划在我的网站上为我的用户存储外国帐户信息,也就是用户名和密码等等...我想保证信息的安全,但我知道如果我散列他们的信息,我无法检索它以供以后使用.

Base64是可解密的,所以没有必要使用它只是简单的关闭.我的想法是加扰用户并在它解密之前和之后通过这种方式传递,如果你尝试解密,你会得到一些看起来很有趣的文本.是否有一个php函数接受将进行字符串的唯一加扰的值,并在以后重新计算该值时对其进行解扰?

有什么建议?

Ali*_*xel 300

你不应该加密密码,而应该使用像bcrypt这样的算法来对它们进行哈希处理.这个答案解释了如何在PHP中正确实现密码散列.不过,以下是加密/解密的方法:

$key = 'password to (en/de)crypt';
$string = ' string to be encrypted '; // note the spaces
Run Code Online (Sandbox Code Playgroud)

要加密:

$iv = mcrypt_create_iv(
    mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC),
    MCRYPT_DEV_URANDOM
);

$encrypted = base64_encode(
    $iv .
    mcrypt_encrypt(
        MCRYPT_RIJNDAEL_128,
        hash('sha256', $key, true),
        $string,
        MCRYPT_MODE_CBC,
        $iv
    )
);
Run Code Online (Sandbox Code Playgroud)

要解密:

$data = base64_decode($encrypted);
$iv = substr($data, 0, mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC));

$decrypted = rtrim(
    mcrypt_decrypt(
        MCRYPT_RIJNDAEL_128,
        hash('sha256', $key, true),
        substr($data, mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC)),
        MCRYPT_MODE_CBC,
        $iv
    ),
    "\0"
);
Run Code Online (Sandbox Code Playgroud)

警告:上面的示例对信息进行加密,但不会对密文进行身份验证以防止篡改.你应该依赖于安全性未经验证的加密所提供易受填充神谕攻击以来,特别是代码.

也可以看看:

此外,不要只使用"密码"作为加密密钥.加密密钥是随机字符串.


在3v4l.org上演示:

echo 'Encrypted:' . "\n";
var_dump($encrypted); // "m1DSXVlAKJnLm7k3WrVd51omGL/05JJrPluBonO9W+9ohkNuw8rWdJW6NeLNc688="

echo "\n";

echo 'Decrypted:' . "\n";
var_dump($decrypted); // " string to be encrypted "
Run Code Online (Sandbox Code Playgroud)

  • 实际上,不是"一些随机",而是"随机存储之后".) (20认同)
  • 我的天啊.即使作为如何存储密码的建议,这也是不好的.它甚至不可逆(所以你为什么首先使用加密)...而且它不使用bcrypt(你在第一行提到).至于如何加密数据,请看一下[SO Answer](http://stackoverflow.com/questions/5089841/php-2-way-encryption-i-need-to-store-passwords-that-可以检索/ 5093422#5093422)其中包括正确设置它的正确工具......示例:您缺少填充(CBC需要)... (13认同)
  • 好吧,在深入查看代码之后,你根本就不存储密码.您使用密码作为密钥来存储其他数据.**所以这甚至都没有回答这个问题.**如果你这样做,你需要**首先在密码上使用密钥派生函数.像"PBKDF2"...... (10认同)
  • @ wired00:不,一点也不!如果解密加密的字符串,您会注意到字符串末尾添加了一些NULL字节.通常人们只是使用`[r] trim()`去除那些NULL字节,但是在进程空间中也被删除了.我添加了空格,以便人们可以测试并验证修剪解密字符串的正确方法是:`$ original = rtrim($ decrypted,"\ 0");` - 注意`\ 0`.=) (5认同)
  • 我只是想知道`$ string`周围空间的重要性.是否在加密前人工添加以增加破解难度?对不起,如果我错过了那一点;) (2认同)
  • 因为这不是他的密码!在用户输入密码进行注册,然后再次登录以进行登录的情况下,散列是有意义的 - 您只需将两者都哈希,比较登录时的哈希值,如果它们相同,则密码是相同的.OP正在谈论存储其他网站的密码 - 实际上他正在为其他网站保存密码.哈希对他没用,他需要使用明文密码登录,但他不想将其存储为明文...所以它需要是可逆加密. (2认同)

wil*_*age 33

安全警告:此类不安全.它使用的是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);
    }
}
Run Code Online (Sandbox Code Playgroud)

并称之为:

$str = "My secret String";

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

echo "$encoded<p>$decoded";
Run Code Online (Sandbox Code Playgroud)

  • 不不不.这个不好.首先,它使用ECB模式,这是不好的.然后,它使用不安全的方法生成IV.它根本不会以安全的方式工作.相反,看看[这个答案提供]的东西(http://stackoverflow.com/questions/5089841/php-2-way-encryption-i-need-to-store-passwords-that-c​​an-be-检索/ 5093422#5093422)或只是使用一个库.**这不安全** (15认同)
  • `//你可以改变它``应该是`//你必须改变它' (7认同)
  • 这个答案不会产生安全的密码文本,请不要使用.它只能在加密/解密的意义上起作用. (6认同)

小智 18

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

工作实例

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); 
Run Code Online (Sandbox Code Playgroud)

  • 这个答案不会产生安全的密码文本,请不要使用.它只能在加密/解密的意义上起作用. (12认同)
  • 样品不好; 因为ECB,使用ECB编码,首先使用ECB编码,而不使用AES兼容代码,而不是正确填充消息,因此IV完全不是随机的两次.是的,它的工作方式与[xkcd上的随机数生成器](http://xkcd.com/221/)相同. (9认同)

Seb*_*olm 12

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

试图聪明并发明自己的东西通常会给你一些不安全的东西.

您可能最好使用PHP附带的加密扩展之一.