5

I am using simple md5($password); format but i want to add salt so how i can do that?

here is my code :

   if($success)
    {
        $data['firstname'] = $firstname;
        $data['lastname'] = $lastname;
        $data['username'] = $username;
        $data['password'] = md5($password);
        $data['email'] = $email;


        $newUser = new User($data);
        $newUser->save(true);
        $Newuser->login($username, $password);
        header("Location: welcome.php");

    }
deerox
  • 1,045
  • 3
  • 14
  • 28

5 Answers5

8
$data['hashedpwd'] = md5($salt . $password);

The longer, more complex and unique to each user you can make the salt the harder it will be for anyone to get the password (though it's not impossible).

A simple (but poor salt) would be: $salt = '10';
A much stronger salt would be: $salt = '-45dfeHK/__yu349@-/klF21-1_\/4JkUP/4';

Salts that are unique to the user are even better.

As mentioned in several comments md5 is an old and relatively poor hashing algorythm, SHA-512 or any of the SHA-2 family would be much better choices.

See this salting question for more detail.

Community
  • 1
  • 1
SteB
  • 1,999
  • 4
  • 32
  • 57
2

Other people have shown how it can be done, so about the principles in general...

Like already linked by NullUserException in the comments, you should not do it by just adding a static salt to md5, if security matters. Note however that you can store your salt as-is. Both static salt and md5 are not considered very safe approaches. They're ok if it doesn't matter that much, but if it does, you should go the other way.

About static salt:

A common mistake is to use the same salt in each hash. Either the salt is hard-coded into the program, or is generated randomly once. This is ineffective because if two users have the same password, they'll still have the same hash. An attacker can still use a reverse lookup table attack to run a dictionary attack on every hash at the same time. They just have to apply the salt to each password guess before they hash it. If the salt is hard-coded into a popular product, lookup tables and rainbow tables can be built for that salt, to make it easier to crack hashes generated by the product.

A new random salt must be generated each time a user creates an account or changes their password.

If the salt is static, an attacker can just generate a rainbow table for all possibilities. With a salt that's unique to a user, there's no point in doing that.

md5 is designed for computational speed, so it's fundamentally not the way to go. Also, there's already a lot of pre-created rainbow tables for it, and a lots of online cracking tools.

The page linked contains PHP source code, too, as an example of how to get this properly done.

<?php
/*
 * Password hashing with PBKDF2.
 * Author: havoc AT defuse.ca
 * www: https://defuse.ca/php-pbkdf2.htm
 */

// These constants may be changed without breaking existing hashes.
define("PBKDF2_HASH_ALGORITHM", "sha256");
define("PBKDF2_ITERATIONS", 1000);
define("PBKDF2_SALT_BYTES", 24);
define("PBKDF2_HASH_BYTES", 24);

define("HASH_SECTIONS", 4);
define("HASH_ALGORITHM_INDEX", 0);
define("HASH_ITERATION_INDEX", 1);
define("HASH_SALT_INDEX", 2);
define("HASH_PBKDF2_INDEX", 3);

function create_hash($password)
{
    // format: algorithm:iterations:salt:hash
    $salt = base64_encode(mcrypt_create_iv(PBKDF2_SALT_BYTES, MCRYPT_DEV_URANDOM));
    return PBKDF2_HASH_ALGORITHM . ":" . PBKDF2_ITERATIONS . ":" .  $salt . ":" . 
        base64_encode(pbkdf2(
            PBKDF2_HASH_ALGORITHM,
            $password,
            $salt,
            PBKDF2_ITERATIONS,
            PBKDF2_HASH_BYTES,
            true
        ));
}

function validate_password($password, $good_hash)
{
    $params = explode(":", $good_hash);
    if(count($params) < HASH_SECTIONS)
       return false; 
    $pbkdf2 = base64_decode($params[HASH_PBKDF2_INDEX]);
    return slow_equals(
        $pbkdf2,
        pbkdf2(
            $params[HASH_ALGORITHM_INDEX],
            $password,
            $params[HASH_SALT_INDEX],
            (int)$params[HASH_ITERATION_INDEX],
            strlen($pbkdf2),
            true
        )
    );
}

// Compares two strings $a and $b in length-constant time.
function slow_equals($a, $b)
{
    $diff = strlen($a) ^ strlen($b);
    for($i = 0; $i < strlen($a) && $i < strlen($b); $i++)
    {
        $diff |= ord($a[$i]) ^ ord($b[$i]);
    }
    return $diff === 0; 
}

/*
 * PBKDF2 key derivation function as defined by RSA's PKCS #5: https://www.ietf.org/rfc/rfc2898.txt
 * $algorithm - The hash algorithm to use. Recommended: SHA256
 * $password - The password.
 * $salt - A salt that is unique to the password.
 * $count - Iteration count. Higher is better, but slower. Recommended: At least 1000.
 * $key_length - The length of the derived key in bytes.
 * $raw_output - If true, the key is returned in raw binary format. Hex encoded otherwise.
 * Returns: A $key_length-byte key derived from the password and salt.
 *
 * Test vectors can be found here: https://www.ietf.org/rfc/rfc6070.txt
 *
 * This implementation of PBKDF2 was originally created by https://defuse.ca
 * With improvements by http://www.variations-of-shadow.com
 */
function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false)
{
    $algorithm = strtolower($algorithm);
    if(!in_array($algorithm, hash_algos(), true))
        die('PBKDF2 ERROR: Invalid hash algorithm.');
    if($count <= 0 || $key_length <= 0)
        die('PBKDF2 ERROR: Invalid parameters.');

    $hash_length = strlen(hash($algorithm, "", true));
    $block_count = ceil($key_length / $hash_length);

    $output = "";
    for($i = 1; $i <= $block_count; $i++) {
        // $i encoded as 4 bytes, big endian.
        $last = $salt . pack("N", $i);
        // first iteration
        $last = $xorsum = hash_hmac($algorithm, $last, $password, true);
        // perform the other $count - 1 iterations
        for ($j = 1; $j < $count; $j++) {
            $xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true));
        }
        $output .= $xorsum;
    }

    if($raw_output)
        return substr($output, 0, $key_length);
    else
        return bin2hex(substr($output, 0, $key_length));
}
Community
  • 1
  • 1
eis
  • 51,991
  • 13
  • 150
  • 199
2

PHP 5.5 will bring a very easy to use password hashing API, and it is currently reimplemented to be used right away with PHP starting at version 5.3.7.

I could copy&paste the explanation, but see for yourself: https://github.com/ircmaxell/password_compat

In short, it's like this:

/* Create the hash */
$hash = password_hash($password, PASSWORD_BCRYPT, array('cost' => 10));

/* Store the hash... then user comes back */
if (password_verify($password, $hash)) {
    /* Valid */
} else {
    /* Invalid */
}

/*
 * If the security level has to be increased to new $options or a new $algorithm,
 * silent rehashing is supported 
 */
if (password_verify($password, $hash)) {
    if (password_needs_rehash($hash, $algorithm, $options)) {
        $hash = password_hash($password, $algorithm, $options);
        /* Store new hash in db */
    }
}

The hash might be as long as 255 characters (not with bcrypt, but whatever might come next), plan the storage accordingly. Databases should use VARCHAR(255).

Sven
  • 69,403
  • 10
  • 107
  • 109
1

Here is an example : (Use your password here)

    $pass = 'abcxyz123'; // password 
    $salt = '}#f4ga~g%7hjg4&j(7mk?/!bj30ab-wi=6^7-$^R9F|GK5J#E6WT;IO[JN'; // random string 

    $hash = md5($pass); 
    $hash_md5 = md5($salt . $pass); 

    // echo now 
    echo 'Original Password: ' . $pass . '<br><br>';
    echo 'Original Salt: ' . $salt . '<br><br>';
    echo 'MD5: ' . $hash . '<br><br>';
    echo 'MD5 with Salt: ' . $hash_md5 . '<br><br>';
J.K.A.
  • 7,272
  • 25
  • 94
  • 163
1
 $salt="Your text vatiable";
 $data[passsord] = md5($salt . $password);
questions
  • 29
  • 4