【发布时间】:2014-07-10 10:14:36
【问题描述】:
我正试图找出我的加密/解密代码出了什么问题,但我似乎在 Google 搜索与我类似的问题时遇到了死胡同。
这是我的两个函数的 php 代码,但我会先解释一下。这些工作原理是使用盐、用户密码和他们上次登录的 unix 纪元时间(如果他们以前从未登录过,则为当前纪元时间)来创建加密密码。
现在我正在测试代码以查看它是否有效,然后再将其连接到我的其余 php 代码中。传递给函数的密码是 Test,它使用 time() 提供时间,然后在加密过程中将该值存储到全局变量中,因此我不必在测试时将其存储到数据库中。
在一个 SO 线程 this one 中,我读到在创建 IV 时使用 MCRYPT_RAND 然后不保存生成的 IV 意味着解密将永远无法工作,因为如果您重新调用 mcrypt_create_iv 来创建 IV,IV 会有所不同在解密过程中。因此,我也为 IV 制作了一个全局变量,并在解密过程中进行了尝试,但它仍然无法正确解密。下面的代码反映了这一变化。
//Encrypt the user's password for storing in database
function encrypt($password, $id)
{
echo "Function: encrypt \n"; //For debugging
$salt2 = getTime($id);
$salt1 = 'akey'; //Changed for security purposes
global $cur_iv;
$key = substr(hash('sha256',$salt1.$password.$salt2),0,32);
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256,MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size,MCRYPT_RAND);
$encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $password, MCRYPT_MODE_ECB, $iv));
$cur_iv = $iv;
echo $encrypted;
echo "\n";
global $cur_time;
$cur_time = $salt2;
return $encrypted;
}
//Decrypt the user's password for loggin checking
function decrypt($password,$id)
{
echo "Function: decrypt \n"; //For debugging
//$salt2 = getTime($id);
global $cur_time;
$salt2 = $cur_time;
$salt1 = 'akey'; //Changed for security purposes
global $cur_iv;
$key = substr(hash('sha256',$salt1.$password.$salt2),0,32);
$iv = $cur_iv;
$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($pass), MCRYPT_MODE_ECB, $iv);
echo $decrypted;
echo "\n";
return $decrypted;
}
加密后的密码如下所示:xgr5YB0vHwJAkjkqwTl6rnZMjbZL0qmLE4D8JXDT1rM=
但解密后是这样的:NÞÚ±=º)cz_öUñŽP´è8Åáó»d—+ÒAÐ
编辑 2:
这是 Saikios 要求的 getTime 函数:
//Use the last login time for part of the encryption salt to ensure more secure hashing
function getTime($id)
{
global $sql;
echo "Function: getTime \n"; //For debugging
if ($salt_stmt = $sql->prepare("Select Last_Login From login_log Where User_ID = ?;"))
{
$salt_stmt->bind_param('i',$id);
$salt_stmt->execute();
$salt_stmt->store_result();
$salt_stmt->bind_result($time);
$salt_stmt->fetch();
if ($salt_stmt->num_rows < 1)
{
echo "No last login \n";
$time = time();
}
else
{
echo "Last Login Time: ".$time."\n";
}
return $time;
}
else
{
echo "Error: ".$sql->error;
}
}
【问题讨论】:
-
你为什么不直接使用
password_hash()和password_verify()? -
或者只是将用户输入的密码加密并与数据库中的密码进行比较?
-
在解密函数中你也有:
$salt2 == $cur_time;所以你是比较两者而不是设置。 -
@JonathanKuhn facepalm 感谢您指出这一点,我现在会解决这个问题。编辑:仍然无法正常工作。
-
我建议为此使用非对称加密。这样您就可以始终保持一把钥匙的安全。