Question

I've long been using your site to help me with various programming answers and I've finally come across a problem I can't find addressed anywhere else.

I am attempting to use mcrypt in PHP to encrypt and decrypt passwords stored on my client's website. These passwords are for use on external websites, so they must be encrypted/decrypted instead of hashed. I am currently updating their old framework, Legato, to the much more recent Yii framework. The passwords are stored in the current database using an encryption scheme outlined in a class file. The scheme is as follows:

<?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;

    }

}

My issue is that using that class on the live server, it accurately encrypts and decrypts the passwords. If I take that code, paste it to a new file and use it in the exact same way with the same input, it returns a different string, usually with "?" characters (not question mark characters, but characters the web browser can't interpret).

For instance, Legato_Encryption('hello', 'twofish').encrypt('hello') will return something entirely different than if I used it in say Yii_Encryption('hello', 'twofish').encrypt('hello'). It's the same code and same procedure with the same parameters...how can it be returning different values? I believe the encrypt() function seems to generate random values every time it is executed, but the decrypt() should return the correct string.

Does anyone see a possible area where this code can be temperamental or yield inconsistent results? I've spent way too much time on this problem as and many of the other posts on here about similar issues have not yielded successful results.

No correct solution

OTHER TIPS

Sounds like you are running into a "portable hash" issue caused by a different OS / PHP version. Might need to upgrade the hashes (I'd suggest phpNode's Yii password behavior extension) once programmatically and then use a newer hashing system after that ...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top