php mcrypt 已弃用,有什么替代方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41272257/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 02:22:03  来源:igfitidea点击:

mcrypt is deprecated, what is the alternative?

phpencryptionpasswordsphp-7mcrypt

提问by Piet

The mcrypt-extension is deprecatedwill be removed in PHP 7.2 according to the comment posted here. So I am looking for an alternative way to encrypt passwords.

根据此处发布的评论,不推荐使用的 mcrypt-extension将在 PHP 7.2 中删除。所以我正在寻找一种加密密码的替代方法。

Right now I am using something like

现在我正在使用类似的东西

mcrypt_encrypt(MCRYPT_RIJNDAEL_128, md5($key, true), $string, MCRYPT_MODE_CBC, $iv)

I need your opinion for the best/strongest way to encrypt passwords, the encrypted password should of course supported by PHP 7.xx and should also be decryptable because my customers do want to have an option to 'recover' their passwords without generating a new one.

我需要您对加密密码的最佳/最强方法的意见,加密密码当然应该受 PHP 7.xx 支持并且也应该是可解密的,因为我的客户确实希望有一个选项来“恢复”他们的密码而不生成新的一。

采纳答案by Phil

It's best practice to hash passwords so they are not decryptable. This makes things slightly more difficult for attackers that may have gained access to your database or files.

最好的做法是对密码进行哈希处理,使其不可解密。这使得可能已经获得对您的数据库或文件的访问权限的攻击者的事情变得稍微困难​​一些。

If you must encrypt your data and have it decryptable, a guide to secure encryption/decryption is available at https://paragonie.com/white-paper/2015-secure-php-data-encryption. To summarize that link:

如果您必须加密数据并使其可解密,请访问https://paragonie.com/white-paper/2015-secure-php-data-encryption获取安全加密/解密指南。总结该链接:

  • Use Libsodium- A PHP extension
  • If you can't use Libsodium, use defuse/php-encryption- Straight PHP code
  • If you can't use Libsodium or defuse/php-encryption, use OpenSSL- A lot of servers will already have this installed. If not, it can be compiled with --with-openssl[=DIR]
  • 使用Libsodium- PHP 扩展
  • 如果你不能使用 Libsodium,请使用defuse/php-encryption- 直接 PHP 代码
  • 如果您不能使用 Libsodium 或 defuse/php-encryption,请使用OpenSSL- 许多服务器已经安装了它。如果没有,可以用 --with-openssl[=DIR] 编译

回答by kenorb

As suggested by @rqLizard, you can use openssl_encrypt/openssl_decryptPHP functions instead which provides a much better alternative to implement AES(The Advanced Encryption Standard) also known as Rijndael encryption.

正如@rqLizard所建议的,您可以使用openssl_encrypt/ openssl_decryptPHP 函数来代替,它提供了一个更好的替代方案来实现AES(高级加密标准),也称为 Rijndael 加密。

As per the following Scott's comment at php.net:

根据以下Scott 在 php.net 上的评论

If you're writing code to encrypt/encrypt data in 2015, you should use openssl_encrypt()and openssl_decrypt(). The underlying library (libmcrypt) has been abandoned since 2007, and performs far worse than OpenSSL (which leverages AES-NIon modern processors and is cache-timing safe).

Also, MCRYPT_RIJNDAEL_256is not AES-256, it's a different variant of the Rijndael block cipher. If you want AES-256in mcrypt, you have to use MCRYPT_RIJNDAEL_128with a 32-byte key. OpenSSL makes it more obvious which mode you are using (i.e. aes-128-cbcvs aes-256-ctr).

OpenSSL also uses PKCS7 padding with CBC mode rather than mcrypt's NULL byte padding. Thus, mcrypt is more likely to make your code vulnerable to padding oracle attacks than OpenSSL.

Finally, if you are not authenticating your ciphertexts (Encrypt Then MAC), you're doing it wrong.

如果您在 2015 年编写代码来加密/加密数据,则应该使用openssl_encrypt()openssl_decrypt()libmcrypt自 2007 年以来,底层库 ( ) 已被放弃,其性能远低于 OpenSSL(它利用AES-NI现代处理器并且缓存时间安全)。

此外,MCRYPT_RIJNDAEL_256不是AES-256,它是 Rijndael 分组密码的不同变体。如果需要AES-256in mcrypt,则必须使用MCRYPT_RIJNDAEL_12832 字节的密钥。OpenSSL 使您使用的模式更加明显(即aes-128-cbcvs aes-256-ctr)。

OpenSSL 还使用带有 CBC 模式的 PKCS7 填充,而不是 mcrypt 的 NULL 字节填充。因此,与 OpenSSL 相比,mcrypt 更有可能使您的代码容易受到填充预言机攻击。

最后,如果您没有验证您的密文(然后加密 MAC),那么您就做错了。

Further reading:

进一步阅读:

Code examples

代码示例

Example #1

示例#1

AES Authenticated Encryption in GCM mode example for PHP 7.1+

PHP 7.1+ 的 GCM 模式下的 AES 认证加密示例

<?php
//$key should have been previously generated in a cryptographically safe way, like openssl_random_pseudo_bytes
$plaintext = "message to be encrypted";
$cipher = "aes-128-gcm";
if (in_array($cipher, openssl_get_cipher_methods()))
{
    $ivlen = openssl_cipher_iv_length($cipher);
    $iv = openssl_random_pseudo_bytes($ivlen);
    $ciphertext = openssl_encrypt($plaintext, $cipher, $key, $options=0, $iv, $tag);
    //store $cipher, $iv, and $tag for decryption later
    $original_plaintext = openssl_decrypt($ciphertext, $cipher, $key, $options=0, $iv, $tag);
    echo $original_plaintext."\n";
}
?>

Example #2

示例#2

AES Authenticated Encryption example for PHP 5.6+

PHP 5.6+ 的 AES 认证加密示例

<?php
//$key previously generated safely, ie: openssl_random_pseudo_bytes
$plaintext = "message to be encrypted";
$ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
$iv = openssl_random_pseudo_bytes($ivlen);
$ciphertext_raw = openssl_encrypt($plaintext, $cipher, $key, $options=OPENSSL_RAW_DATA, $iv);
$hmac = hash_hmac('sha256', $ciphertext_raw, $key, $as_binary=true);
$ciphertext = base64_encode( $iv.$hmac.$ciphertext_raw );

//decrypt later....
$c = base64_decode($ciphertext);
$ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
$iv = substr($c, 0, $ivlen);
$hmac = substr($c, $ivlen, $sha2len=32);
$ciphertext_raw = substr($c, $ivlen+$sha2len);
$original_plaintext = openssl_decrypt($ciphertext_raw, $cipher, $key, $options=OPENSSL_RAW_DATA, $iv);
$calcmac = hash_hmac('sha256', $ciphertext_raw, $key, $as_binary=true);
if (hash_equals($hmac, $calcmac))//PHP 5.6+ timing attack safe comparison
{
    echo $original_plaintext."\n";
}
?>

Example #3

示例#3

Based on above examples, I've changed the following code which aims at encrypting user's session id:

基于以上示例,我更改了以下旨在加密用户会话 ID 的代码:

class Session {

  /**
   * Encrypts the session ID and returns it as a base 64 encoded string.
   *
   * @param $session_id
   * @return string
   */
  public function encrypt($session_id) {
    // Get the MD5 hash salt as a key.
    $key = $this->_getSalt();
    // For an easy iv, MD5 the salt again.
    $iv = $this->_getIv();
    // Encrypt the session ID.
    $encrypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $session_id, MCRYPT_MODE_CBC, $iv);
    // Base 64 encode the encrypted session ID.
    $encryptedSessionId = base64_encode($encrypt);
    // Return it.
    return $encryptedSessionId;
  }

  /**
   * Decrypts a base 64 encoded encrypted session ID back to its original form.
   *
   * @param $encryptedSessionId
   * @return string
   */
  public function decrypt($encryptedSessionId) {
    // Get the MD5 hash salt as a key.
    $key = $this->_getSalt();
    // For an easy iv, MD5 the salt again.
    $iv = $this->_getIv();
    // Decode the encrypted session ID from base 64.
    $decoded = base64_decode($encryptedSessionId);
    // Decrypt the string.
    $decryptedSessionId = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $decoded, MCRYPT_MODE_CBC, $iv);
    // Trim the whitespace from the end.
    $session_id = rtrim($decryptedSessionId, "
class Session {

  const SESS_CIPHER = 'aes-128-cbc';

  /**
   * Encrypts the session ID and returns it as a base 64 encoded string.
   *
   * @param $session_id
   * @return string
   */
  public function encrypt($session_id) {
    // Get the MD5 hash salt as a key.
    $key = $this->_getSalt();
    // For an easy iv, MD5 the salt again.
    $iv = $this->_getIv();
    // Encrypt the session ID.
    $ciphertext = openssl_encrypt($session_id, self::SESS_CIPHER, $key, $options=OPENSSL_RAW_DATA, $iv);
    // Base 64 encode the encrypted session ID.
    $encryptedSessionId = base64_encode($ciphertext);
    // Return it.
    return $encryptedSessionId;
  }

  /**
   * Decrypts a base 64 encoded encrypted session ID back to its original form.
   *
   * @param $encryptedSessionId
   * @return string
   */
  public function decrypt($encryptedSessionId) {
    // Get the Drupal hash salt as a key.
    $key = $this->_getSalt();
    // Get the iv.
    $iv = $this->_getIv();
    // Decode the encrypted session ID from base 64.
    $decoded = base64_decode($encryptedSessionId, TRUE);
    // Decrypt the string.
    $decryptedSessionId = openssl_decrypt($decoded, self::SESS_CIPHER, $key, $options=OPENSSL_RAW_DATA, $iv);
    // Trim the whitespace from the end.
    $session_id = rtrim($decryptedSessionId, '
$decoded = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, ENCRYPT_KEY, $term, MCRYPT_MODE_ECB);
'); // Return it. return $session_id; } public function _getIv() { $ivlen = openssl_cipher_iv_length(self::SESS_CIPHER); return substr(md5($this->_getSalt()), 0, $ivlen); } public function _getSalt() { return $this->drupal->drupalGetHashSalt(); } }
"); // Return it. return $session_id; } public function _getIv() { return md5($this->_getSalt()); } public function _getSalt() { return md5($this->drupal->drupalGetHashSalt()); } }

into:

进入:

$rijndael = new \phpseclib\Crypt\Rijndael(\phpseclib\Crypt\Rijndael::MODE_ECB);
$rijndael->setKey(ENCRYPT_KEY);
$rijndael->setKeyLength(256);
$rijndael->disablePadding();
$rijndael->setBlockLength(256);

$decoded = $rijndael->decrypt($term);

To clarify, above change is not a true conversion since the two encryption uses a different block size and a different encrypted data. Additionally, the default padding is different, MCRYPT_RIJNDAELonly supports non-standard null padding. @zaph

澄清一下,上述更改不是真正的转换,因为两种加密使用不同的块大小和不同的加密数据。此外,默认填充不同,MCRYPT_RIJNDAEL仅支持非标准空填充。@zaph



Additional notes (from the @zaph's comments):

附加说明(来自@zaph 的评论):

  • Rijndael 128(MCRYPT_RIJNDAEL_128) isequivalent to AES, however Rijndael 256(MCRYPT_RIJNDAEL_256) is notAES-256as the 256 specifies a block size of 256-bits, whereas AEShas only one block size: 128-bits. So basically Rijndael with a block size of 256-bits (MCRYPT_RIJNDAEL_256) has been mistakenly named due to the choices by the mcryptdevelopers. @zaph
  • Rijndael with a block size of 256 may be less secure than with a block size of 128-bits because the latter has had much more reviews and uses. Secondly, interoperability is hindered in that while AES is generally available, where Rijndael with a block size of 256-bits is not.
  • Encryption with different block sizes for Rijndael produces different encrypted data.

    For example, MCRYPT_RIJNDAEL_256(not equivalent to AES-256) defines a different variant of the Rijndael block cipher with size of 256-bits and a key size based on the passed in key, where aes-256-cbcis Rijndael with a block size of 128-bits with a key size of 256-bits. Therefore they're using different block sizes which produces entirely different encrypted data as mcrypt uses the number to specify the block size, where OpenSSL used the number to specify the key size (AES only has one block size of 128-bits). So basically AES is Rijndael with a block size of 128-bits and key sizes of 128, 192 and 256 bits. Therefore it's better to use AES, which is called Rijndael 128 in OpenSSL.

  • Rijndael算法128MCRYPT_RIJNDAEL_128等同于AES,但是Rijndael算法256MCRYPT_RIJNDAEL_256不是AES-256作为256个指定的256位的块尺寸,而AES仅具有一个块大小:128比特。所以基本上,MCRYPT_RIJNDAEL_256由于mcrypt开发人员的选择,块大小为 256 位 ( ) 的Rijndael被错误地命名。@zaph
  • 块大小为 256 的 Rijndael 可能不如块大小为 128 位的 Rijndael 安全,因为后者有更多的评论和使用。其次,互操作性受到阻碍,因为 AES 普遍可用,而具有 256 位块大小的 Rijndael 则不可用。
  • Rijndael 使用不同块大小的加密会产生不同的加密数据。

    例如,MCRYPT_RIJNDAEL_256(不等价于AES-256)定义了大小为 256 位的 Rijndael 分组密码的不同变体,密钥大小基于传入的密钥,其中aes-256-cbcRijndael 的块大小为 128 位,密钥大小为256 位。因此,他们使用不同的块大小,产生完全不同的加密数据,因为 mcrypt 使用数字来指定块大小,而 OpenSSL 使用数字来指定密钥大小(AES 只有一个 128 位的块大小)。所以基本上 AES 是 Rijndael,块大小为 128 位,密钥大小为 128、192 和 256 位。因此最好使用 AES,在 OpenSSL 中称为 Rijndael 128。

回答by Pentium10

Pure-PHP implementation of Rijndael exists with phpseclibavailable as composer package and works on PHP 7.3 (tested by me).

Rijndael 的纯 PHP 实现存在于phpseclib 中,可作为 composer 包使用,并在 PHP 7.3 上运行(由我测试)。

There's a page on the phpseclib docs, which generates sample codeafter you input the basic variables (cipher, mode, key size, bit size). It outputs the following for Rijndael, ECB, 256, 256:

phpseclib 文档上有一个页面,它在您输入基本变量(密码、模式、密钥大小、位大小)后生成示例代码。它为 Rijndael、ECB、256、256 输出以下内容:

a code with mycrypt

带有 mycrypt 的代码

function encrypt($key, $payload) {
  $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
  $encrypted = openssl_encrypt($payload, 'aes-256-cbc', $key, 0, $iv);
  return base64_encode($encrypted . '::' . $iv);
}

works like this with the library

像这样与图书馆合作

function decrypt($key, $garble) {
    list($encrypted_data, $iv) = explode('::', base64_decode($garble), 2);
    return openssl_decrypt($encrypted_data, 'aes-256-cbc', $key, 0, $iv);
}

* $termwas base64_decoded

*$termbase64_decoded

回答by Ariston Cordeiro

As detailed by other answers here, the best solution I found is using OpenSSL. It is built into PHP and you don't need any external library. Here are simple examples:

正如此处的其他答案所详述的那样,我找到的最佳解决方案是使用 OpenSSL。它内置于 PHP 中,您不需要任何外部库。下面是简单的例子:

To encrypt:

加密:

/**
 * This library is unsafe because it does not MAC after encrypting
 */
class UnsafeMcryptAES
{
    const CIPHER = MCRYPT_RIJNDAEL_128;

    public static function encrypt($message, $key)
    {
        if (mb_strlen($key, '8bit') !== 32) {
            throw new Exception("Needs a 256-bit key!");
        }
        $ivsize = mcrypt_get_iv_size(self::CIPHER);
        $iv = mcrypt_create_iv($ivsize, MCRYPT_DEV_URANDOM);

        // Add PKCS7 Padding
        $block = mcrypt_get_block_size(self::CIPHER);
        $pad = $block - (mb_strlen($message, '8bit') % $block, '8bit');
        $message .= str_repeat(chr($pad), $pad);

        $ciphertext = mcrypt_encrypt(
            MCRYPT_RIJNDAEL_128,
            $key,
            $message,
            MCRYPT_MODE_CBC,
            $iv
        );

        return $iv . $ciphertext;
    }

    public static function decrypt($message, $key)
    {
        if (mb_strlen($key, '8bit') !== 32) {
            throw new Exception("Needs a 256-bit key!");
        }
        $ivsize = mcrypt_get_iv_size(self::CIPHER);
        $iv = mb_substr($message, 0, $ivsize, '8bit');
        $ciphertext = mb_substr($message, $ivsize, null, '8bit');

        $plaintext = mcrypt_decrypt(
            MCRYPT_RIJNDAEL_128,
            $key,
            $ciphertext,
            MCRYPT_MODE_CBC,
            $iv
        );

        $len = mb_strlen($plaintext, '8bit');
        $pad = ord($plaintext[$len - 1]);
        if ($pad <= 0 || $pad > $block) {
            // Padding error!
            return false;
        }
        return mb_substr($plaintext, 0, $len - $pad, '8bit');
    }
}

To decrypt:

解密:

/**
 * This library is unsafe because it does not MAC after encrypting
 */
class UnsafeOpensslAES
{
    const METHOD = 'aes-256-cbc';

    public static function encrypt($message, $key)
    {
        if (mb_strlen($key, '8bit') !== 32) {
            throw new Exception("Needs a 256-bit key!");
        }
        $ivsize = openssl_cipher_iv_length(self::METHOD);
        $iv = openssl_random_pseudo_bytes($ivsize);

        $ciphertext = openssl_encrypt(
            $message,
            self::METHOD,
            $key,
            OPENSSL_RAW_DATA,
            $iv
        );

        return $iv . $ciphertext;
    }

    public static function decrypt($message, $key)
    {
        if (mb_strlen($key, '8bit') !== 32) {
            throw new Exception("Needs a 256-bit key!");
        }
        $ivsize = openssl_cipher_iv_length(self::METHOD);
        $iv = mb_substr($message, 0, $ivsize, '8bit');
        $ciphertext = mb_substr($message, $ivsize, null, '8bit');

        return openssl_decrypt(
            $ciphertext,
            self::METHOD,
            $key,
            OPENSSL_RAW_DATA,
            $iv
        );
    }
}

Reference link: https://www.shift8web.ca/2017/04/how-to-encrypt-and-execute-your-php-code-with-mcrypt/

参考链接:https: //www.shift8web.ca/2017/04/how-to-encrypt-and-execute-your-php-code-with-mcrypt/

回答by Ahmet Erkan ?EL?K

You can use phpseclibpollyfill package. You can not use open ssl or libsodium for encrypt/decrypt with rijndael 256. Another issue, you don't need replacement any code.

您可以使用phpseclibpollyfill 包。您不能使用开放的 ssl 或 libsodium 使用 rijndael 256 进行加密/解密。另一个问题,您不需要替换任何代码。

回答by kenorb

You should use OpenSSL over mcryptas it's actively developed and maintained. It provides better security, maintainability and portability. Secondly it performs AES encryption/decryption much faster. It uses PKCS7 padding by default, but you can specify OPENSSL_ZERO_PADDINGif you need it. To use with a 32-byte binary key, you can specify aes-256-cbcwhich is much obvious than MCRYPT_RIJNDAEL_128.

您应该使用 OpenSSL,mcrypt因为它正在积极开发和维护。它提供了更好的安全性、可维护性和可移植性。其次,它执行 AES 加密/解密的速度要快得多。它默认使用 PKCS7 填充,但您可以指定OPENSSL_ZERO_PADDING是否需要它。要与 32 字节的二进制密钥一起使用,您可以指定aes-256-cbc哪个比MCRYPT_RIJNDAEL_128.

Here is the code example using Mcrypt:

这是使用 Mcrypt 的代码示例:

Unauthenticated AES-256-CBC encryption library written in Mcrypt with PKCS7 padding.

未经身份验证的 AES-256-CBC 加密库,用 Mcrypt 编写,带有 PKCS7 填充。

public function make_hash($userStr){
        try{
            /** 
             * Used and tested on PHP 7.2x, Salt has been removed manually, it is now added by PHP 
             */
             return password_hash($userStr, PASSWORD_BCRYPT);
            }catch(Exception $exc){
                $this->tempVar = $exc->getMessage();
                return false;
            }
        }

And here is the version written using OpenSSL:

这是使用 OpenSSL 编写的版本:

public function varify_user($userStr,$hash){
        try{
            if (password_verify($userStr, $hash)) {
                 return true;
                }
            else {
                return false;
                }
            }catch(Exception $exc){
                $this->tempVar = $exc->getMessage();
                return false;
            }
        }

Source: If You're Typing the Word MCRYPT Into Your PHP Code, You're Doing It Wrong.

来源:如果您在 PHP 代码中输入 MCRYPT 这个词,那您就做错了

回答by Abdul Rahman

I am posting this very late, but i hope it will help someone else who face the same problem in PHP 7.2x version.

我发布这个很晚,但我希望它会帮助其他人在 PHP 7.2x 版本中面临同样的问题。

I am using this on PHP 7.2x, its working fine for me.

我在 PHP 7.2x 上使用它,它对我来说工作正常。

  //create hash from user string

 $user_password = $obj->make_hash2($user_key);

and then authenticate the hash with the following function:

然后使用以下函数验证哈希:

if($obj->varify_user($key, $user_key)){
      //this is correct, you can proceed with  
    }

//example:

//例子:

openssl genrsa -des3 -out pkey.pem 2048
(set a password)
openssl rsa -in pkey.pem -out pkey-pub.pem -outform PEM -pubout

and to authenticate this hash use the following code:

并使用以下代码验证此哈希:

$pubKey = openssl_get_publickey(file_get_contents('./pkey-pub.pem'));
openssl_seal($pwd, $sealed, $ekeys, [ $pubKey ]);
$encryptedPassword = base64_encode($sealed);
$key = base64_encode($ekeys[0]);

That's all

就这样

回答by rqLizard

You should use openssl_encrypt()function.

你应该使用openssl_encrypt()函数。

回答by Thoracius Appotite

As pointed out, you should not be storing your users' passwords in a format that is decryptable. Reversable encryption provides an easy route for hackers to find out your users' passwords, which extends to putting your users' accounts at other sites at risk should they use the same password there.

正如所指出的,您不应该以可解密的格式存储用户的密码。可逆加密为黑客找到您用户的密码提供了一条简单的途径,如果他们在其他站点使用相同的密码,则可以扩展到将您的用户帐户置于其他站点的风险中。

PHP provides a pair of powerful functions for random-salted, one-way hash encryption — password_hash()and password_verify(). Because the hash is automatically random-salted, there is no way for hackers to utilize precompiled tables of password hashes to reverse-engineer the password. Set the PASSWORD_DEFAULToption and future versions of PHP will automatically use stronger algorithms to generate password hashes without you having to update your code.

PHP 为随机加盐、单向哈希加密提供了一对强大的函数——password_hash()password_verify(). 由于哈希是自动随机加盐的,黑客无法利用预编译的密码哈希表对密码进行逆向工程。设置该PASSWORD_DEFAULT选项,PHP 的未来版本将自动使用更强的算法来生成密码哈希,而无需更新代码。

回答by Joshua Goldstein

I was able to translate my Crypto object

我能够翻译我的加密对象

  • Get a copy of php with mcrypt to decrypt the old data. I went to http://php.net/get/php-7.1.12.tar.gz/from/a/mirror, compiled it, then added the ext/mcrypt extension (configure;make;make install). I think I had to add the extenstion=mcrypt.so line to the php.ini as well. A series of scripts to build intermediate versions of the data with all data unencrypted.

  • Build a public and private key for openssl

    openssl genrsa -des3 -out pkey.pem 2048
    (set a password)
    openssl rsa -in pkey.pem -out pkey-pub.pem -outform PEM -pubout
    
  • To Encrypt (using public key) use openssl_seal. From what I've read, openssl_encrypt using an RSA key is limited to 11 bytes less than the key length (See http://php.net/manual/en/function.openssl-public-encrypt.phpcomment by Thomas Horsten)

    $pubKey = openssl_get_publickey(file_get_contents('./pkey-pub.pem'));
    openssl_seal($pwd, $sealed, $ekeys, [ $pubKey ]);
    $encryptedPassword = base64_encode($sealed);
    $key = base64_encode($ekeys[0]);
    
  • 使用 mcrypt 获取一份 php 副本以解密旧数据。我去了http://php.net/get/php-7.1.12.tar.gz/from/a/mirror,编译它,然后添加了 ext/mcrypt 扩展(配置;制作;制作安装)。我想我还必须将 extenstion=mcrypt.so 行添加到 php.ini 中。一系列脚本,用于在所有数据未加密的情况下构建数据的中间版本。

  • 为openssl构建公钥和私钥

    $passphrase="passphrase here";
    $privKey = openssl_get_privatekey(file_get_contents('./pkey.pem'), $passphrase);
    // I base64_decode() from my db columns
    openssl_open($encryptedPassword, $plain, $key, $privKey);
    echo "<h3>Password=$plain</h3>";
    
  • 要加密(使用公钥),请使用 openssl_seal。从我读过的内容来看,使用 RSA 密钥的 openssl_encrypt 限制为比密钥长度少 11 个字节(参见Thomas Horsten 的http://php.net/manual/en/function.openssl-public-encrypt.php评论)

    $passphrase="passphrase here";
    $privKey = openssl_get_privatekey(file_get_contents('./pkey.pem'), $passphrase);
    // I base64_decode() from my db columns
    openssl_open($encryptedPassword, $plain, $key, $privKey);
    echo "<h3>Password=$plain</h3>";
    

You could probably store the raw binary.

您可能可以存储原始二进制文件。

  • To Decrypt (using private key)

    ##代码##
  • 解密(使用私钥)

    ##代码##

P.S. You can't encrypt the empty string ("")

PS你不能加密空字符串(“”)

P.P.S. This is for a password database not for user validation.

PPS 这是用于密码数据库而不是用于用户验证。