Crypt()盐生成和密码加密,执行良好


Crypt() salt generation and password encryption, well executed?

这些是我用于密码加密和密码验证的一些函数。我想知道这是否是一个处理它的好方法。我使用的是codeigniter框架。

这是"加密"的功能:

function crypt_pass( $input ){
    $salt = substr(sha1(date('r')), rand(0, 17), 22);
    $cost = 10;
    $hash = '$2y$' . $cost . '$' . $salt;
    $pw_and_salt['pw'] = crypt($input, "$hash");
    $pw_and_salt['salt'] = $salt;
    return $pw_and_salt;
}

我将密码和salt都存储在数据库中。这是登录功能:

function login(){
    $this->db->select('salt');
    $salt = $this->db->get_where('users', array('username' => $this->input->post('username') ) )->row();

    $where = array(
        'username' => $this->input->post('username'),
        'password' => crypt( $this->input->post('password'), '$2y$10$' . $salt->salt),
    );

    $user = $this->db->get_where('users', $where)->first_row();
    if (!$user) {
        return FALSE;
    }else{
        if(!empty($user->activation)){
            return 2;
        }else if($user && empty($user->activation)){
            $this->session->set_userdata('id',$user->id);
            $this->session->set_userdata('username',$user->username);
            $this->session->set_userdata('first_name',$user->first_name);   
            return 1;
        }
    }
}

我是否以正确的方式执行此操作?这足够安全吗?

版本2:不存储SALT,而是从数据库中的密码中提取:

function login(){
    $this->db->select('password');
    $pw = $this->db->get_where('users', array('username' => $this->input->post('username') ) )->row();

    $where = array(
        'username' => $this->input->post('username'),
        'password' => crypt( $this->input->post('password'), $pw->password),
    );
    $user = $this->db->get_where('users', $where)->first_row();
    if (!$user) {
        return FALSE;
    }else{
        if(!empty($user->activation)){
            return 2;
        }else if($user && empty($user->activation)){
            $this->session->set_userdata('id',$user->id);
            $this->session->set_userdata('username',$user->username);
            $this->session->set_userdata('first_name',$user->first_name);   
            return 1;
        }
    }
}

有些地方可以改进,但首先我建议使用PHP的新函数password_hash()。此函数将生成一个安全的salt,并将其包含在生成的哈希值中,因此您可以将其存储在单个数据库字段中。还有一个早期版本的兼容包。

// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT);
// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $existingHashFromDb.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);

关于你的代码的一些想法:

  1. 您使用crypt()生成BCrypt哈希,因此salt将是生成的哈希的一部分。没有必要单独存放
  2. 可以改进盐的生成,使用操作系统MCRYPT_DEV_URANDOM的随机源
  3. 如果将成本因子更改为9,则格式将变为无效,因为crypt需要两位数字