使用 PHP 加密和解密密码的最佳方法?

发布于 2024-08-02 15:56:04 字数 480 浏览 10 评论 0原文

可能的重复:
PHP 2 路加密:我需要存储可以检索的密码

我计划在我的网站上存储用户的外国帐户信息,又名 Rapidshare 用户名和密码等...我想保证信息安全,但我知道如果我散列他们的信息,我无法检索它以供以后使用。

Base64 是可解密的,因此直接使用它是没有意义的。 我的想法是对用户进行扰乱,并在其经过 Base64 处理之前和之后通过,即使在解密之后,如果您尝试解密,也会得到一些看起来很有趣的文本。是否有一个 php 函数接受的值会对字符串进行唯一的加扰,并在稍后重新输入该值时对其进行解扰?

有什么建议吗?

Possible Duplicate:
PHP 2-way encryption: I need to store passwords that can be retrieved

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.

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?

Any suggestions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

难理解 2024-08-09 15:56:04

您不应该加密密码,而应该使用 bcrypt 等算法对它们进行哈希处理。 这个答案解释了如何在 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"
);

警告:上面的示例对信息进行了加密,但没有对密文进行身份验证以防止篡改。 您不应依赖未经身份验证的加密来进行加密安全性,特别是因为所提供的代码容易受到 padding oracle 攻击。

另请参阅:

另外,不要只使用“密码”作为加密密钥。 加密密钥是随机字符串。


3v4l.org 上的演示

echo 'Encrypted:' . "\n";
var_dump($encrypted); // "m1DSXVlAKJnLm7k3WrVd51omGL/05JJrPluBonO9W+9ohkNuw8rWdJW6NeLNc688="

echo "\n";

echo 'Decrypted:' . "\n";
var_dump($decrypted); // " string to be encrypted "

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:

$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
    ),
    "\0"
);

Warning: The above example encrypts information, but it does not authenticate the ciphertext to prevent tampering. You should not rely on unauthenticated encryption for security, especially since the code as provided is vulnerable to padding oracle attacks.

See also:

Also, don't just use a "password" for an encryption key. Encryption keys are random strings.


Demo at 3v4l.org:

echo 'Encrypted:' . "\n";
var_dump($encrypted); // "m1DSXVlAKJnLm7k3WrVd51omGL/05JJrPluBonO9W+9ohkNuw8rWdJW6NeLNc688="

echo "\n";

echo 'Decrypted:' . "\n";
var_dump($decrypted); // " string to be encrypted "
忆伤 2024-08-09 15:56:04

安全警告:此类不安全。它使用 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";

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.

Found this class recently, it works like a dream!

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);
    }
}

And to call it:

$str = "My secret String";

$converter = new Encryption;
$encoded = $converter->encode($str );
$decoded = $converter->decode($encoded);    

echo "$encoded<p>$decoded";
廻憶裏菂餘溫 2024-08-09 15:56:04

安全警告:此代码不安全。

工作示例

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); 

Security warning: This code is not secure.

working example

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); 
卸妝后依然美 2024-08-09 15:56:04

在处理加密时,您应该非常注意一件事:

试图变得聪明并发明自己的东西通常会让您感到不安全。

您可能最好使用其中一个加密扩展使用 PHP。

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 extensions that come with PHP.

阳光的暖冬 2024-08-09 15:56:04

安全警告:此代码不安全。除了容易受到选择密文攻击之外,它对 unserialize() 的依赖也使其容易受到 PHP 对象注入的攻击。<​​/p>

为了处理字符串/数组,我使用这两个函数:

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 存储/发送字符串或数组,因为字符串/数组在加密之前已序列化。

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.

To handle a string / array I use these two functions:

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;
}

It's flexible as in you can store/send via URL a string or array because the string/array is serialzed before encryption.

ι不睡觉的鱼゛ 2024-08-09 15:56:04

这只能为您提供边际保护。如果攻击者可以在您的应用程序中运行任意代码,他们就可以以与您的应用程序完全相同的方式获取密码。如果您将密钥存储在文件中,并使用它在进入数据库的过程中进行加密并在导出时进行解密,那么您仍然可以获得一些针对某些 SQL 注入攻击和错误的数据库备份的保护。但是你应该使用bindparams来完全避免SQL注入的问题。

如果决定加密,您应该为此使用一些高级加密库,否则您将会出错。您必须正确设置密钥、消息填充和完整性检查,否则您所有的加密工作都没有什么用处。 GPGME 是一个不错的选择。 Mcrypt 级别太低,您可能会出错。

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.

If decide to encrypt, you should use some high level crypto library for this, or you will get 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. GPGME is a good choice for one example. Mcrypt is too low level and you will probably get it wrong.

为人所爱 2024-08-09 15:56:04

查看 mycrypt(): http://us.php.net/manual/ en/book.mcrypt.php

如果您使用 postgres,则可以使用 pgcrypto 进行数据库级加密。 (使搜索和排序更容易)

Check out 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)

古镇旧梦 2024-08-09 15:56:04

即使您有权访问代码,加密/解密数据库中的数据的最佳想法是使用 2 个不同的密码,每个用户使用私有密码 (user-pass),并为所有用户使用私有代码用户(系统通行证)。

场景

  1. 用户密码与md5一起存储在数据库中,用于验证每个用户登录系统。每个用户的用户通行证不同
  2. 数据库中的每个用户条目在 md5 中都有一个用于数据加密/解密的系统密码。每个用户的系统通行证相同
  3. 每当用户从系统中删除时,所有在旧系统通行证下加密的数据都必须在新系统通行证下再次加密,以避免安全问题。

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).

Scenario

  1. user-pass is stored with md5 in the database and is being used to validate each user to login to the system. This user-pass is different for each user.
  2. Each user entry in the database has in md5 a system-pass for the encryption/decryption of the data. This system-pass is the same for each user.
  3. 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.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文