Шифрование / дешифрование в PHP с MCRYPT... Непоследовательные результаты

Я давно использую ваш сайт, чтобы помочь мне с различными ответами на программирование, и, наконец, я столкнулся с проблемой, которую не могу найти нигде.

Я пытаюсь использовать mcrypt в PHP для шифрования и дешифрования паролей, хранящихся на сайте моего клиента. Эти пароли предназначены для использования на внешних сайтах, поэтому они должны быть зашифрованы / расшифрованы, а не хешированы. В настоящее время я обновляю их старую среду, Legato, до гораздо более новой платформы Yii. Пароли хранятся в текущей базе данных с использованием схемы шифрования, описанной в файле класса. Схема выглядит следующим образом:

<?php

//--------------------------------------------------------------------------
// Name: Legato_Encryption
// Desc: An encryption engine. Contains functions to encrypt and decrypt
//       text.
//--------------------------------------------------------------------------
class Legato_Encryption
{

    //------------------------------------------------------------------------
    // Public Variables
    //------------------------------------------------------------------------
    private $_cypher; // The cypher algorithm.
    private $_mode; // The encryption mode.
    private $_td; // The TD for mcrypt.
    private $_private_key; // The private key.

    //------------------------------------------------------------------------
    // Public Member Functions
    //------------------------------------------------------------------------
    //------------------------------------------------------------------------
    // Name: __construct()
    // Desc: Class constructor.
    //------------------------------------------------------------------------
    public function __construct( $private_key, $cypher = 'blowfish', $mode = 'cfb' )
    {

        // Make sure everything was filled in.
        if ( $private_key == "" || $cypher == "" || $mode == "" )
        {
            Legato_Debug_Debugger::add_item( 'Invalid parameters for encryption. NULL passed in.' );
            return false;
        }

        // Assign the class variables to those passed in.
        $this->_cypher = $cypher;
        $this->_mode = $mode;

        // Get the TD.
        $this->_td = mcrypt_module_open( $this->_cypher, '', $this->_mode, '' );

        // Get the expected key size based on mode and cipher  .
        $expected_key_size = mcrypt_enc_get_key_size( $this->_td );

        // We dont need to know the real key, we just need to be able to confirm a hashed version.
        $this->_private_key = substr( md5($private_key), 0, $expected_key_size );

    }

    //------------------------------------------------------------------------
    // Name: encrypt()
    // Desc: Encrypts the plaint text passed in.
    //------------------------------------------------------------------------
    public function encrypt( $plaintext )
    {

        // Create the IV.
        $iv = mcrypt_create_iv( mcrypt_enc_get_iv_size($this->_td), MCRYPT_RAND );

        // Initialize the mcrypt engine.
        mcrypt_generic_init( $this->_td, $this->_private_key, $iv );

        // Encode/encrypt the text.
        $crypttext = base64_encode( mcrypt_generic($this->_td, $plaintext) );

        // Shut down mcrypt.
        mcrypt_generic_deinit( $this->_td );

        // Return the iv prefixed to the encrypted text.
        return $iv . $crypttext;

    }

    //------------------------------------------------------------------------
    // Name: decrypt()
    // Desc: Decrypts the encrypted text passed in.
    //------------------------------------------------------------------------
    public function decrypt( $crypttext )
    {

        // Get the iv from the beginning of the encrypted text.
        $iv_size = mcrypt_enc_get_iv_size( $this->_td );
        $iv = substr( $crypttext, 0, $iv_size );

        // Get the encrypted text.
        $crypttext = substr( $crypttext, $iv_size );
        $plaintext = '';

        // Attempt to decrypt the text.
        if ( $iv )
        {

            // Initialize the mcrypt engine.
            mcrypt_generic_init( $this->_td, $this->_private_key, $iv );

            // Decode the crypted text, then decrypt it, then trim it of whitespaces.
            $plaintext = trim( mdecrypt_generic($this->_td, base64_decode($crypttext)) );

            // Shut down mcrypt.
            mcrypt_generic_deinit( $this->_td );

        } // End if $iv true.

        // Return the plain text.
        return $plaintext;

    }

}

Моя проблема в том, что, используя этот класс на живом сервере, он точно шифрует и дешифрует пароли. Если я возьму этот код, вставлю его в новый файл и использую его точно таким же образом с тем же вводом, он возвращает другую строку, обычно с "?" символы (не символы знака вопроса, но символы, которые веб-браузер не может интерпретировать).

Например, Legato_Encryption('hello', 'twofish'). Encrypt('hello') вернет что-то совершенно другое, чем если бы я использовал это, скажем, в Yii_Encryption('hello', 'twofish'). Encrypt('hello'). Это тот же код и та же процедура с теми же параметрами... как он может возвращать разные значения? Я полагаю, что функция encrypt() генерирует случайные значения каждый раз, когда выполняется, но decrypt() должна возвращать правильную строку.

Кто-нибудь видит возможную область, где этот код может быть темпераментным или давать противоречивые результаты? Я потратил слишком много времени на эту проблему, так как многие другие посты, посвященные подобным проблемам, не дали успешных результатов.

1 ответ

Похоже, вы столкнулись с проблемой "переносимого хеша", вызванной другой версией OS / PHP. Возможно, потребуется обновить хеши (я бы рекомендовал расширение поведения пароля Yii в phpNode) один раз программно, а затем использовать более новую систему хеширования...

Другие вопросы по тегам