Search code examples
phpsecurityhashsystemcrypt

The most safe user login system


I am developing website and I am doing my best to ensure that I have a good security system. I am going to tell you what I have done and I have also another question about this system.

1) I am using sha512 method to hash password.salt and save it in database

2) my salt is generating randomly and every salt is unique, I am using this methods (developed in Yii framework)

class Random extends CApplicationComponent
{
    public static function intRandom($min, $max) 
    {
        $bits = '';

        $diff = $max-$min;
        $bytes = ceil($diff/256);


        $fp = @fopen('/dev/urandom','rb');
        if ($fp !== FALSE) {
            $bits .= @fread($fp,$bytes);
            @fclose($fp);
        }
        $bitlength = strlen($bits);
        for ($i = 0; $i < $bitlength; $i++) {
            $int =  1+(ord($bits[$i]) % (($max-$min)+1));
        }
        return $int;
    }

    public static function strRandom($length) {
        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_-+=|]}[{;:?.,></";   

        $size = strlen( $chars );
        for( $i = 0; $i < $length; $i++ ) {
            $str .= $chars[ self::intRandom(0, strlen($chars)-1) ];
        }

        return $str;
    }
}

3) after user loges in I am generating new salt and hashing password.new_salt (of course every salt must be unique)

        while ($record2 !== null){
            $salt = Random::strRandom(32);
            $record2 = User::model()->findByAttributes(array('salt'=>$salt));
        }
        $record->salt = $salt;
        $record->password = hash('sha512', $this->password.$salt);
        $record->save;

4) now it is time to save salt in database, and I am using Rijndael two way crypting method for it. mc_key is located in php file and every month I am replacing it.

function mc_encrypt($encrypt, $mc_key) {
    $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND);
    $passcrypt = trim(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $mc_key, trim($encrypt), MCRYPT_MODE_ECB, $iv));
    $encode = base64_encode($passcrypt);
    return $encode;
}

// Decrypt Function
function mc_decrypt($decrypt, $mc_key) {
    $decoded = base64_decode($decrypt);
    $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND);
    $decrypted = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $mc_key, trim($decoded), MCRYPT_MODE_ECB, $iv));
    return $decrypted;
}

So, What do you think? Is it enough or should I use something more?

I think, I made nightmare for hacker, or I am just another stupid programmer who is trying to create another bicycle.


Solution

  • One issue is that plain SHA512 is fast. You should use a slower method, such as bcrypt


    And intRandom sucks. If I understand it correctly

    1. it fails silently when /dev/urandom is absent, instead of dying loudly.
    2. The logic for $max-$min>=256 looks completely broken.
    3. $min != 1 is broken
    4. Its return values are not uniform