0

Following is the encryption class I am using in one of my php project. Where as this class was given as answer to one of the SO question here is the link

https://stackoverflow.com/a/5093422/5330647

/**
 * 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 (!hash_equals(hash_hmac('sha512', $enc, $macKey, true), $mac)) {
             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);
    }
}

Question: How do I save the encrypted data to a MySQL table which is returned from encrypt() function of this class?

Here the encrypted string is very long for password of only 5 chars and contains non ASCII characters.

  1. What data type should be used for column in a MySQL table for saving the output of this class?
  2. What should be the size of the column which can hold good size of password encrypted and padded.

EDIT: As this question was marked as duplicate i had just edited the title which gives clear idea.

Two way encryption was already answered and therefore i am using the given class in the answer for my project.

Problem : But i am unable to save the encrypted value which is encrypted using this class in MySQL database table.

Community
  • 1
  • 1
Sameer
  • 1
  • 3
  • 1
    Why encrypt when you can use bcrypt and salt built in to PHP ? its more than secure enougth. – SteffenCH Nov 29 '16 at 18:19
  • the answer you linked explains the storage size. if you're having trouble understanding it, commenting on that question might be better than asking a new question which is essentially a duplicate. – mister martin Nov 29 '16 at 18:24
  • 1
    Possible duplicate of [Two-way encryption: I need to store passwords that can be retrieved](http://stackoverflow.com/questions/5089841/two-way-encryption-i-need-to-store-passwords-that-can-be-retrieved) – mister martin Nov 29 '16 at 18:25
  • 1
    *mcrypt* is abandomware, flagged as depreciated in PHP 7.1 and probably removed in PHP 7.2. – Xorifelse Nov 29 '16 at 18:54
  • Why would you **encrypt** passwords instead of **hash** them? – N.B. Nov 29 '16 at 21:28
  • Yeah ! i learned that password should not be encrypted at all but should be hashed. But what if i want to encrypt so other information and should be able to decrypt it for later use. for E.G: i have a unique Loyalty Points saved in my database table which are encrypted entries so any one with access to db does not change it. But while displaying it on the Dashboard of user it should be Decrypted So i used [link]http://stackoverflow.com/a/5093422/5330647[/link] to encrypt & decrypt. but now i am totally lost how to save this encrypted value in My Sql Table. – Sameer Dec 01 '16 at 15:48
  • @mistermartin : i dont have enough rep. to add comment to the question and thus asking for help in altogether in new question. – Sameer Dec 01 '16 at 16:01
  • **Do not encrypt passwords**, when the attacker gets the DB he will also get the encryption key. Just using a hash function is not sufficient and just adding a salt does little to improve the security. Iterate over an HMAC with a random salt for about a 100ms duration and save the salt with the hash. Use a function such as `ehash`, `PBKDF2`, `Rfc2898DeriveBytes`, `Bcrypt`, `passlib.hash` or similar functions. The point is to make the attacker spend a substantial of time finding passwords by brute force. – zaph Aug 14 '17 at 13:00

1 Answers1

-1

two way encryption in php

public function encryptIt( $q ) {
$cryptKey  = 'qJB0rGtIn5UB1xG03';
$qEncoded      = base64_encode( mcrypt_encrypt( MCRYPT_RIJNDAEL_256, md5( $cryptKey ), $q, MCRYPT_MODE_CBC, md5( md5( $cryptKey ) ) ) );
return( $qEncoded );

}

public function decryptIt( $q ) {
$cryptKey  = 'qJB0rGtIn5UB1xG03';
$qDecoded      = rtrim( mcrypt_decrypt( MCRYPT_RIJNDAEL_256, md5( $cryptKey ), base64_decode( $q ), MCRYPT_MODE_CBC, md5( md5( $cryptKey ) ) ), "\0\4");
return( $qDecoded );

}

  • 1. Don't use `MCRYPT_RIJNDAEL_256`, that is specifying a block size of 256-bits, this is usually done accidentally. It is better to specify a block size of 128-bits which is AES, the current encryption standard. – zaph Aug 14 '17 at 12:59
  • 2. It is best not to use mcrypt, it is abandonware, has not been updated in years and does not support standard PKCS#7 (née PKCS#5) padding, only non-standard null padding that can't even be used with binary data. mcrypt has many outstanding [bugs](https://sourceforge.net/p/mcrypt/bugs/) dating back to 2003. The mcrypt-extension is deprecated will be removed in PHP 7.2. Instead consider using [defuse](https://github.com/defuse/php-encryption) or [RNCryptor](https://github.com/RNCryptor), they provide a complete solution and are being maintained and is correct. – zaph Aug 14 '17 at 12:59
  • 3. The `cryptKey` is only about 42-bits of randomness, way to weak. Using MD5 to generate a key is not secure, one should use a password derivation function such as `PBKDF2`, `Rfc2898DeriveBytes` which are NUST recommended or equivalent. – zaph Aug 14 '17 at 13:04
  • 4. All encryoption is "two way encryption". Hash functiions are not encryption. – zaph Aug 15 '17 at 12:20
  • mcrypt deprecated, use: https://stackoverflow.com/questions/9262109/simplest-two-way-encryption-using-php – T.Todua Jan 18 '18 at 17:40