Skip to main content
Tweeted twitter.com/#!/StackCodeReview/status/498051531842011136
deleted 182 characters in body; edited title
Source Link
Jamal
  • 35.2k
  • 13
  • 134
  • 238

Am I'mI using PHP Mcrypt the right way?

This is a repost since I didn't know about codereview.stackexchange.com yesterday.

Am I'm using PHP Mcrypt the right way?

This is a repost since I didn't know about codereview.stackexchange.com yesterday.

Am I using PHP Mcrypt the right way?

deleted 5 characters in body; edited tags
Source Link
Alex L
  • 5.8k
  • 2
  • 26
  • 69

I have written a small wrapper class for using PHP Mcrypt for encrypting and decrypting some text data. This class generates a salt for hashing the key and encrypts the given data with the generated key hash. The encrypted data get stored with the initialization vector and the key salt into a container class. The container class can be decrypted when the given key is valid.

I have written a small wrapper class for using PHP Mcrypt for encrypting and decrypting some text data. This class generates a salt for hashing the key and encrypts the given data with the generated key hash. The encrypted data get stored with the initialization vector and the key salt into a container class. The container class can be decrypted when the given key is valid.

I have written a small wrapper class for using PHP Mcrypt for encrypting and decrypting text data. This class generates a salt for hashing the key and encrypts the given data with the generated key hash. The encrypted data get stored with the initialization vector and the key salt into a container class. The container class can be decrypted when the given key is valid.

Source Link

Am I'm using PHP Mcrypt the right way?

I have written a small wrapper class for using PHP Mcrypt for encrypting and decrypting some text data. This class generates a salt for hashing the key and encrypts the given data with the generated key hash. The encrypted data get stored with the initialization vector and the key salt into a container class. The container class can be decrypted when the given key is valid.

class Mcrypt
{
    /**
     * @var array
     */
    protected static $validCiphers = [
        MCRYPT_BLOWFISH,
        MCRYPT_TWOFISH,
        MCRYPT_RIJNDAEL_128,
        MCRYPT_RIJNDAEL_192,
        MCRYPT_RIJNDAEL_256,
        MCRYPT_SERPENT
    ];

    /**
     * @var string
     */
    protected $cipher = MCRYPT_TWOFISH;

    /**
     * @var string
     */
    protected $mode = MCRYPT_MODE_CBC;

    /**
     * @var string
     */
    protected $keyHashRounds = '11';

    /**
     * Encrypts the data with the given key.
     *
     * @param string $data
     * @param string $key
     * @return McryptContainer
     */
    public function encrypt($data, $key)
    {
        $data      = trim($data);
        $container = new McryptContainer;
        $container->setInitializationVector($this->getInitializationVector());
        $container->setPasswordSalt($this->generateSalt());
        $container->setCipher($this->cipher);

        $container->setData(mcrypt_encrypt(
            $this->cipher,
            $this->getKeyHash($key, $container->getPasswordSalt()),
            sha1($data) . $data,
            $this->mode,
            $container->getInitializationVector()
        ));

        return $container;
    }

    /**
     * Decrypts the container data with the given key
     * or returns false if the key is not valid.
     *
     * @param McryptContainer $container
     * @param string $key
     * @return bool|string
     */
    public function decrypt(McryptContainer $container, $key)
    {
        $data = trim(mcrypt_decrypt(
            $container->getCipher(),
            $this->getKeyHash($key, $container->getPasswordSalt()),
            $container->getData(),
            $this->mode,
            $container->getInitializationVector()
        ));

        $checkSum = substr($data, 0, 40);
        $data     = substr($data, 40);

        if (sha1($data) != $checkSum) {
            return false;
        }

        return $data;
    }

    /**
     * Generates a hash for the given key.
     *
     * @param string $key
     * @return string
     */
    protected function getKeyHash($key, $salt)
    {
        $length = mcrypt_enc_get_key_size(mcrypt_module_open($this->cipher, '', $this->mode, ''));
        $hash   = crypt($key, sprintf('$2a$%s$%s$', $this->keyHashRounds, $salt));

        return substr($hash, $length * -1);
    }

    /**
     * Generates a random salt.
     *
     * @return string
     */
    protected function generateSalt()
    {
        $length     = mcrypt_enc_get_key_size(mcrypt_module_open($this->cipher, '', $this->mode, ''));
        $validChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
        $salt       = '';
        $count      = strlen($validChars) - 1;

        while ($length--) {
            $salt .= $validChars[mt_rand(0, $count)];
        }

        return $salt;
    }

    /**
     * Generates a new mcrypt initialization vector.
     *
     * @return string
     */
    protected function getInitializationVector()
    {
        return mcrypt_create_iv(mcrypt_get_iv_size($this->cipher, $this->mode), MCRYPT_DEV_URANDOM);
    }

    /**
     * Sets the cipher.
     *
     * @param string $cipher
     */
    public function setCipher($cipher)
    {
        if (!in_array($cipher, static::$validCiphers)) {
            $msg = 'Given cipher is not supported, supported ciphers are: ' . implode(', ', static::$validCiphers);
            throw new \InvalidArgumentException($msg);
        }

        $this->cipher = $cipher;
    }

    /**
     * Sets the rounds used for hashing the key.
     *
     * @param string $keyHashRounds
     */
    public function setKeyHashRounds($keyHashRounds)
    {
        $this->keyHashRounds = $keyHashRounds;
    }
}

Are there any security issues with my usage of Mcrypt?

Here is a Gist containing both classes.

This is a repost since I didn't know about codereview.stackexchange.com yesterday.