【问题标题】:Crypt() salt generation and password encryption, well executed?Crypt() 盐生成和密码加密,执行得好吗?
【发布时间】:2013-12-20 12:10:02
【问题描述】:

这些是我用于密码加密和密码验证的一些功能。想知道这是否是处理它的好方法。我正在使用 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;
}

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

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:不存储盐,而是从数据库中的密码中提取:

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

【问题讨论】:

  • 我认为这个问题放在code review堆栈上会更好。
  • 另见 Openwall 的 PHP password hashing framework (PHPass)。它的便携性和强化了针对用户密码的一些常见攻击。编写框架 (SolarDesigner) 的人与编写 John The Ripper 并在 Password Hashing Competition 担任评委的人是同一个人。所以他对密码攻击略知一二。
  • 这个问题似乎属于 Stack Exchange 网络中的另一个站点。也许你应该试试Code Review Stack Exchange
  • $pw_and_salt['pw'] = crypt($input, "$hash");为什么 $hash 在引号中?应该不会吧?

标签: php mysql codeigniter salt crypt


【解决方案1】:

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

// 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 散列,因此盐将成为生成散列的一部分。无需单独存放。
  2. 盐的生成可以改进,使用操作系统MCRYPT_DEV_URANDOM的随机源。
  3. 如果您将成本因子更改为 9,格式将变为无效,因为 crypt 需要两位数。

【讨论】:

  • 嗨,马丁,感谢您的意见。我一定会使用你的建议。关于当前设置的一个问题,如果我没记错的话,我只能通过散列密码来验证输入的密码,就像我散列存储在数据库中的密码一样,我怎么能在不实际存储和检索盐的情况下做到这一点?跨度>
  • 我在原始帖子中添加了我的验证方法,无需从 DB 中添加盐。
  • @Jursels - salt 已经包含在生成的哈希值中,password_verify() 函数将从那里提取它以及成本因素。示例:哈希值$2y$10$nOUIs5kJ7naTuTFkBy1veuK0kSxUFXfuaOKdOKf9xYT0KKIGSJwFa 包含第三个$ 之后的盐,盐是nOUIs5kJ7naTuTFkBy1veu
猜你喜欢
  • 1970-01-01
  • 2010-11-04
  • 1970-01-01
  • 2013-12-21
  • 1970-01-01
  • 1970-01-01
  • 2012-07-07
  • 2016-02-21
  • 2014-01-24
相关资源
最近更新 更多