Author Topic: Use bcrypt or not in login script?  (Read 2665 times)

0 Members and 5 Guests are viewing this topic.

Offline The Alchemist

  • Peasant
  • *
  • Posts: 100
  • Cookies: 18
  • Cult Of Personality
    • View Profile
    • Scriptings - Paste Tool
Use bcrypt or not in login script?
« on: March 30, 2013, 12:15:30 pm »

Hello EZ Web Developers,


I'd read this in a lot of places that the best way of storing passwords in databases would be hashing(or encrypting, a little confused about which term refers to the irreversible algo) the password using bcrypt algorithm and I come across this class that some guy made, for performing bcrypt algorithm on passwords.


Here's the class :
Code: (php) [Select]
<?php
class Bcrypt
{
private $rounds;
    public function 
__construct($rounds 12)
    {
if(CRYPT_BLOWFISH != 1)
{
throw new Exception("bcrypt not supported in this installation. See http://php.net/crypt");
}
$this->rounds $rounds;
}

public function hash($input)
{
$hash crypt($input$this->getSalt());

if(strlen($hash) > 13)
    return $hash;
return false;
}

public function verify($input$existingHash)
{
$hash crypt($input$existingHash);

return $hash === $existingHash;
}

private function getSalt()
{
$salt sprintf('$2a$%02d$'$this->rounds);

$bytes $this->getRandomBytes(16);

$salt .= $this->encodeBytes($bytes);

return $salt;
}

private $randomState;

private function getRandomBytes($count)
{
$bytes '';

if(function_exists('openssl_random_pseudo_bytes') &&
          (
strtoupper(substr(PHP_OS03)) !== 'WIN')) // OpenSSL slow on Win
{
$bytes openssl_random_pseudo_bytes($count);
}

if($bytes === '' && is_readable('/dev/urandom') &&
           (
$hRand = @fopen('/dev/urandom''rb')) !== FALSE)
{
$bytes fread($hRand$count);
fclose($hRand);
}

if(strlen($bytes) < $count)
{
$bytes '';

if($this->randomState === null)
{
$this->randomState microtime();
if(function_exists('getmypid'))
{
$this->randomState .= getmypid();
}
}

for($i 0$i $count$i += 16)
{
$this->randomState md5(microtime() . $this->randomState);

if (PHP_VERSION >= '5')
{
$bytes .= md5($this->randomStatetrue);
}
else
{
$bytes .= pack('H*'md5($this->randomState));
}
}

$bytes substr($bytes0$count);
}

return $bytes;
}

private function encodeBytes($input)
{
// The following is code from the PHP Password Hashing Framework
$itoa64 './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

$output '';
$i 0;
do
{
$c1 ord($input[$i++]);
$output .= $itoa64[$c1 >> 2];
$c1 = ($c1 0x03) << 4;
if ($i >= 16)
{
$output .= $itoa64[$c1];
break;
}

$c2 ord($input[$i++]);
$c1 |= $c2 >> 4;
$output .= $itoa64[$c1];
$c1 = ($c2 0x0f) << 2;

$c2 ord($input[$i++]);
$c1 |= $c2 >> 6;
$output .= $itoa64[$c1];
$output .= $itoa64[$c2 0x3f];
} while (1);

return $output;
}
}
?>
[size=78%]


Now, as you may know, passwords that are hashed(or encrypted) using bcrypt algorithm may have different results, thats why, there's a verify() function in the class given above that check whether a given string and a bcrypt hashed string are equivalent or not.
For example, the verify() is used like this :
[/size]
Code: () [Select]
include("includes/file_with_bcrypt_class.php");
$bcrypt   = new Bcrypt();
$hash     = $bcrypt->hash("abcd"); // Returns the bcrypt equivalent of "abcd"
$verify_1 = $bcrypt->verify("abcd", $hash); // This will return true as the value of $hash is the bcrypt equivalent of "abcd"
$verify_2 = $bcrypt->verify("1234", $hash); // This will return false as the value of $hash is NOT the bcrypt equivalent of "1234"
[size=78%]


Now, to make a log in credentials verification script, I could either do this :
[/size]
Code: (php) [Select]
require("includes/mysql_pdo_connect.php");
$username = $_POST['username'];
$password = sha1($_POST['password']); // or maybe use sha256 or something else with/without a salt
$query    = $pdo_connect->prepare("SELECT * FROM `users` WHERE `username` = ? AND `password` = ?");
$query->execute(array($username, $password));
if($query->rowCount() == 1) // Keep in mind, my database has the sha1 or sha256 or... equivalent of the password
    echo "Verified and authorised";
[size=78%]
   


OR I could do this :
[/size]
Code: (php) [Select]
require("includes/mysql_pdo_connect.php");
require("includes/file_with_bcrypt_class.php");
$bcrypt   = new Bcrypt();
$username = $_POST['username'];
$password = $_POST['password'];
$query    = $pdo_connect->prepare("SELECT `password` FROM `users` WHERE `username` = ?");
$query->execute(array($username));
if($query->rowCount() != 0)
{
    $row  = $query->fetch(PDO::FETCH_ASSOC); // Keep in mind, my database table has a bcrypt equivalent of the password
    if($bcrypt->verify($password, $row['password'])) // If the function verify() returns true, user is verified and authorised
    {
        echo "Verified and authorised";
    }
}
[size=78%]


In the first code, my code is protected from SQLi and quite secure but, there's a problem. There are so many rainbow tables around the internet and password may be 'decrypted'
In the second code, my code is secure from SQLi too(I guess), but the problem is, the function verify() is not an inbuilt PHP function(that is verified and experimented by PHP security experts), so there may be security holes in that function.


So, which one do I use for the best protection?


Opinions and reasons please everyone!! The better opinions and solutions we get, the better we learn.[/size]
Defeat the best... To be the best...

Offline Fur

  • Knight
  • **
  • Posts: 216
  • Cookies: 34
    • View Profile
Re: Use bcrypt or not in login script?
« Reply #1 on: March 30, 2013, 05:34:33 pm »
I prefer Pbkdf2 over Bcrypt.

Pbkdf2 makes it VERY hard for an attacker to retrieve the plaintext of a hash.
If will add a random salt to your value before hashing (so the hash won't be parallel to anything in a rainbow table, rendering them useless) and hashes it X times (so the attacker will have to crack X hashes before he can retrieve the plaintext, where X = how many iterations you choose).
It's also slow, which is good.
Here's an implementation of Pbkdf2: https://defuse.ca/php-pbkdf2.htm

If you're storing user credentials, use Pbkdf2. It'll make retrieving the plaintext a pain in the arse.

Quote
or encrypting, a little confused about which term refers to the irreversible algo
Encryption is reversible, hashing is not.

Quote
the function verify() is not an inbuilt PHP function(that is verified and experimented by PHP security experts), so there may be security holes in that function.
The 'verify()' function just hashes $input and compares it to $existing_hash.
So if there are vulnerabilities in verify(), they exist in the entire algorithm.

Regarding the authentication script: It depends. If you don't want the plaintext leaked, use Pbkdf2/Bcrypt.

You know what?
Just read this: https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet


P.S: I'm no expert on security.
« Last Edit: March 30, 2013, 05:38:11 pm by Fur »

Offline relax

  • Sir
  • ***
  • Posts: 562
  • Cookies: 114
  • The one and only
    • View Profile
Re: Use bcrypt or not in login script?
« Reply #2 on: March 30, 2013, 07:05:39 pm »
I think you will be fine with standard md5 hashing and salt.
what you should think about is guidelines for passwords for users

Code: (PHP) [Select]
if (!preg_match('/(?=.*\d)(?=.*[a-z])(?=.*[A-Z])/', $_POST['pwd']) && strlen($_POST['pwd']) =< 6) {
    echo "password must contain at least a upper, lower and digital character and have a minimum length of 6 characters";
} else $password = md5("This-1S_My_'s3cret'_Str1ng".md5($_POSt['pwd']."-Lets-dance-lambada"));


the password Ma4aa8 would take a desktop PC 94 septemvigintillion years to brute force that hash.
just keep your source and salts hidden. you can ofc mix md5, sha1/256/512 and all those other one way hashes.

but then again agains a skilled hacker your screwed witch ever method you use if you have other flaws in your code

Offline The Alchemist

  • Peasant
  • *
  • Posts: 100
  • Cookies: 18
  • Cult Of Personality
    • View Profile
    • Scriptings - Paste Tool
Re: Use bcrypt or not in login script?
« Reply #3 on: March 31, 2013, 08:48:12 am »
Thanks for the opinions guys. Thanks a lot.
Defeat the best... To be the best...

Offline Stackprotector

  • Administrator
  • Titan
  • *
  • Posts: 2515
  • Cookies: 205
    • View Profile
Re: Use bcrypt or not in login script?
« Reply #4 on: April 03, 2013, 09:51:04 am »
I think you will be fine with standard md5 hashing and salt.
what you should think about is guidelines for passwords for users

Code: (PHP) [Select]
if (!preg_match('/(?=.*\d)(?=.*[a-z])(?=.*[A-Z])/', $_POST['pwd']) && strlen($_POST['pwd']) =< 6) {
    echo "password must contain at least a upper, lower and digital character and have a minimum length of 6 characters";
} else $password = md5("This-1S_My_'s3cret'_Str1ng".md5($_POSt['pwd']."-Lets-dance-lambada"));


the password Ma4aa8 would take a desktop PC 94 septemvigintillion years to brute force that hash.
just keep your source and salts hidden. you can ofc mix md5, sha1/256/512 and all those other one way hashes.

but then again agains a skilled hacker your screwed witch ever method you use if you have other flaws in your code
You should die, die in hell.
No really, md5 is old, there are even COLLISION attacks. Bcrypt hashing is one of the best methods out there. Most big opensource systems use it, it's proven to be secure.
Quote
bcrypt is an hashing algorithm which is scalable with hardware (via a configurable number of rounds). Its slowness and multiple rounds ensures that an attacker must deploy massive funds and hardware to be able to crack your passwords. Add to that per-password salts (bcrypt REQUIRES salts) and you can be sure that an attack is virtually unfeasible without either ludicrous amount of funds or hardware.
~Factionwars

Offline relax

  • Sir
  • ***
  • Posts: 562
  • Cookies: 114
  • The one and only
    • View Profile
Re: Use bcrypt or not in login script?
« Reply #5 on: April 03, 2013, 01:21:38 pm »
COLLISION attacks


OMG I did not know that :/
guess I will look at bcrypt closer then


thanks for the info +1

Offline TETYYS

  • /dev/null
  • *
  • Posts: 16
  • Cookies: -12
    • View Profile
Re: Use bcrypt or not in login script?
« Reply #6 on: April 03, 2013, 02:17:33 pm »
lol, just grab hmac whirlpool and forget problems.

Offline Stackprotector

  • Administrator
  • Titan
  • *
  • Posts: 2515
  • Cookies: 205
    • View Profile
Re: Use bcrypt or not in login script?
« Reply #7 on: April 03, 2013, 02:26:27 pm »
lol, just grab hmac whirlpool and forget problems.
You could do that, but in the end we are security guys and we should always concentrate on security methods.
~Factionwars

Offline TETYYS

  • /dev/null
  • *
  • Posts: 16
  • Cookies: -12
    • View Profile
Re: Use bcrypt or not in login script?
« Reply #8 on: April 03, 2013, 06:11:26 pm »
You could do that, but in the end we are security guys and we should always concentrate on security methods.
But that's secure, if you don't know secret key, you will _never_ brute it.