可能重复:
PHP 2-way encryption: I need to store passwords that can be retrieved
我打算在我的网站上存储我的用户的外国帐户信息,也就是用户名和密码等等...我想保证信息安全,但我知道如果我散列他们的信息,我就无法检索它供以后使用。
Base64是可解密的,所以没有必要使用它只是简单的关闭。 我的想法是加扰用户并在它解密之前和之后通过这种方式传递,如果你尝试解密,你会得到一些看起来很有趣的文本。是否有一个php函数接受将对字符串进行唯一加扰的值,并在以后重新计算该值时对其进行解扰?
有什么建议吗?
答案 0 :(得分:298)
您不应该加密密码,而应该使用像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
加密:
$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
)
);
要解密:
$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"
);
警告:以上示例对信息进行加密,但不会对密文进行身份验证以防止篡改。 You should not rely on unauthenticated encryption for security,特别是因为提供的代码容易受到填充oracle攻击。
另见:
此外,不要只使用“密码”作为加密密钥。 加密密钥是随机字符串。
echo 'Encrypted:' . "\n";
var_dump($encrypted); // "m1DSXVlAKJnLm7k3WrVd51omGL/05JJrPluBonO9W+9ohkNuw8rWdJW6NeLNc688="
echo "\n";
echo 'Decrypted:' . "\n";
var_dump($decrypted); // " string to be encrypted "
答案 1 :(得分: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);
}
}
并称之为:
$str = "My secret String";
$converter = new Encryption;
$encoded = $converter->encode($str );
$decoded = $converter->decode($encoded);
echo "$encoded<p>$decoded";
答案 2 :(得分: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 :(得分:12)
答案 4 :(得分:2)
这只会给你边际保护。如果攻击者可以在您的应用程序中运行任意代码,他们可以获得与您的应用程序完全相同的密码。如果将密钥存储在文件中并使用该密钥在去往数据库的路上加密并在出路时解密,您仍然可以从某些SQL注入攻击和错放的数据库备份中获得一些保护。但是你应该使用bindparams来完全避免SQL注入的问题。
如果决定加密,你应该为此使用一些高级加密库,否则你将弄错。您必须正确设置密钥设置,消息填充和完整性检查,或者您的所有加密工作都没什么用处。 GPGME是一个例子的不错选择。 Mcrypt太低了,你可能会弄错。
答案 5 :(得分:2)
安全警告:此代码不安全。除了易受选择密文攻击之外,它对
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存储/发送字符串或数组,因为字符串/数组在加密前是串行化的。
答案 6 :(得分:1)
查看mycrypt():http://us.php.net/manual/en/book.mcrypt.php
如果您使用postgres,那么pgcrypto用于数据库级加密。 (使搜索和排序更容易)
答案 7 :(得分:-1)
即使您有权访问代码,加密/解密数据库中数据的最佳方法是为每个用户使用2个不同的密码(user-pass
),为所有用户使用私有密码( system-pass
)。
<强>方案强>
user-pass
与md5一起存储在数据库中,用于验证每个用户是否登录系统。每个用户的此用户传递不同。system-pass
,用于加密/解密数据。此系统传递是每个用户的相同。