首页 文章

使用PHP加密和解密密码的最佳方法? [重复]

提问于
浏览
212

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

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

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

有什么建议?

8 回答

  • 294

    You should not encrypt passwords, instead you should hash them using an algorithm like bcrypt. This answer explains how to properly implement password hashing in PHP. 仍然,以下是加密/解密的方法:

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

    To Encrypt:

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

    To Decrypt:

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

    Warning :以上示例对信息进行加密,但不对密文进行身份验证以防止篡改 . You should not rely on unauthenticated encryption for security,特别是因为提供的代码容易受到填充oracle攻击 .

    也可以看看:

    此外,不要只使用"password"作为加密密钥 . Encryption keys are random strings.


    Demo at 3v4l.org

    echo 'Encrypted:' . "\n";
    var_dump($encrypted); // "m1DSXVlAKJnLm7k3WrVd51omGL/05JJrPluBonO9W+9ohkNuw8rWdJW6NeLNc688="
    
    echo "\n";
    
    echo 'Decrypted:' . "\n";
    var_dump($decrypted); // " string to be encrypted "
    
  • 2

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

    如果您正在使用postgres,那么pgcrypto用于数据库级加密 . (使搜索和排序更容易)

  • 0

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

    试图聪明并发明自己的东西通常会让你感到不安全 .

    您可能最好使用PHP附带的cryptography extensions之一 .

  • 1

    安全警告:此代码不安全 . 除了易受选择密文攻击之外,它对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存储/发送字符串或数组,因为字符串/数组在加密之前是串行的 .

  • 34

    安全警告:此类不安全 . 它使用的是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";
    
  • 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);
    
  • 3

    即使您有权访问代码,加密/解密数据库中数据的最佳方法是为每个用户使用2个不同的密码( user-pass ),为所有用户使用私有代码( system-pass ) .

    Scenario

    • user-pass 与md5一起存储在数据库中,用于验证每个用户是否登录系统 . 每个用户的此用户传递是不同的 .

    • 数据库中的每个用户条目都在md5中为 system-pass 用于数据的加密/解密 . 对于每个用户,该系统传递是相同的 .

    • 每次从系统中删除用户时,必须在新的系统通过下再次加密在旧系统通道下加密的所有数据,以避免出现安全问题 .

  • 12

    这只会给你边际保护 . 如果攻击者可以在您的应用程序中运行任意代码,他们可以获得与您的应用程序完全相同的密码 . 如果将密钥存储在文件中并使用该密钥在去往数据库的路上进行加密并在出路时解密,您仍然可以从某些SQL注入攻击和错误放置的数据库备份中获得一些保护 . 但是你应该使用bindparams来完全避免SQL注入的问题 .

    如果决定加密,你应该使用一些高级加密库,否则你会弄错 . 您必须正确设置密钥设置,消息填充和完整性检查,或者您的所有加密工作都没什么用处 . GPGME是一个例子的不错选择 . Mcrypt太低了,你可能会弄错 .

相关问题