无法解密密码

时间:2014-01-29 22:39:34

标签: php encryption-symmetric

我最近决定对我的密码使用更安全的加密。加密密码没问题,在调用mc_encrypt($encrypt)后,该方法返回加密密码。

通过调用mc_decrypt($decrypt)进行解密时,该方法返回false。正如您在mc_decrypt($decrypt)方法中看到的那样,底部附近有一个if语句。我无法通过if语句。有谁知道我可以改变什么让$calcmac!==$mac返回真实?感谢

<?php

    class Encrypt {
    public $encryptionKey = 'xxxxxxx';

    public function __construct() {
    define('ENCRYPTION_KEY', $this->encryptionKey);
    }

    // Encrypt Function
    public function mc_encrypt($encrypt){
        $encrypt = serialize($encrypt);
        $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), MCRYPT_DEV_URANDOM);
        $key = pack('H*', $this->encryptionKey);
        $mac = hash_hmac('sha256', $encrypt, substr(bin2hex($key), -32));
        $passcrypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $encrypt.$mac, MCRYPT_MODE_CBC, $iv);
        $encoded = base64_encode($passcrypt).'|'.base64_encode($iv);
        return $encoded;
    }

    // Decrypt Function
    public function mc_decrypt($decrypt){
        $decrypt = explode('|', $decrypt);
        $decoded = base64_decode($decrypt[0]);
        $iv = base64_decode($decrypt[1]);
        $key = pack('H*', $this->encryptionKey);
        $decrypted = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $decoded, MCRYPT_MODE_CBC, $iv));
        $mac = substr($decrypted, -64);
        $decrypted = substr($decrypted, 0, -64);
        $calcmac = hash_hmac('sha256', $decrypted, substr(bin2hex($key), -32));
        if($calcmac!==$mac){ return false; }
        $decrypted = unserialize($decrypted);
        return $decrypted;
    }

    }

    ?>

3 个答案:

答案 0 :(得分:4)

  

抱歉,使用存储在服务器上的秘密加密密码   不安全:如果入侵者侵入您的代码库,入侵者可以检索   使用您的代码库和存储的密码的每个密码和任何密码   (代码或持久存储中的某处)。

<{> 3}} OWASP提供了准备充分的文档:Online Web Application Security ProjectPassword Storage Cheat SheetAuthentication Cheat Sheet。看看吧!

要走的路是PHP Security Cheat Sheet

如何处理新创建的密码

  • 如果您创建新密码,请使用随机盐
  • 计算hash = HashFunction( password, salt )
  • 将数据库中的哈希值和salt保存到用户ID

如何验证密码

  • 在数据库中找到userID的记录
  • 从记录中检索哈希和盐
  • 根据用户输入登录的密码,计算hash = HashFunction( enteredPassword, salt )
  • 最后,验证从商店检索的哈希是否与计算的哈希相同。

为什么要使用哈希操作?

哈希操作是所谓的salted hash:虽然您可以轻松地计算函数,但很难计算反向函数推论:从密码计算密码哈希很容易,但是很难从密码哈希计算密码。

PHP的哈希函数

现在,PHP的trapdoor function是密码哈希PBKDF2的首选。

如果您的PHP安装太旧,即使使用md5()的盐渍哈希比使用双加密密码更好。 但只有在没有其他可用的情况下才有效!

PBKDF2使用示例

function getHashAndSaltFromString( $password ) {

   // choose a sufficiently long number of iterations 
   // ... to make the operation COSTLY
   $iterations = 1000;

   // Generate a random IV using mcrypt_create_iv(),
   // openssl_random_pseudo_bytes() or another suitable source of randomness
   $salt = mcrypt_create_iv(16, MCRYPT_DEV_RANDOM);

   $hash = hash_pbkdf2("sha256", $password, $salt, $iterations, 20);

   return array( $hash, $salt );

}

哈希使用的美妙副作用

许多网站确实将密码长度限制在一定长度 - 很可能是由于底层持久存储的长度[=数据库表中的字段长度]。

如果您使用基于哈希的密码存储技术,用户可能会使用任意长度的密码

  

由于散列长度不变,因此您只能保留密码和   盐,长度限制是多余的。 在您的网络应用中支持长密码!

在极端情况下,您甚至可以允许用户上传文件 - 例如他们家的照片 - 作为凭证​​[=密码]。

关于PHP MCRYPT函数中随机源的附注

请注意,PHP确实提供了两个随机来源MCRYPT_DEV_RANDOMMCRYPT_DEV_URANDOM

  • MCRYPT_DEV_RANDOM/dev/random
  • 获得随机性
  • MCRYPT_DEV_URANDOM/dev/urandom
  • 获得随机性
每次查询时,

/dev/urandom都会立即提供随机数据,非阻塞,/dev/random可能会阻止(需要一些时间才能返回)。

因此,乍一看/dev/urandomMCRYPT_DEV_URANDOM可能更适合随机数生成。 事实上,它不是!

/dev/random可能会在一段时间内阻止请求,此时已收集了足够多的 [Wikipedia on PBKDF2]。因此/dev/randomMCRYPT_DEV_RANDOM有效地收集随机性。

  

如果您需要执行强加密操作,请使用MCRYPT_DEV_RANDOM或   /dev/random

答案 1 :(得分:3)

您不应该依赖双向加密密码。如果有人可以获得密文,他们通常也可以获得密钥来解密它们。

相反,您应该使用散列或密钥派生,如blowfish或pbkdf2,这些是单向函数,旨在难以破解。

请永远不要以这种方式加密密码。

答案 2 :(得分:2)

如果你使用PHP&gt; = 5.3.7,你应该使用由PHP参与的人编写的password_comp库,它使用BCRYPT,这是迄今为止最强的PHP算法。

它非常简单易用。

https://github.com/ircmaxell/password_compat

简单地哈希密码

 $hash = password_hash($password, PASSWORD_BCRYPT);

根据存储的密码哈希验证给定的密码

if (password_verify($password, $hash)) {
    /* Valid */
} else {
    /* Invalid */
}

非常简单的东西,就像他们说不需要重写一样,特别是在涉及安全性和专家编写时已经写过了。