3

I'm currently doing a very safe login system, but I'm new to the crypt() function and need some quick assistance.

I used crypt() to encrypt the password string during signup and saved it to the database. However, how will I be able to decrypt the key during login? Or how am I supposed to do otherwise? Or would it be possibly to do some magic with the submitted password string to compare it to the encrypted key in the database?

NullUserException
  • 83,810
  • 28
  • 209
  • 234
Nikkster
  • 327
  • 2
  • 13

5 Answers5

2

crypt() doesn't encrypt passwords, it hashes them. The fundamental difference is, you can't get hashed passwords back (think of hash browns - if you have hash browns, you can't get the potatoes back).

So you apply the same function to the input and compare its result to the value stored in the database:

$stored_pw = get_hashed_password_from_db($_POST['username']);
crypt($_POST['password'], $stored_pw) == $stored_pw

Read the documentation on crypt() to understand the "magic" behind the code above works.

NullUserException
  • 83,810
  • 28
  • 209
  • 234
  • I'd like to thank you all for your kindness and help, highly appreciated. I'm not sure though why I could not get it working with crypt(), because I did as most of you said. But now I created an own function which hashes the password string using sha1, and then combines it with a salt, and then it actually started working. Also, I'd like to apologize for saying "encrypt". :) Have a nice evening! – Nikkster Nov 19 '11 at 17:27
  • @user973763 `crypt` might be a bit counter-intuitive, but if you read the docs you should be able to understand it. **Demo:** http://ideone.com/mLRb3 – NullUserException Nov 19 '11 at 17:30
1

crypt() the provided password at login. Compare the output to the previous crypt()'s output. If they match, the passwords match.

This is the basic theory of operation of a one-way hash function.

dossy
  • 1,617
  • 16
  • 26
1

Do not encrypt the password. Instead, store it with a hash.

Popular SO thread: How should I ethically approach user password storage for later plaintext retrieval?

Community
  • 1
  • 1
Shackrock
  • 4,601
  • 10
  • 48
  • 74
0

Also this is how you should be doing it. Please note that this code is how I'd do it, and you may want to change a few of the things. And you must define your own unique salt, whether in the config file or elsehwere. It must either a) be in the global scope as I've posted, or you can change it to make it defined in the function. Also you're not encrypting, you're actually hashing. Encryption is both ways, hashing is encryption in one way. Meaning you cannot decrypt a hash. You can only bruteforce guess the original plain text.

/*
*   Copyright (c) 2012, Macarthur Inbody
*   The following code was posted on http://stackoverflow.com/questions/8195689/encryption-using-crypt
*   The license is simply CC-by https://creativecommons.org/licenses/by/3.0/
*
*
*
*/


/*
 *
 * This is used to hash their password.
 *
 * @param   $password       string      the users supplied password
 * @param   $username       string      the users supplied username
 * @param   $rand_salt      int         the secondary salt -2^31-1 to 2^31-1 Must be defined previously.
 * @return  string the hashed password
 */
function hash_pass($username,$password,$rand_salt){

    global $unique_salt;
    $main_salt=base64_encode(hash('sha512',$username.$password.$config_salt);
    $main_salt=str_replace('+', '.', $salt);
    $main_salt=str_replace('=','/',$salt);
    $main_salt='$2$06'.$main_salt; //change this here to the cost factor that you want
    $hashed=crypt($unique_salt.$username.$password.$rand_salt,$main_salt);
    return $hashed;
}

function gen_rand_salt(){
    return rand();
}

function rand_str($length,$additional_entropy){
    $max_length=ceil($length/28);
    if(!is_defined($additional_entropy)){
        $additional_entropy='';
    }
    $str='';
    for($i=0;$i<=$max_length;++$i){
        $str.=base64_encode(sha1($i.''.microtime().$additional_entropy,true));
    }
    $str=substr($str,0,$length);
    return $str;
}

/*
*
* Generate A temp password/token
*
* This function generates a temporary password and also gives you
* the hashed password too. It is an array, arr[0]=password, arr[1]=
* hashed password. If it fails it'll return -1;
*
* @param    $username   the username
* @param    $rand_salt  the random salt value, must be given.
*
* @return   array       if it is successful array, if it fails it's a number of -1
*/ 
function generate_temp_password($username,$rand_salt){
    global $unique_salt;
    if(!is_defined($rand_salt)){
    return -1;
    }
    $pass_len=12; // change this to what you want for password recovery
    $pass_arr=Array();
    $password=rand_str($pass_len,$unique_salt.rand().$rand_salt);
    $password=substr(base64_encode(sha1($rand_str.$rand_salt,true)),0,$pass_len);
    $hashed_password=hash_pass($username,$password,$rand_salt);
    $pass_arr[0]=$password;
    $pass_arr[1]=$hashed_password;
    return $pass_arr;
}

As stated in teh code, the license is CC-By as I figure it's good enough for most things. Also please keep the block the same as far as the link to this page as that's what I do with all of my own source code. Also I realize the "random" string isn't really that random, but it's random enough to be useable by you for the purpose that it is going to be.

Edit 2:Also be sure to escape the user's username. I'm not escaping the password, since I'm hashing it, thus escaping it isn't necessary since it's already mitigated and would just waste cycles. But only if you're doing something like this. Make sure to escape the username with mysql_real_escape_string. If you're using php5+ you should look into mysqli(if you're using mysql). If you're using another system, then you'll have to look it up yourself as I only know mysql. I'm going to be away for a couple of days, so I really hope this works for you. I will check it from time to time, but I may forget... so yeah. I hope this helps you, as it's safe, secure, and should work fine for you.

Edit 3: Changed the random string function to make it a bit stronger since I forgot that this is going to be use to generate temporary passwords. That should make it random enough to be used for this purpose since otherwise the generated password might be able to be known by someone knowing the exact time(with the current microtime) though highly unlikely, this still makes it a bit stronger and should make it safe from those kinds of attacks. It should not be completely production ready, and should be secure for your system. Just make sure to set the $unique_salt variable somwhere in the global scope, or set it in every time that it's used in each of those functions.

133794m3r
  • 5,028
  • 3
  • 24
  • 37
0

See

http://php.net/manual/en/function.password-hash.php

and

http://php.net/manual/en/function.password-verify.php

Also never use rand() if you need safe random values. It's the worst source for random values in PHP.

In PHP 7 you should use

http://php.net/manual/en/function.random-bytes.php

instead. For earlier versions see

http://php.net/manual/en/function.openssl-random-pseudo-bytes.php

lastzero
  • 131
  • 1
  • 10