Does this code use Bcrypt or just plain blowfish? - php

I'm learning php security online (using php 5.4) and came across the following code that I'd like to learn about/use. Does the following code use bcrypt and is it a good implementation of blowfish?
If problems exist, can you please suggest a fix or resource. Thanks.
class PassHash {
// blowfish
private static $algo = '$2a';
// cost parameter
private static $cost = '$10';
// mainly for internal use
public static function unique_salt() {
return substr(sha1(mt_rand()),0,22);
}
// this will be used to generate a hash
public static function hash($password) {
return crypt($password,
self::$algo .
self::$cost .
'$' . self::unique_salt());
}
// this will be used to compare a password against a hash
public static function check_password($hash, $password) {
$full_salt = substr($hash, 0, 29);
$new_hash = crypt($password, $full_salt);
return ($hash == $new_hash);
}
}
Here is the usage during user registration:
// include the class
require ("PassHash.php");
// ...
// read all form input from $_POST
// ...
// do your regular form validation stuff
// ...
// hash the password
$pass_hash = PassHash::hash($_POST['password']);
// store all user info in the DB, excluding $_POST['password']
// store $pass_hash instead
// ...
And here is the usage during a user login process:
// include the class
require ("PassHash.php");
// read all form input from $_POST
// ...
// fetch the user record based on $_POST['username'] or similar
// ...
// ...
// check the password the user tried to login with
if (PassHash::check_password($user['pass_hash'], $_POST['password']) {
// grant access
// ...
} else {
// deny access
// ...
}

Short answer :
Yes it does use bcrypt blowfish (in PHP blowfish is the current algorithm for bcrypt)
Correct answer :
Why not use a trusted PHP compatibility library like this one?
The benefits of using this over the one you posted? :
It is widely used by many people (must be trusted and well taken by the community)
Allow for forward compatibility with php 5.5 native bcrypt function (hence name for passwd_compat) more info here : Info Here!
Allows for a rehash which is genius (pretty much if you decide to crank up the cost of the algorithm you can easily do so and check if the cost matches the one in the library file if not then you can just update the password)
Bottom line : You can only go wrong with bcrypt if you don't know what your doing. One thing to remember is : do not reinvent the wheel if there are already wheels out there.
Hopefully this answer can help you out / expand your knowledge.

Related

Bcrypt check password in codeigniter

I have a problem when decrypting passwords hashed with bcrypt. I can't login when I use this code. So, are there any mistakes?
function login(){
if ($this->session->userdata('username'))
{
redirect('dasbor');
}
//fungsi login
$valid = $this->form_validation;
$username = $this->input->post("username");
$password = $this->input->post("password");
$hash = $this->db->get('users')->row('password');
$hashp = $this->bcrypt->check_password($password,$hash);
$valid->set_rules("username","Username","required");
$valid->set_rules("password","Password","required");
if ($hashp) {
if($valid->run()) {
$this->simple_login->login($username,$hashp, base_url("dasbor"), base_url("Auth/login"));
}
}
// End fungsi login
$data = array('title'=>'Halaman Login Admin');
$this->load->view('admin/login_view',$data);
}
please help me to solve this problem.
I know this is an old question, but I want to help others who face the same problem.
First thing first, you need to rework again on your algorithm. The password_verify() function needs 2 parameters:
Password, the text that the user input in the text field before submitting the form.
Hash, a hash that is already stored in your database.
The goal is to verify if Password and Hash are similar. As you know, the password_hash() will return a different result at different times even when you hash the same string. Because of that, you can not use this->db->where() active record.
So, what I would do are these simple 2 steps:
Create a function in the model (e.g. Main_model.php) for getting user data.
public function get_user($user) {
$this->db->where('username', $user);
return $this->db->get('user')->row_array();
}
Get the password from the controller and use password_verify
$get_user = $this->main_model->get_user($this->input->post('username'));
if(password_verify($this->input->post('password'), $get_user['password'])){
// Success
}
else {
// Not Success
}
And one additional tip from me, don't write any active record in the Controller. It is not neat for the MVC method.

Slim Framework Twig Templating using MD5 as required password hash/encryption

I am trying to code an application around an existing database. It already has several hundred users and data involving those users. So trying to change over the database that is used by a different program(game) from md5 to password_bcrypt or the like is not possible. This application is supposed to be a user's panel to allow for profile info and display user's character information. what I have atm is using PASSWORD_BCRYPT. I can get it to register the user with the md5 hash, however, my biggest issue is coding a password check. Here is the current code using PASSWORD_BCRYPT:
public function password($password)
{
return password_hash(
$password,
$this->config->get('app.hash.algo'),
['cost' => $this->config->get('app.hash.cost')]
);
}
public function passwordCheck($password, $hash)
{
return password_verify($password, $hash);
}
Again I know how to write out the code to let the user register with an md5 hash, but when they login it fails. Here is the call to the passwordCheck function:
if ($v->passes()) {
$user = $app->user
->where('username', $identifier)
->first();
if ($user && $app->hash->passwordCheck($password, $user->password)) {
$_SESSION[$app->config->get('auth.session')] = $user->id;
$app->flash('global', 'You are now signed in!');
} else {
$app->flash('global', 'Could not log you in!');
}
$app->response->redirect($app->urlFor('login'));
}
any and all suggestions welcome.
Thanks in advance!
The issue turned out to be that because I need to use a different hash, I can't use PASSWORD_HASH or the follow up function password_verify since the password_verify is checking apparently for the password_hash function. I'm not totally sure. But the following code is what works:
public function password($encrypt)
{
$encrypt = $salt . md5($encrypt);
return $encrypt;
}
public function passwordCheck($password, $hash)
{
return (strcmp($password, $hash) == 0);
}
the salt is a custom salt that I will keep to myself. I've tested this with my current app I am building and it is working like I want it to. The user can register and log in. Thanks for the help, but sadly the answer above came from else where. I know this isn't as secure as it should be but again it is a must since I am forced to use a pre-existing database that is still in use.

PHP : Decrypt password from hash

So, I successfully encrypt a password to password hash using this following code :
class PassHash
{
// blowfish
private static $algo = '$2a';
// cost parameter
private static $cost = '$10';
// mainly for internal use
public static function unique_salt()
{
return substr(sha1(mt_rand()), 0, 22);
}
// this will be used to generate a hash
public static function hash($password)
{
return crypt($password, self::$algo .
self::$cost .
'$' . self::unique_salt());
}
// this will be used to compare a password against a hash
public static function check_password($hash, $password)
{
$full_salt = substr($hash, 0, 29);
$new_hash = crypt($password, $full_salt);
return ($hash == $new_hash);
}
}
and this is how I encrypting the password :
$password_hash = PassHash::hash($user->getPasswordHash());
But I have a little problem now when I try to display the password in normal mode.
What is the best way to decrypt the password from that hash ?
You can't decrypt a hash (well... technically you can, but you shouldn't) that's what hashes are for (not to be decrypted). You'll want to encrypt(hash) the password you received with the same hashing algorithm you used for the stored hash, and compare the hashes with eachother.
$password_hash = PassHash::hash($user->getPasswordHash());
if($stored_password === $password_hash){
//The passwords are the same
}
All in all you don't want to let anyone (not even yourself) know what the password of a user is (or the hash for that matter). The user will know, because he entered it and remembers it (hopefully anyway). No one else has got anything to do with seeing the user's password/hash. Letting anyone else but the user see/know the password/hash is a serious security issue.
On a different note: You should use the default implementations for hashing. Using your own hashing algorithm will always be worse than the true tried and tested methods. I'm not sure what PHP version you're using, but from PHP 5.5 onwards you can use password_hash(). For more information please view this question.

Check Parse.com password manually

I'm migrating a Parse.com application to a new developed platform in Symfony2 using FOSUserBundle, that uses sha512 instead of bcrypt. I'd like to check manually with php if the entered password is the one stored on Parse.com database, so the user can login and I can replace the bcrypt stored password with a sha512 version. Is there any way to accomplish that? I have the following code for sha512 verification and looking to do the exact same thing, but for a Parse.com bcrypt password:
$salted = $password.'{'.$entity->getSalt().'}';
$digest = hash('sha512', $salted, true);
for ($i = 1; $i < 5000; $i++) {
$digest = hash('sha512', $digest.$salted, true);
}
if(base64_encode($digest) == $entity->getPassword())
{
$message = 'OK';
}
else{
$message = 'Incorrect password.';
}
return $message;
The first step is to plug in your own password encoder.
# security.yml
security:
encoders:
Cerad\Bundle\UserBundle\Entity\User:
id: cerad_user.user_encoder
# services.yml
cerad_user.user_encoder:
class: Cerad\Bundle\UserBundle\Security\UserEncoder
arguments:
- '%cerad_user_master_password%'
So now, every time the security system want to check the user's password, it will call my UserEncoder
My UserEncoder looks like:
use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
/* =============================================================
* Defaults to sha512
* Then tries legacy md5
* Also supports master password
*/
class UserEncoder extends MessageDigestPasswordEncoder
{
public function __construct($master, $algorithm = 'sha512', $encodeHashAsBase64 = true, $iterations = 5000)
{
parent::__construct($algorithm,$encodeHashAsBase64,$iterations);
$this->master = $master;
}
public function isPasswordValid($encoded, $raw, $salt)
{
// Master Password
if ($raw == $this->master) return true;
// sha12
if ($this->comparePasswords($encoded, $this->encodePassword($raw, $salt))) return true;
// Legacy, be nice to force an update
if ($encoded == md5($raw)) return true;
// Oops
return false;
}
}
My encoder simple extends the default encoder which does the sha512 stuff by default. If sha512 fails then we check for an md5 encoding.
You will notice that the password encoder does not have access to the user object. It only deals with passwords. It's not real clear to me what you need to do to access your "parse.com" database. You might be able to plugin your own user provider (http://symfony.com/doc/current/cookbook/security/custom_provider.html) which could retrieve any parse.com password in the loadUserByUsername() method. Your question is somewhat unclear.
Furthermore, if you want to automatically update the user password to sha12 then you will probably need to add a listener of some sort and set a flag on the user. Again, your question lacks details. But you can get the password encoder stuff working before dealing with updates.
This is what I was looking for:
How do you use bcrypt for hashing passwords in PHP?
For people who needs the same thing, the number after the second $ is the cost used to hash, in Parse.com case is 10.
Thanks anyway Cerad!
This was the complete solution using Symfony2. Downvoters are just following the first guy, it's a valid question.
$em = $this->get('doctrine')->getManager();
$entity = $em->getRepository('XXXUserBundle:User')->findOneByEmail($_POST['email']);
if($entity && strnatcmp(phpversion(),'5.5.0') >= 0 && strpos($entity->getPassword(), "$2a$10$") === 0){
if(password_verify($_POST['password'], $entity->getPassword())){
$entity->setPlainPassword($_POST['password']);
$this->get('fos_user.user_manager')->updateUser($entity);
}
}
return new Response('OK');

CodeIgniter 2.1.0, jQuery: Login Security questions

I have a website where I do the following in order to let people log in:
jQuery: - using the $.md5() plugin and the $.cookie() plugin (for CodeIgniter CSRF protection cookie for post data)
$('#login').on('submit', function(e){
e.preventDefault();
$.get('/salt/', function(salt){
// get / set salt and salt flashdata
$.post('/login/', {
'username' : $('#l_username').val(),
'password' : $.md5('' + salt['m'] + $.md5($('#l_password').val()) + salt['s']),
//set to string (in case MD5 hash of password is an integer)hash password, add salt, hash salted password.
'_token' : $.cookie('_cookie')
}, function(r){
// *r* == 0: unknown user; 1: wrong password; 2: logged in; 3: database error; 4: session error;
// perform action depending on *r* value
})
})
});
PHP (CodeIgniter): - rout file forwards /salt/ and /login/ to /process/salt/ and /process/login/ - 'session' class is autoloaded
class Process extends CI_Controller {
public function __construct() {
parent::__construct();
$this->load->model('login'); // loads model with login functions ()
}
public function login() {
$data = array();
$data['username'] = $this->input->post('username');
$data['password'] = $this->input->post('password');
if ($data['username'] && $data['password']) {
//if user and password are set
$user = $this->login->getUser($data['username']);
if ($user->num_rows() === 1) {
// if the username is in the database
$user = $user->row();
$salt = $this->session->flashdata('s');
//flashdata set by ajax call to '/salt/'
$pass = $salt->m . $user->password . $salt->s;
//password is already hashed in database
if ($data['password'] === $pass){
// update logged_in database table then set login session
echo 2; // logged in; if database / session error, echo 3 / 4
} else {
echo 1; // wrong password
}
} else {
echo 0; //unknown user
}
}
}
public function salt() {
// set salt values based in minute and second time
$salt = (object) array('m' => intval(date('i')), 's' => intval(date('s')));
//intval() removes leading 0
$this->session->set_flashdata('s', $salt);
// flashdata only valid for the next server request (which is the login);
header('Content-type: application/json');
//return value as json string
echo json_encode($salt);
}
}
My question is this: exactly how secure is this log in method? Are there any potential loopholes in the script? I want to make sure that the log in process is as secure as possible without https for the moment.
If I'm guessing correctly, you are storing a md5-hashed version of the password in your database?
Would it not be better to store a hash of the password with a global salt and pass that global salt as well to the javascript? This way you don't have a hash in your database which is pretty easy to decifer if it's an easy password.
Even better would be to use a personal salt for each user, which you can get at the same time as the other salts.
'password' : $.md5('' + salt['m'] + $.md5($('#l_password').val() + salt['personal']) + salt['s']),
Another advice would be to use a stronger hashing function than md5 since that isn't so secure anymore.
This is all however in case your database gets leaked. The transfer of the password and username looks pretty secure and obfuscated though.
I think you still have a bug, since you don't make a md5 hash of your salted password on the php-side when comparing it to the received value. I think it should be:
//flashdata set by ajax call to '/salt/'
$pass = md5($salt->m . $user->password . $salt->s);
For hashing on the serverside could you use the spark-version of phpass, which everyone advices to use. Or you could just install it as a library.

Categories