I'm trying to generate salt using Mcrypt's mcrypt_create_iv(), but it doesn't seems to work and I'm getting errors.
Here is my code:
<?php
$salt= substr(mcrypt_create_iv(16, MCRYPT_DEV_URANDOM))(mt_rand()),0,22);
echo $salt;
?>
$salt = substr( mcrypt_create_iv(16, MCRYPT_DEV_URANDOM), mt_rand( 0, 22 ) );
you have some syntax errors
This cannot work, you use mcrypt_create_iv() to get random bytes, but those cannot be used for hashing with BCrypt. The problem is, that mcrypt_create_iv returns binary data, while BCrypt expects a salt with characters of a given alphabet. You would have to encode your salt to this alphabet: ./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz. The function mt_rand() is of no use here.
PHP 5.5 will have it's own functions password_hash() and password_verify() ready, to simplify generating BCrypt password hashes. I strongly recommend to use this excellent api, or it's compatibility pack for earlier PHP versions. The usage is very straightforward:
// 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);
Related
I'm trying to make register and log in forms having salt encryption, and I'm not really familiar with it. So everything is working except that log in can't recognize password so I'm pretty sure it's encryption problem. These are lines for register:
$hash = hash('sha256', $password1);
function createSalt()
{
$text = md5(uniqid(rand(), true));
return substr($text, 0, 3);
}
$salt = createSalt();
$password = hash('sha256', $salt . $hash);
and these are for login:
$userData = mysql_fetch_array($result, MYSQL_ASSOC);
$hash = hash('sha256', $userData['salt'] . hash('sha256', $password) );
if($hash != $userData['password'])
{
echo "Incorrect password";
}
Can anybody point the problem. Thanks!
Actually your code should work as far as i can see, though it is very unsafe!
Problem: SHA256 is not appropriate to hash passwords, because it is ways too fast. Use a slow key-derivation function like BCrypt.
Problem: A three character salt with only letters is nearly no protection.
Maybe your database field is smaller than 64 characters, or you are comparing different passwords. In every case there is an easier and safer way to hash passwords, just use the new functions password_hash() and password_verify(). There exists also a compatibility pack for earlier PHP versions.
// 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);
There are quite a few things wrong with this. For starters: Are you storing the salt with the password? If not, then passwords become unverifiable.
Security considerations:
hash('sha256', ... is insufficient; consider bcrypt, scrypt, or pbkdf2
https://github.com/DomBlack/php-scrypt
http://us2.php.net/password_hash
https://defuse.ca/php-pbkdf2.htm
$text = md5(uniqid(rand(), true)); Ever heard of openssl_random_pseudo_bytes()?
(Also, you shouldn't seek to decrypt passwords, only verify them.)
If you're not familiar with these concepts, play it safe and use a tried and true library.
I'm writing a piece of php code but is does not give me the output i want;
function passhash($unhashPass){
if(CRYPT_BLOWFISH != 1) {
throw new Exception("bcrypt not supported in this installation.);
}
$salt = "test123";
$password = hash_pbkdf2 ("sha256", $unhashPass, $salt, 1, 20);
echo $password;
return $password;
}
When i put an echo statement for unhashpass or salt before the hash it works, but after it does nothing, the whole php script just gives me a white screen.
Can somebody help me :)?
Cheers
The function hash_pbkdf2() will be introduced in PHP version 5.5, so i suspect that your installed PHP version does not yet support this function. Before you call the function, you test whether BCrypt is defined, but the function hash_pbkdf2() (password-based-key-derivation-function) has nothing to do with BCrypt.
It is recommended to hash passwords with BCrypt though, in PHP version 5.5 you can do it with password_hash() instead. There also exist a compatibility pack for earlier versions.
// 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);
I have created this code for a salt and pepper password encryption. I assume this is a good way to encrypt passwords, but what level of encryption is this?
I first thought the 'bit' part was the length of characters used but I know that is incorrect. How many bits of encryption would this be?
PHP
function _h() {
$result = "";
$charPool = '0123456789abcdefghijklmnopqrstuvwxyz';
for($p = 0; $p<32; $p++)
$result .= $charPool[mt_rand(0,strlen($charPool)-1)];
return md5(sha1(md5(sha1($result))));
}
$salt = _h();
$pepper = _h();
$pass = $salt.md5($salt.md5($_POST['password']).$pepper).$pepper;
UPDATE
I understand this is not encryption, so I would not be able to say this is encrypted, but instead hashed. Is a hashed password with a salt and pepper secure enough to save a password?
There are quite a lot of problems with your scheme to hash a password.
PHP 5.5 will have it's own functions password_hash() and password_verify() ready, to simplify generating BCrypt password hashes. I strongly recommend to use this excellent api, or it's compatibility pack for earlier PHP versions. The usage is very straightforward:
// 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);
These functions will solve following problems:
They use a slow adaptable hash function (BCrypt), MD5 is ways too fast for hashing passwords.
They generate a safe salt from the random source of the operating system.
A pepper is not just a second salt, in contrast to a salt, the pepper is secret and will not be stored together with the hash. The same pepper will normally be used for all passwords.
There is no use in complicating the computation of salt and $peppr too much. After all the task is not the retrieval of what was originally used to produce these spices but trather the value of $_POST('a'] and you give away the $saltand $pepper as prefix/suffix (otherwise you couldn't use the stored valuelater to verify an input password with this hash). That being said, do as #zneak commented and use an expert library function.
$salt = uniqid();
$crypt = md5($password , $salt);
$new_pass = $crypt.':'.$salt;
In the database: ot÷„[ªà%Ûʼn¹:17b8bc731c322c9e05a26666458117f4
Is this a syntactical error? Or is the database not set up with the correct character formatting?
You enabled raw_output
PHP DOC
If the optional raw_output is set to TRUE, then the md5 digest is instead returned in raw binary format with a length of 16.
Change
$crypt = md5($password , $salt);
^------ You moved the salt to raw_output
To
$crypt = md5($password . $salt);
^------ Should be this
For security reasons i would not advice you to use md5 for password hashing. MD5 is so badly broken that it no longer takes so long to find an appropriate collision or reverse hash. Once broken, a hash algorithm only gets worse, never better therefore it would be better to choose an unbroken hash algorithm.
Standard
sha1
hash (sha256 & sha512)
Better Alternatives
password_compat
Portable PHP password hashing framework
PBKDF2
I've been using PHP's crypt() as a way to store and verify passwords in my database. I use hashing for other things, but crypt() for passwords. The documentation isn't that good and there seems to be a lot of debate. I'm using blowfish and two salts to crypt a password and store it in the database. Before I would store the salt and the encrypted password, (like a salted hash) but realized its redundant because the salt is part of the encrypted password string.
I'm a little confused on how rainbow table attacks would work on crypt(), anyway does this look correct from a security standpoint. I use a second salt to append to the password to increase the entropy of short passwords, probably overkill but why not?
function crypt_password($password) {
if ($password) {
//find the longest valid salt allowed by server
$max_salt = CRYPT_SALT_LENGTH;
//blowfish hashing with a salt as follows: "$2a$", a two digit cost parameter, "$", and 22 base 64
$blowfish = '$2a$10$';
//get the longest salt, could set to 22 crypt ignores extra data
$salt = get_salt ( $max_salt );
//get a second salt to strengthen password
$salt2 = get_salt ( 30 ); //set to whatever
//append salt2 data to the password, and crypt using salt, results in a 60 char output
$crypt_pass = crypt ( $password . $salt2, $blowfish . $salt );
//insert crypt pass along with salt2 into database.
$sql = "insert into database....";
return true;
}
}
function get_salt($length) {
$options = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./';
$salt = '';
for($i = 0; $i <= $length; $i ++) {
$options = str_shuffle ( $options );
$salt .= $options [rand ( 0, 63 )];
}
return $salt;
}
function verify_password($input_password)
{
if($input_password)
{
//get stored crypt pass,and salt2 from the database
$stored_password = 'somethingfromdatabase';
$stored_salt2 = 'somethingelsefromdatabase';
//compare the crypt of input+stored_salt2 to the stored crypt password
if (crypt($input_password . $stored_salt2, $stored_password) == $stored_password) {
//authenticated
return true;
}
else return false;
}
else return false;
}
You really should have a look at PHPASS: http://www.openwall.com/phpass/ It's a password hashing framework using crypt() which is used in projects like Wordpress and phpBB.
There is also an excellent article on this website about password hashing, salting and stretching using crypt(): http://www.openwall.com/articles/PHP-Users-Passwords
UPDATE:
Currently there's an alternative for the PHPASS library. In the next version of PHP there are special functions for hashing and verifying passwords (using bcrypt): http://www.php.net/manual/en/ref.password.php. There is a compatibility library that implements these functions for PHP 5.3.7+: https://github.com/ircmaxell/password_compat
Your use of crypt() is fine. crypt($input, $stored) == $stored is the way it is designed to be used.
Your get_salt() function is not great, since it is using the often-poor rand() function. You should consider using a stronger random function, like openssl_random_pseudo_bytes(), instead.
The idea of a rainbow table is that an attacker can make a table with all possible passwords and their hashes at home.
E.g.
PASSWORD HASH
iloveSO gjroewjgo
password knbnogjwm
secret gjroehghe
jbieber rewgroewj
etc.
With this table, the attacker can quickly convert any hash to a password. Rainbow table uses some tricks so that not all hashes have to be stored, but it still computes all hashes beforehand.
By using a salt, even when storing it with the password, you make this much harder. Instead of hashing every word in a dictionary, the attacker would now have to hash every word with every salt. With a long enough salt, this gives enough combinations to make it unfeasible to compute all these hashes.
So a salt is not meant to be an extra password, known only to the application, it is meant to change the hash function so that it is non-standard.
This is a misuse of crypt() because you are using a deprecated primitive. Blowfish is very old, twofish is the replacement and even that is old because threefish is almost finalized. You should be using a member of the sha2 family, sha256 or sha512 are both good choices. crypt() can be used with sha256 or sha512, you should use the CRYPT_SHA256 CRYPT_SHA512 parameters respectively.
Also your salts have a very small entropy/size ratio, you are only using an alphanumeric set which is a joke because alphanumeric rainbow tables are the most common. You should be using a full byte which base256, and I recommend a salt that is 256 bytes long. Keep in mind all hash functions are binary safe by definition thus you shouldn't have to worry about null bytes and the like.
Use SHA-512 (if available) with a salt which includes time() and openssl_random_pseudo_bytes(). Crypt is consolidated / efficient because it returns the salt inserted with the hashed string.