使用openssl解密mcrypt

Pho*_*nix 2 php encryption openssl cryptography mcrypt

由于mcrypt被认为是过时的,我的任务是升级当前代码以使用openssl.听起来很简单,但......经过几天的尝试和失败后,我觉得自己很疯狂.

我的问题是:你有什么方法可以用之前用mcrypt加密的openssl数据解密吗?我已经阅读了很多这方面的帖子,大多数人都说在运行mcrypt之前需要先前手动填充数据.问题是mcrypt-ed数据已经加密(使用mcrypt提供的自动空填充)并驻留在数据库中,因此无法和/或期望对其进行修改.

提及:

  1. 使用的算法是rijndael-128 cbc,带有32字节密钥(所以我使用aes-256-cbc表示openssl).
  2. 我正在使用php(php-crypto)的openssl包装器.
  3. 我已经设法使逆操作工作(用mcrypt解码openssl),只需剥离最终解码的字符(如果它们是非字母数字).
  4. 在mcrypting之前手动填充数据然后使用openssl解密它就像魅力一样,但这不是问题所在.

一些代码片段:

// Simple mcrypt encrypt, decrypt with php-crypto example
// This doesn't work and produces a "Finalizing of cipher failed" error
        $data = "This is a text";
        $strMcryptData=mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv);

        $algorithm = 'aes-256-cbc';
        $cipher = new Cipher($algorithm);
        $sim_text = $cipher->decrypt($strMcryptData, $key, $iv);

// Simple mcrypt encrypt with padding, decrypt with php-crypto
// Works and produces the correct text on decryption
        $pad =  $blocksize - (strlen($data) % $blocksize);
        $text = $data;
        $text .= str_repeat(chr($pad), $pad);
        $strPaddedData=mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_CBC, $iv);

        $sim_text = $cipher->decrypt($strPaddedData, $key, $iv);
Run Code Online (Sandbox Code Playgroud)

Sco*_*ski 5

如果你在没有手动添加PKCS7的情况下在mcrypt中加密,mcrypt将很乐意用NUL字节填充你的明文.

无论何时使用,OpenSSL都会为您做PKCS7填充aes-X-cbc.这样做的不幸结果是,如果你有AES-CBC(NULL_PADDED(plaintext))并尝试解密它,openssl_decrypt将尝试删除填充并失败.

比较http://3v4l.org/bdQe9http://3v4l.org/jr68fhttp://3v4l.org/K6ZEU

OpenSSL扩展目前没有为您提供一种说法"此字符串未填充,请不要为我删除填充"然后NUL自行删除字节的方法.您必须使用PKCS7填充进行加密,以便解密成功.

虽然这是OpenSSL的限制,但它强调的是,你遇到它的唯一原因是因为mcrypt很糟糕.


小智 5

稍微陈旧,但你可以通过一些工作来解决这个问题.您可以告诉PHP的OpenSSL加密的字符串没有填充,并告诉它为您提供原始输出(因此您不必对其进行base64解码).然后,如果字符串的长度碰巧可以被IV完全整除,则可以从结果字符串的末尾去除空值(这是一个完整性检查,就好像结果字符串不能被IV整除那么它不是填补所有).

请注意,此代码有两个主要限制:

  1. 如果您在任何时候加密了以两个或更多NULL字节结尾的合法字符串,那么此代码将不会为您提供相同的输出.

  2. 如果字符串的填充只需要一个空字节,则此代码不会剥离它.

您可以解决这两个如果你知道一个事实,你没有加密任何在空字节结束,你可以改变这条只是做了preg_replace空值的代码; 只需确保将正则表达式锚定到字符串的末尾,以便它只从末尾剥离.

http://3v4l.org/kYAXn

显然这段代码没有主要的免责声明,请在您的用例中进行测试,但有人可能会发现这很有用.