使用 PHP 加密和解密密码的最佳方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1289061/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Best way to use PHP to encrypt and decrypt passwords?
提问by jiexi
Possible Duplicate:
PHP 2-way encryption: I need to store passwords that can be retrieved
可能的重复:
PHP 2 路加密:我需要存储可以检索的密码
I plan to store foreign account information for my users on my website, aka rapidshare username and passwords, etc... I want to keep information secure, but I know that if I hash their information, I can't retrieve it for later use.
我打算在我的网站上为我的用户存储外国帐户信息,又名 Rapidshare 用户名和密码等...我想确保信息安全,但我知道如果我散列他们的信息,我将无法检索以备后用.
Base64 is decrypt-able so there's no point using that just plain off. My idea is to scramble the user and pass before and after it gets base64ed that way even after you decrypt it, you get some funny looking text if you try to decrypt. Is there a php function that accepts values that will make an unique scramble of a string and de-scramble it later when the value is reinputed?
Base64 是可解密的,所以直接使用它是没有意义的。我的想法是打乱用户并在它以这种方式进行 base64ed 之前和之后通过,即使在你解密之后,如果你尝试解密,你会得到一些看起来很有趣的文本。是否有一个 php 函数接受值,这些值将对字符串进行唯一的加扰,并在稍后重新输入该值时对其进行解扰?
Any suggestions?
有什么建议?
回答by Alix Axel
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.Still, here is how you would encrypt/decrypt:
你不应该加密密码,而应该使用像 bcrypt 这样的算法来散列它们。这个答案解释了如何在 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
),
"echo 'Encrypted:' . "\n";
var_dump($encrypted); // "m1DSXVlAKJnLm7k3WrVd51omGL/05JJrPluBonO9W+9ohkNuw8rWdJW6NeLNc688="
echo "\n";
echo 'Decrypted:' . "\n";
var_dump($decrypted); // " string to be encrypted "
"
);
Warning: The above example encrypts information, but it does not authenticate the ciphertext to prevent tampering. You should notrely on unauthenticated encryption for security, especially since the code as provided is vulnerable to padding oracle attacks.
警告:以上示例对信息进行了加密,但并未对密文进行身份验证以防止篡改。你应该不依赖于安全性未经验证的加密所提供易受填充神谕攻击以来,特别是代码。
See also:
也可以看看:
- https://stackoverflow.com/a/30189841/2224584
- https://stackoverflow.com/a/30166085/2224584
- https://stackoverflow.com/a/30159120/2224584
- https://stackoverflow.com/a/30189841/2224584
- https://stackoverflow.com/a/30166085/2224584
- https://stackoverflow.com/a/30159120/2224584
Also, don't just use a "password" for an encryption key. Encryption keys are random strings.
此外,不要只使用“密码”作为加密密钥。加密密钥是随机字符串。
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);
}
}
回答by wilsonpage
Security Warning: This class is not secure. It's using Rijndael256-ECB, which is not semantically secure. Just because "it works" doesn't mean "it's secure". Also, it strips tailing spaces afterwards due to not using proper padding.
安全警告:此类不安全。它使用Rijndael256-ECB,这在语义上是不安全的。仅仅因为“它有效”并不意味着“它是安全的”。此外,由于没有使用适当的填充,它会在之后剥离尾随空间。
Found this class recently, it works like a dream!
最近发现了这个类,它像做梦一样!
$str = "My secret String";
$converter = new Encryption;
$encoded = $converter->encode($str );
$decoded = $converter->decode($encoded);
echo "$encoded<p>$decoded";
And to call it:
并称之为:
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);
回答by stasl
Security warning:This code is not secure.
安全警告:此代码不安全。
working example
工作示例
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))), "##代码##"));
return $s;
}
回答by Sebastian Paaske T?rholm
One thing you should be very aware of when dealing with encryption:
处理加密时您应该非常注意的一件事:
Trying to be clever and inventing your own thing usually will leave you with something insecure.
试图变得聪明并发明自己的东西通常会给你带来不安全感。
You'd probably be best off using one of the cryptography extensionsthat come with PHP.
您可能最好使用PHP 附带的加密扩展之一。
回答by Ants Aasma
This will only give you marginal protection. If the attacker can run arbitrary code in your application they can get at the passwords in exactly the same way your application can. You could still get some protection from some SQL injection attacks and misplaced db backups if you store a secret key in a file and use that to encrypt on the way to the db and decrypt on the way out. But you should use bindparams to completely avoid the issue of SQL injection.
这只会给您提供边际保护。如果攻击者可以在您的应用程序中运行任意代码,他们就可以以与您的应用程序完全相同的方式获取密码。如果您将密钥存储在文件中并使用它在通往数据库的途中加密并在出去的路上解密,您仍然可以从一些 SQL 注入攻击和错位的数据库备份中获得一些保护。但是你应该使用 bindparams 来完全避免 SQL 注入的问题。
If decide to encrypt, you should use some high level crypto library for this, or you willget it wrong. You'll have to get the key-setup, message padding and integrity checks correct, or all your encryption effort is of little use. GPGMEis a good choice for one example. Mcrypt is too low level and you will probably get it wrong.
如果决定加密,您应该为此使用一些高级加密库,否则您会出错。您必须使密钥设置、消息填充和完整性检查正确无误,否则您的所有加密工作都将毫无用处。举个例子,GPGME是一个不错的选择。Mcrypt 级别太低,您可能会弄错。
回答by Martin
Securiy Warning: This code is insecure. In addition to being vulnerable to chosen-ciphertext attacks, its reliance on
unserialize()makes it vulnerable to PHP Object Injection.
安全警告:此代码不安全。除了容易受到选择密文攻击之外,它的依赖
unserialize()使它容易受到 PHP 对象注入的攻击。
To handle a string / array I use these two functions:
要处理字符串/数组,我使用这两个函数:
##代码##It's flexible as in you can store/send via URL a string or array because the string/array is serialzed before encryption.
它很灵活,因为您可以通过 URL 存储/发送字符串或数组,因为字符串/数组在加密之前已序列化。
回答by Josh Rice
Check out mycrypt(): http://us.php.net/manual/en/book.mcrypt.php
查看 mycrypt():http://us.php.net/manual/en/book.mcrypt.php
And if you're using postgres there's pgcrypto for database level encryption. (makes it easier to search and sort)
如果您使用的是 postgres,则可以使用 pgcrypto 进行数据库级加密。(使搜索和排序更容易)
回答by Nikos Tsirakis
The best idea to encrypt/decrypt your data in the database even if you have access to the code is to use 2 different passes a private password (user-pass) for each user and a private code for all users (system-pass).
即使您有权访问代码,加密/解密数据库中的数据的最佳方法是使用 2 个不同的密码user-pass,每个用户的私有密码 ( ) 和所有用户的私有代码 ( system-pass)。
Scenario
设想
user-passis stored with md5 in the database and is being used to validate each user to login to the system. This user-pass is differentfor each user.- Each user entry in the database has in md5 a
system-passfor the encryption/decryption of the data. This system-pass is the samefor each user. - Any time a user is being removed from the system all data that are encrypted under the old system-pass have to be encrypted again under a new system-pass to avoid security issues.
user-pass与 md5 一起存储在数据库中,用于验证每个用户登录系统。这个用户通行证对于每个用户都是不同的。- 数据库中的每个用户条目都在 md5 a 中
system-pass用于数据的加密/解密。该系统通行证对每个用户都是相同的。 - 每当用户从系统中删除时,所有在旧系统通行证下加密的数据都必须在新系统通行证下再次加密,以避免出现安全问题。

