我最近决定对我的密码使用更安全的加密。加密密码没问题,在调用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;
}
}
?>
答案 0 :(得分:4)
<{> 3}} OWASP提供了准备充分的文档:Online Web Application Security Project,Password Storage Cheat Sheet和Authentication Cheat Sheet。看看吧!抱歉,使用存储在服务器上的秘密加密密码 不安全:如果入侵者侵入您的代码库,入侵者可以检索 使用您的代码库和存储的密码的每个密码和任何密码 (代码或持久存储中的某处)。
要走的路是PHP Security Cheat Sheet。
如何处理新创建的密码
hash = HashFunction( password, salt )
如何验证密码
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_RANDOM
和MCRYPT_DEV_URANDOM
。
MCRYPT_DEV_RANDOM
从/dev/random
MCRYPT_DEV_URANDOM
从/dev/urandom
/dev/urandom
都会立即提供随机数据,非阻塞,/dev/random
可能会阻止(需要一些时间才能返回)。
因此,乍一看,/dev/urandom
和MCRYPT_DEV_URANDOM
可能更适合随机数生成。 事实上,它不是!
/dev/random
可能会在一段时间内阻止请求,此时已收集了足够多的 [Wikipedia on PBKDF2]。因此/dev/random
和MCRYPT_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 */
}
非常简单的东西,就像他们说不需要重写一样,特别是在涉及安全性和专家编写时已经写过了。