Actualización de mi biblioteca de cifrado de Mcrypt a OpenSSL

Estoy usando la siguiente biblioteca comúnmente referenciada para el cifrado. Quiero actualizarlo a OpenSSL desde Mcrypt para que ya no use una biblioteca obsoleta.

Estoy tratando de averiguar si esto es posible. He investigado un poco sobre esto, pero he encontrado información contradictoria:

Esta publicación dice que es imposible descifrar los datos usando OpenSSL que se cifró con Mcrypt.https://stackoverflow.com/a/19748494/5834657

Sin embargo, esta publicación dice que es posible usar relleno. Parece que mi función usa relleno. ¿Es este el tipo correcto de relleno necesario para que esto funcione?https://stackoverflow.com/a/31614770/5834657

<?php 

namespace Utilities\Encryption;

/**
* A class to handle secure encryption and decryption of arbitrary data
*
* Note that this is not just straight encryption.  It also has a few other
* features in it to make the encrypted data far more secure.  Note that any
* other implementations used to decrypt data will have to do the same exact
*  operations.  
*
* Security Benefits:
*
* - Uses Key stretching
* - Hides the Initialization Vector
* - Does HMAC verification of source data
*
*/

class Encryption {

/**
 * @var string $cipher The mcrypt cipher to use for this instance
 */
protected $cipher = '';

/**
 * @var int $mode The mcrypt cipher mode to use
 */
protected $mode = '';

/**
 * @var int $rounds The number of rounds to feed into PBKDF2 for key generation
 */
protected $rounds = 100;

/**
 * Constructor!
 *
 * @param string $cipher The MCRYPT_* cypher to use for this instance
 * @param int    $mode   The MCRYPT_MODE_* mode to use for this instance
 * @param int    $rounds The number of PBKDF2 rounds to do on the key
 */
public function __construct($cipher, $mode, $rounds = 100) {
    $this->cipher = $cipher;
    $this->mode = $mode;
    $this->rounds = (int) $rounds;
}

/**
 * Decrypt the data with the provided key
 *
 * @param string $data The encrypted datat to decrypt
 * @param string $key  The key to use for decryption
 * 
 * @returns string|false The returned string if decryption is successful
 *                           false if it is not
 */
public function decrypt($data, $key) {
    $salt = substr($data, 0, 128);
    $enc = substr($data, 128, -64);
    $mac = substr($data, -64);

    list ($cipherKey, $macKey, $iv) = $this->getKeys($salt, $key);

    if ($mac !== hash_hmac('sha512', $enc, $macKey, true)) {
         return false;
    }

    $dec = mcrypt_decrypt($this->cipher, $cipherKey, $enc, $this->mode, $iv);

    $data = $this->unpad($dec);

    return $data;
}

/**
 * Encrypt the supplied data using the supplied key
 * 
 * @param string $data The data to encrypt
 * @param string $key  The key to encrypt with
 *
 * @returns string The encrypted data
 */
public function encrypt($data, $key) {
    $salt = mcrypt_create_iv(128, MCRYPT_DEV_URANDOM);
    list ($cipherKey, $macKey, $iv) = $this->getKeys($salt, $key);

    $data = $this->pad($data);

    $enc = mcrypt_encrypt($this->cipher, $cipherKey, $data, $this->mode, $iv);

    $mac = hash_hmac('sha512', $enc, $macKey, true);
    return $salt . $enc . $mac;
}

/**
 * Generates a set of keys given a random salt and a master key
 *
 * @param string $salt A random string to change the keys each encryption
 * @param string $key  The supplied key to encrypt with
 *
 * @returns array An array of keys (a cipher key, a mac key, and a IV)
 */
protected function getKeys($salt, $key) {
    $ivSize = mcrypt_get_iv_size($this->cipher, $this->mode);
    $keySize = mcrypt_get_key_size($this->cipher, $this->mode);
    $length = 2 * $keySize + $ivSize;

    $key = $this->pbkdf2('sha512', $key, $salt, $this->rounds, $length);

    $cipherKey = substr($key, 0, $keySize);
    $macKey = substr($key, $keySize, $keySize);
    $iv = substr($key, 2 * $keySize);
    return array($cipherKey, $macKey, $iv);
}

/**
 * Stretch the key using the PBKDF2 algorithm
 *
 * @see http://en.wikipedia.org/wiki/PBKDF2
 *
 * @param string $algo   The algorithm to use
 * @param string $key    The key to stretch
 * @param string $salt   A random salt
 * @param int    $rounds The number of rounds to derive
 * @param int    $length The length of the output key
 *
 * @returns string The derived key.
 */
protected function pbkdf2($algo, $key, $salt, $rounds, $length) {
    $size   = strlen(hash($algo, '', true));
    $len    = ceil($length / $size);
    $result = '';
    for ($i = 1; $i <= $len; $i++) {
        $tmp = hash_hmac($algo, $salt . pack('N', $i), $key, true);
        $res = $tmp;
        for ($j = 1; $j < $rounds; $j++) {
             $tmp  = hash_hmac($algo, $tmp, $key, true);
             $res ^= $tmp;
        }
        $result .= $res;
    }
    return substr($result, 0, $length);
}

protected function pad($data) {
    $length = mcrypt_get_block_size($this->cipher, $this->mode);
    $padAmount = $length - strlen($data) % $length;
    if ($padAmount == 0) {
        $padAmount = $length;
    }
    return $data . str_repeat(chr($padAmount), $padAmount);
}

protected function unpad($data) {
    $length = mcrypt_get_block_size($this->cipher, $this->mode);
    $last = ord($data[strlen($data) - 1]);
    if ($last > $length) return false;
    if (substr($data, -1 * $last) !== str_repeat(chr($last), $last)) {
        return false;
    }
    return substr($data, 0, -1 * $last);
 }
}

Actualización: He estado tratando de descifrar una cadena encriptada con Mcrypt usando OpenSSL mediante la conversión de la biblioteca a OpenSSL.

Luego, estoy encriptando una cadena usando una clave usando el código anterior, y tratando de descifrar ese valor usando el siguiente código y la misma clave. Sin embargo, solo recibo una respuesta en blanco. Si comento:

$ data = $ this-> unpad ($ dec)

en la función de descifrado, obtengo una cadena pero solo son caracteres mezclados (muy parecido a cuando se encripta por primera vez).

<?php 

namespace Utilities\Encryption;

/**
* A class to handle secure encryption and decryption of arbitrary data
*
* Note that this is not just straight encryption.  It also has a few other
*  features in it to make the encrypted data far more secure.  Note that any
*  other implementations used to decrypt data will have to do the same exact
*  operations.  
*
* Security Benefits:
*
* - Uses Key stretching
* - Hides the Initialization Vector
* - Does HMAC verification of source data
*
*/
class EncryptionOpenSsl {

/**
 * @var string $cipher The mcrypt cipher to use for this instance
 */
protected $cipher = '';

/**
 * @var int $mode The mcrypt cipher mode to use
 */
protected $mode = '';

/**
 * @var int $rounds The number of rounds to feed into PBKDF2 for key generation
 */
protected $rounds = 100;

/**
 * Constructor!
 *
 * @param string $cipher The MCRYPT_* cypher to use for this instance
 * @param int    $mode   The MCRYPT_MODE_* mode to use for this instance
 * @param int    $rounds The number of PBKDF2 rounds to do on the key
 */
public function __construct($cipher, $rounds = 100) {
    $this->cipher = $cipher;
    // $this->mode = MCRYPT_MODE_CBC;
    $this->rounds = (int) $rounds;
}

/**
 * Decrypt the data with the provided key
 *
 * @param string $data The encrypted datat to decrypt
 * @param string $key  The key to use for decryption
 * 
 * @returns string|false The returned string if decryption is successful
 *                           false if it is not
 */
public function decrypt($data, $key) {
    $salt = substr($data, 0, 128);
    $enc = substr($data, 128, -64);
    $mac = substr($data, -64);

    list ($cipherKey, $macKey, $iv) = $this->getKeys($salt, $key);

    if ($mac !== hash_hmac('sha512', $enc, $macKey, true)) {
         return false;
    }
    $dec = openssl_decrypt($enc, $this->cipher, $key, OPENSSL_RAW_DATA, $iv);
    // $dec = mcrypt_decrypt($this->cipher, $cipherKey, $enc, $this->mode, $iv);

    $data = $this->unpad($dec);

    return $data;
}

/**
 * Encrypt the supplied data using the supplied key
 * 
 * @param string $data The data to encrypt
 * @param string $key  The key to encrypt with
 *
 * @returns string The encrypted data
 */
public function encrypt($data, $key) {
    $salt = mcrypt_create_iv(128, MCRYPT_DEV_URANDOM);
    list ($cipherKey, $macKey, $iv) = $this->getKeys($salt, $key);

    $data = $this->pad($data);

    $enc = mcrypt_encrypt($this->cipher, $cipherKey, $data, $this->mode, $iv);

    $mac = hash_hmac('sha512', $enc, $macKey, true);
    return $salt . $enc . $mac;
}

/**
 * Generates a set of keys given a random salt and a master key
 *
 * @param string $salt A random string to change the keys each encryption
 * @param string $key  The supplied key to encrypt with
 *
 * @returns array An array of keys (a cipher key, a mac key, and a IV)
 */
protected function getKeys($salt, $key) {
    $ivSize = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_CBC);
    $keySize = mcrypt_get_key_size(MCRYPT_BLOWFISH, MCRYPT_MODE_CBC);
    $length = 2 * $keySize + $ivSize;

    $key = $this->pbkdf2('sha512', $key, $salt, $this->rounds, $length);

    $cipherKey = substr($key, 0, $keySize);
    $macKey = substr($key, $keySize, $keySize);
    $iv = substr($key, 2 * $keySize);
    return array($cipherKey, $macKey, $iv);
}

/**
 * Stretch the key using the PBKDF2 algorithm
 *
 * @see http://en.wikipedia.org/wiki/PBKDF2
 *
 * @param string $algo   The algorithm to use
 * @param string $key    The key to stretch
 * @param string $salt   A random salt
 * @param int    $rounds The number of rounds to derive
 * @param int    $length The length of the output key
 *
 * @returns string The derived key.
 */
protected function pbkdf2($algo, $key, $salt, $rounds, $length) {
    $size   = strlen(hash($algo, '', true));
    $len    = ceil($length / $size);
    $result = '';
    for ($i = 1; $i <= $len; $i++) {
        $tmp = hash_hmac($algo, $salt . pack('N', $i), $key, true);
        $res = $tmp;
        for ($j = 1; $j < $rounds; $j++) {
             $tmp  = hash_hmac($algo, $tmp, $key, true);
             $res ^= $tmp;
        }
        $result .= $res;
    }
    return substr($result, 0, $length);
}

protected function pad($data) {
    $length = mcrypt_get_block_size(MCRYPT_BLOWFISH, MCRYPT_MODE_CBC);
    $padAmount = $length - strlen($data) % $length;
    if ($padAmount == 0) {
        $padAmount = $length;
    }
    return $data . str_repeat(chr($padAmount), $padAmount);
}

protected function unpad($data) {
    $length = mcrypt_get_block_size(MCRYPT_BLOWFISH, MCRYPT_MODE_CBC);
    $last = ord($data[strlen($data) - 1]);
    if ($last > $length) return false;
    if (substr($data, -1 * $last) !== str_repeat(chr($last), $last)) {
        return false;
    }
    return substr($data, 0, -1 * $last);
 }
}

Respuestas a la pregunta(1)

Su respuesta a la pregunta