【问题标题】:Converting MCRYPT to OPENSSL [duplicate]将 MCRYPT 转换为 OPENSSL [重复]
【发布时间】:2020-05-16 03:19:34
【问题描述】:

我继承了一个在 PHP 5.X 时代编码的项目。该网站目前在 PHP 7.1 上运行,并使用 MCRYPT 库进行加密和解密功能。​​

我需要升级到 PHP 7.2,这意味着再见 MCRYPT!

不熟悉加密会导致尝试转换为 OPENSSL 时出现问题

下面是当前的代码。

function decrypt($encryptedText)
{
    $key = pack('H*', 'NOTHINGTOSEEHERE');
    $enc = base64_decode($encryptedText);
    return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $enc, MCRYPT_MODE_ECB, $key), "\x80");
}
function encrypt($plaintext)
{
    $key = pack('H*', 'NOTHINGTOSEEHERE');

    $blockSize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
    $inputLength = strlen($plaintext);
    $blockCount = floor($inputLength / $blockSize);
    $padding = ($blockCount + 1) * $blockSize - $inputLength;
    $paddedPlainText = str_pad($plaintext, $inputLength + $padding, "\x80", STR_PAD_RIGHT);

    $enc = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $paddedPlainText, MCRYPT_MODE_ECB, $key);
    return base64_encode($enc);
}

我查看了其他几篇关于从 MCRYPT 转换为 OPENSSL 的确切主题的 StackOverflow 帖子,根据我阅读的所有内容,我想出了以下代码,但它不起作用。

function decrypt($encryptedText)
{
    $key = pack('H*', 'NOTHINGTOSEEHERE');

    $ivsize = openssl_cipher_iv_length('AES-128-ECB');
    $iv = openssl_random_pseudo_bytes($ivsize);

    $enc = base64_decode($encryptedText);

    return trim(openssl_decrypt($enc, 'AES-128-ECB', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
}

function encrypt($plaintext)
{
    $key = pack('H*', 'NOTHINGTOSEEHERE');

    $ivsize = openssl_cipher_iv_length('AES-128-ECB');
    $iv = openssl_random_pseudo_bytes($ivsize);

    $enc = openssl_encrypt($plaintext, 'AES-128-ECB', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);

    return base64_encode($enc);
}

我不确定,但我感觉问题与旧加密函数中文本的填充有关,这导致新代码无法工作。如果这确实是问题,我不知道如何将它集成到 OPENSSL 函数中。

$blockSize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
$inputLength = strlen($plaintext);
$blockCount = floor($inputLength / $blockSize);
$padding = ($blockCount + 1) * $blockSize - $inputLength;
$paddedPlainText = str_pad($plaintext, $inputLength + $padding, "\x80", STR_PAD_RIGHT);

再次,不熟悉加密,感谢任何/所有帮助,以便我找出并理解我做错了什么。

【问题讨论】:

  • 您对“不起作用”的定义到底是什么?你的意思是代码运行的时候有错误吗?还是您的意思是新代码无法解密用旧代码加密的内容?
  • 新代码不会解密用旧代码加密的内容
  • thisthis。我还将抛出一个不雅的选项:获取所有加密文本,使用 mcrypt 解密,然后使用 openssl 加密,然后重新存储。根据这些数据的敏感程度以及您所在的行业,可能会有一些法规对此不满意,不太确定。
  • 没错,这正是我所说的:-P
  • 让我为@PatrickQ 不优雅的解决方案添加一票。只需使用较新的 openssl 接口找出正确的方法,然后使用 mcrypt 解密并使用 openssl API 重新加密。这将使您免于尝试追踪 MCRYPT 加密中的每一个小特性并尝试使用 openssl API 复制它。另外,从安全角度来看,大量 MCRYPT 代码存在缺陷,因此不应该使用 openssl API 为下一代保留。

标签: php encryption openssl mcrypt


【解决方案1】:

我在升级我的用户密码加密时已经解决了这个问题。在伪逻辑中,你只需要这样的东西:

<?php

if ($whatever === $this->decryptNew($var)) {
    // business as usual
} elseif ($whatever === $this->decryptOldWay($var)) {
    // encrypt as the new way!
    $encrypted = $this->encryptNew($whatever);
    // save!
    // Back to business as usual!
}

这是我的 SSl 课程。试试看:

class Ssl
{
    private $cipher = "aes-128-gcm";
    private $options = 0;

    /**
     * @param string $plaintext
     * @return array
     */
    public function encrypt($plaintext)
    {
        $key = \openssl_random_pseudo_bytes(16);
        $ivlen = \openssl_cipher_iv_length($this->cipher);
        $iv = \openssl_random_pseudo_bytes($ivlen);
        $ciphertext = openssl_encrypt($plaintext, $this->cipher, $key, $this->options, $iv,$tag);

        return array(
            'key' => \bin2hex($key),
            'iv' => \bin2hex($iv),
            'tag' => \bin2hex($tag),
            'ciphertext' => $ciphertext,
        );
    }

    /**
     * @param string $json
     * @return false|string
     */
    public function decrypt($json, $key)
    {
        $data = \json_decode($json);
        $result = \openssl_decrypt($data->ciphertext, $this->cipher, \hex2bin($key), $this->options, \hex2bin($data->iv), \hex2bin($data->tag));

        return \json_decode($result, true);
    }
}

【讨论】:

  • 您能否提供一个示例,证明它可以解密使用 mcrypt 加密的文本?
  • 与 mcrypt 无关。保留现有功能,添加这些功能,然后尝试使用新功能进行解密。如果失败,用旧的东西解密并用新的东西重新加密。我在更新用户密码字段加密时会做类似的事情,所以下次用户登录时它会自行更新
  • OP 的全部问题是他们如何使用 openssl 而不是 mcrypt 解密现有的加密文本。 “新代码不会解密用旧代码加密的内容”
  • 搞定了... return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $enc, MCRYPT_MODE_ECB, $key), "\x80");替换为 return trim(openssl_decrypt($enc, 'AES-128-ECB', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $key), "\x80");
  • $enc = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $paddedPlainText, MCRYPT_MODE_ECB, $key);替换为 $enc = openssl_encrypt($paddedPlainText, 'AES-128-ECB', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $key);
猜你喜欢
  • 2019-07-23
  • 2017-10-15
  • 2018-11-10
  • 2020-07-17
  • 2021-10-28
  • 2012-04-17
  • 2017-06-23
  • 2017-12-26
  • 2018-10-04
相关资源
最近更新 更多