I'm migrating a system from OpenCart to Spree in ruby, and as part of that I would like to seamlessly migrate the users so they can keep login in without changing their passwords.
Looking at the OpenCart code I've found the login function for the website. I'm not great at PHP, so I'm trying to understand how to reproduce the following in ruby
SHA1(CONCAT(salt, SHA1(CONCAT(salt, SHA1('" . $this->db->escape($password) . "')))))
I've tried the following, with no success:
Digest::SHA1.hexdigest("#{salt}#{Digest::SHA1.hexdigest("#{salt}#{Digest::SHA1.hexdigest(" . #{password . ")}")}")
My current test case is:
Password: 7fe391813e
Salt: e4e91e33a
OpenCart hash (what I'm trying to get): 2e62a3b86da5ce878895bcc5745725493bde7ef0
Has anyone done the same migration before? Or can someone explain what the PHP code is actually doing?
Thanks!
The OpenCart code is a MySQL statement, PHP is used only to construct it. You were close with your Ruby alternative, the problem was in password inclusion, dots are used only in PHP. Here is the correct one:
Digest::SHA1.hexdigest("#{salt}#{Digest::SHA1.hexdigest("#{salt}#{Digest::SHA1.hexdigest(password)}")}")
irb(main):001:0> password = "7fe391813e"
=> "7fe391813e"
irb(main):002:0> salt = "e4e91e33a"
=> "e4e91e33a"
irb(main):005:0> Digest::SHA1.hexdigest("#{salt}#{Digest::SHA1.hexdigest("#{salt}#{Digest::SHA1.hexdigest(password)}")}")
=> "2e62a3b86da5ce878895bcc5745725493bde7ef0"
Related
My old PHP app has a default admin user and md5 encrypted password created by the SQL that creates the database: insert into users values ( 1, 'admin', MD5('changeMe'), 2 );
Is there a simple way to include a default user and encrypted password using PHP's passowrd_hash function on creating the tables? I ask because I understand that password_hash is a native PHP function and I assume it won't be understood in SQL.
The solution to my problem came in three parts. My OP sought a simple way to create a hashed password for the admin user for insertion in the MySQL database on the installation of the application, using the native PHP password_hash() function.
(1) Based on a suggestion by #Nick and #Tadman, I decided to incorporate setting the hash in an installer script that would set not only the hash but other defined site/application variables.
Rather than inserting user values when the database table is created, it was deferred until immediately after, with the admin user entering their credentials in the form that inserts the hash and writes other definitions to a file:
$userpass = $_POST['userpass'];
echo password_hash($userpass, PASSWORD_BCRYPT);
(2) The second part of my problem was replacing all instances of md5()`` withpassword_hash()` and I achieved that by using a neat PHP script I found online to recursively search and replace the occurrences on the server.
Having replaced the md5() occurrences, I needed to change the hash comparison method and again by searching the relevant files I was able to replace instances of:
if ($p != $theUser->pwd ) {
return( false ); }
with:
if(password_verify($p, $theUser->pwd)) {
// Success!
}
else {
// Invalid credentials
echo "Uh oh!";
}
(3) The third step in resolving the problem was discovering that adding $1$ to the opening of the md5 hash could make it readable by password_hash(); so I just needed to make a couple of adjustments in the installed database to the admin user's old password.
Thanks to those who helped shine the light so I could find my way. I'm off now to invent the wheel and sliced bread.
you can do something like this in php:
$hash = password_hash('changeMe');
//echo $hash;
then use this hash in the Database.
My client forgot password to login to the backend of the website that was developed by other developer who refused to help. Therefore, I went to SQL database to see if I could retrieve the password directly from there but it seems that password is encrypted. See below
3a0606b25e75eb6c1fed61886844832e
it would be easier if I knew how the password was encrypted so that I could just encrypt new password and add to SQL but when I looked at the code (in password changing PHP gile) there is something called salt_pass that encrypts the password of this website. See below code :
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$db = new database();
$option_uw = array(
"table" => "users",
"fields" => "password",
"condition" => "id='{$_POST['id']}'"
);
$query_uw = $db->select($option_uw);
$rs_uw = $db->get($query_uw);
if ($rs_uw['password'] == trim(salt_pass($_POST['oldpassword']))) {
$value_pw = array(
"password" => trim(salt_pass($_POST['pass']))
);
$query_pw = $db->update("users", $value_pw, "id='{$_POST['id']}'");
if ($query_pw == TRUE) {
header("location:" . $baseUrl . "/back/user");
}
}else{
$_SESSION[_ss . 'msg_result'] = TRUE;
header("location:" . $baseUrl . "/back/user/changepassword");
}
mysql_close();
}
Here is the salt_pass function
function salt_pass($pass) {
return md5("supapongherb.com" . $pass);
}
Does anybody know how I can regenerate or encrypt the new password according to this code?
PS. the website is developed with MVC programming and I am really capable of it. Please let me know if you would like to see more file.
Thank you in advance!
Let's clear a few things up
but it seems that password is encrypted
First, your password is hashed, not encrypted. There is a difference. Namely that hashes are meant to be one-way. There's no way to look at a hash and just regenerate the password from that.
Second, they're using MD5. They're not actually salting anything, they're appending the same string to all passwords and THEN hashing it. MD5 is a terrible way to hash because it's stupid easy to break. This is the equivalent of securing your front door with a rubber band. It's not secure because you can make millions of guesses a minute. Yes it is that bad.
Third, with the function and the "salt" known, you can easy make a new password this way (via SQL because I'm not guessing what sort of screwy ORM they're using there)
UPDATE users
SET password = MD5(CONCAT('supapongherb.com', 'new_password_here'))
WHERE id = their_user_id_here
Fourth, switch to password_hash. Like now. Get rid of the rubber band and upgrade to a deadbolt, with rabid pitbulls behind it and a shotgun in your lap.
we are implementing a web service for a Drupal 7 site (the web service code is not part of drupal installation folder).
one of the web services needs to sign up the user on the site.
the main hurdle was getting a hashed password that Drupal will also recognize.
for that , am following a suggestion made on stack overflow to Implement a REST service inside drupal and call that from the outside service code . (that part also seems possible and achieveable).
have implemented a password hashing service with following code:
function GetHashedPassword($string)
{
require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'includes/password.inc');
$hashedpw = user_hash_password($string);
$data = array(
'password' => $hashedpw
);
header("Access-Control-Allow-Origin: *");
drupal_json_output($data);
drupal_exit();
}
the main issue now is that whenever this service is called even with same string , it returns a new hashed value each time..
kindly assist if what we need is actually even possible and if so, then what could be fixed in the above code
any help appreciated
The Drupal user_hash_password function generates a new salt each time it calculates the hash. This will cause a new hash to be generated since the salt is likely to be different to the last one.
This question already has an answer here:
bcrypt and randomly generated salts
(1 answer)
Closed 8 years ago.
* A REAL WORKING ANSWER is at the bottom of this page! *
This is a question about using crypt () blowfish hash during login for customer verification. I am restricted to PHP 5.3 by my web host and I know it would be better to use PHP 5.5 with password hash () and password verify() but PHP 5.3 doesn’t seem to recognize them. The problem is not hashing the password and putting it in the database the available codes on line work for that. The problem is all the codes I found (about ten so far) don’t take into consideration that the randomized salt that is highly recommended for the registration page can’t be used on login passwords because it will be different every time with no match. Is what I am trying to do not possible on PHP 5.3 or is there a way to re-hash the users password using the salt it was randomized with so it can be checked against the one stored in the database?
Codes like this work well for randomizing the salt and hashing the password for the database entry.
function better_crypt($input, $rounds = 9)
{
$salt = "";
$salt_chars = array_merge(range('A','Z'), range('a','z'), range(0,9));
for($i=0; $i < 22; $i++) {
$salt .= $salt_chars[array_rand($salt_chars)];
}
return crypt($input, sprintf('$2a$%02d$', $rounds) . $salt);
}
$password_hash = better_crypt($input);
But login codes like this don’t work and the functions from the registration page must be redefined on the login page some how. They don’t carry over like session variables. I know I must be missing something… Does anyone have a code that will work for this funtion?
$password_hash = better_crypt($db_password_hash);
if (crypt($user_password, $password_hash) == $password_hash) {
echo '<br>';
echo 'true';
}else{
echo '<br>';
echo 'false';
}
Can’t add comment at bottom of page… I don’t have permission?
The “better crypt” function is for the registration page, it could be called something else. I don’t think it is used for the login page or the PHP include page, but this is what I am asking. Is there a login function or code that can use the original salt and how do I get it out of the hashed password in the database to check it and verify the user?
About the answer (bcrypt and randomly generated salts)
How do I extract the original randomized salt from the hashed password stored in the database or do I try to separate it first during registration and save it separately to use during login? I read this not the way it is suppose to work.
Hi martinstoeckli … The link to “compatibility pack “ goes to the PHP manual on “password_hash”, I don’t see any compatibility pack. The algorithm is set by blowfish and it stays the same for every hashed password. Using crypt by itself is weaker then blowfish, but even that dose not solve the login problem I am asking about. I tried that frist.
If anyone has a working login code to use with blowfish ($2a$) algorithm and using any cost value, please post it. It needs to extract the salt from the saved hashed database password to hash the user enter password during login for comparison. Somehow... Using a fixed salt is not recommended so the randomized salt during registration must be extracted somehow from the saved hash password.
Hi deceze,
I did check the duplicate but it had no login code to try. I will try to make a new code to test using this one line below… where $passwordToCheck is the login password and $2y$10$abcdefg... is the stored hashed password in the database. I will put it in an “if statement and echo if it is true or else false”. Get back to you with the results…Thanks
crypt($passwordToCheck, '$2y$10$abcdefg...')
deceze,
I tried this code below with the “,” and “==” both return true or “worked!” with any password input into the login. Please post the code you use for your login page so I can test or modify it to use on mine .
if
(crypt($user_password == $db_password_hash)){
echo '<br>';
echo ' Worked! ';
echo '<br>';
}
else
{
echo '<br>';
echo ' Did not work ): ';
echo '<br>';
}
Also I am using “$2y$11$” now for the algorithm and cost parameter on my registration page with database input like this “$2y$11$9MUd40QqfmmtPaes91OttOlvAhkAtMvS4.mtg9LT.tazythwhRMwu”
Would someone please remove the post that this question has been answered. This will just frustrate others trying to fine an answer to this problem as I have been for days now. Again if anyone does have a working code to answer this question please post it so this problem can get resolved for others STILL NEEDING A REAL WORKING ANSWER!
//////////////////////////////////////////////////////////////////////////////
EUREKA! “I found it” or at least learned how to write the code.
This is A REAL WORKING ANSWER! , The Blowfish login code I wish I had days ago, when I sill had hair!
The "$2y$" is better for PHP 5.3.7 or higher but I must use the "$2a$" algorithm for PHP 5.3 as explained below from http://php.net/manual/en/function.crypt.php.
Versions of PHP before 5.3.7 only support "$2a$" as the salt prefix: PHP 5.3.7 introduced the new prefixes to fix a security weakness in the Blowfish implementation. Please refer to » this document for full details of the security fix, but to summarise, developers targeting only PHP 5.3.7 and later should use "$2y$" in preference to "$2a$".
<?php
// Blowfish login code to verify user login password with the hashed password in database
// Make variables from login form on another page and use “include()” to get this PHP code
$user_name_from_login = $_POST[ 'login_user_name' ];
$user_password_from_login = $_POST[ 'login_password' ];
//Check users name for match in your database table of user names
// You must use a line like this “include(‘your_conection_name.php');”
//at the top of your page to get the database connection code or add it directly to this page for this to work
$sql = "SELECT * FROM customers WHERE user_name=:login_user_name";
$query = $db->prepare( $sql );
$query->execute( array( ':login_user_name'=>$user_name_from_login ) );
$results = $query->fetchAll( PDO::FETCH_ASSOC );
//Get hashed password in database associated with user name and make it into a php variable
foreach( $results as $row ){
$database_password_hash = $row[ 'password' ];
}
//Using the Blowfish “$2a$” algorithm with a cost of “11$” and random salt form registration page
// this one line converts login password to the original saved hashed so it can be compared with the one saved in database
$user_password_rehashed = crypt($user_password_from_login, $database_password_hash);
//Now a simple comparison can be made and verified with an “if else” using the variables above
if
($user_password_rehashed == $database_password_hash) {
echo '<br>';
echo ' User’s login password “IS A MATCH” with the one in database (:';
echo '<br>';
}
else
{
echo '<br>';
echo ' User’s login password “DOES NOT MATCH” with the one in database ):';
echo '<br>';
}
//Check your output to better understand process
echo '<br>';
echo ' $user_password_from_login = ' . $user_password_from_login;
echo '<br>';
echo ' $user_password_rehashed --- = ' . $user_password_rehashed;
echo '<br>';
echo ' $database_password_hash --- = ' . $database_password_hash;
echo '<br>';
?>
I hope this will save time and money for other web designers…
I know it would be better to use PHP 5.5 with password hash () and password verify() but PHP 5.3 doesn’t seem to recognize them…
Use the password_compat library. It provides those functions for PHP 5.3.7 and later.
The problem with your better_crypt() function is that it generates a new random salt every time it is called, so the results can't be verified. To be compatible with crypt(), it would need to take a salt from another password hash as input.
But don't do that. Use password_compat.
I am currently working on a PHP Project where i need to integrate user information from a CakePHP driven website.
CakePHP using the following method for password encryption:
Security::hash($user['User']['password'],null,true);
I know, CakePHP By default use the SHA1 encryption method.
i have tried to encrypt a password using SHA1 by using PHP but i come to know that is not matching with cakePHP encryption.
<?php
$str = 'apple';
if (sha1($str) === 'd0be2dc421be4fcd0172e5afceea3970e2f3d940') {
echo "login info found?";
}
else{
echo "No info found";
}
?>
if any one has a solution. please help me.
Because your 3rd argument is true, CakePHP will salt the hash with the value stored in your configuration:
$string = Configure::read('Security.salt') . $string;
See http://api.cakephp.org/view_source/security#line-91