python and php bcrypt - php

I was using Laravel to register the users. It uses bcrypt like so:
$2y$10$kb9T4WXdz5aKLSZX1OkpMOx.3ogUn9QX8GRZ93rd99i7VLKmeoXXX
I am currently making another script that will authenticate users from another source using python. I installed py-bcrypt and tried it. The format is as follows:
$2a$10$Vj0b0GZegbpXIIpa/lvi9OjkAFJ5zNzziVRW7yN9ssDKVQDX47XXX
But on python I cannot authenticate the user because of invalid salt.
I noticed that Laravel bcrypt uses $2y while python uses $2a. How do I get around this?
notes:
I used 10 rounds for both crypts.

I just found out that the 2a and 2y are very similar except for the name(prefix).
replacing 2y of the laravel hash, to 2a still keeps the integrity of the hash and should work properly and match the password even if you replace the identity.
In my case (question) the solution was to use str.replace('$2y$', '$2a$') and it all worked well.
Now the py-bcrypt accepts the hash without the error invalid salt.
Good Luck guys.

Now in 2018, we are able to use a hash string from php:
<?php echo password_hash( "302010", PASSWORD_BCRYPT ); ?>
$2y$10$20l2aC6kIyltpgWLmp80n.4itLhmoP58CU80m1
m/ukE8TZYJAASx.
and check it with python:
>>>import bcrypt
>>>bcrypt.checkpw(b'302010',b'$2y$10$20l2aC6kIyltpgWLmp80n.4itLhmoP58CU80m1
m/ukE8TZYJAASx.')
True
or a hash string from python with php
>>>import bcrypt
>>>hashed = bcrypt.hashpw(b'302010', bcrypt.gensalt())
$2b$12$tbv8bBsuQUwq0GTCW0E2GeVUiS65ESb60fRVwbaVLlR1m4iwbbOWO
<?php //validade hash in php
if(password_verify ( "302010", '$2b$12$tbv8bBsuQUwq0GTCW0E2GeVUiS65ESb60fRVwbaVLlR1m4iwbbOWO' )){
echo "valid";
} else {
echo "invalid";
} ?>
https://3v4l.org/ELWtU

Related

I can't compare password from my database and the one inputted

I am using php crypt function to make a password secure, but when I try and compare a password entered to a one in the database it will not work.
here is my code to create the password in the first place:
$crypt_password = crypt($_POST['confirm-password']);
here is me trying to compare to the password in another function:
$input_crypt_password = crypt($_POST['input-pw']);
if ($input_crypt_password == $dbpassword){
// do change password function
}
This is not working.
when i print both passwords the are different.
why are the passwords different even though I am entering the same password and using crypt function on both?
can anyone point me in the right direction?
From the docs
Example #1 crypt() examples
<?php
$hashed_password = crypt('mypassword'); // let the salt be automatically generated
/* You should pass the entire results of crypt() as the salt for comparing a
password, to avoid problems when different hashing algorithms are used. (As
it says above, standard DES-based password hashing uses a 2-character salt,
but MD5-based hashing uses 12.) */
if (hash_equals($hashed_password, crypt($user_input, $hashed_password))) {
echo "Password verified!";
}
?>
The code in the question will effectively generate a new hash every time it's called - the existing password hash needs to be passed as the salt to get a consistent result.
As also mentioned in the docs:
Use of password_hash() is encouraged.
I'd go further and say you definitely should be using password_hash instead of calling crypt for password usage (assuming php >= 5.5); in any case though for whichever whatever tools/methods you're using - please read the docs to know how to use them.
Don't use crypt directly for passwords.
If you have PHP 5.5+, than use the built in password_hash function, otherwise if you have PHP 5.3.7+ use the polyfill for this function.
Try to something like this.
$crypt_password = crypt($_POST['confirm-password'],salt);
$input_crypt_password = crypt($_POST['input-pw'],salt);
if ($input_crypt_password == $dbpassword){
// do change password function
echo "Password match successfully!";
}
Here salt parameter to base the hashing on. If not provided, the behaviour is defined by the algorithm implementation and can lead to unexpected results.
I don't know what to say that will add more detail than what everyone else has already said...
So, in modern day hash/unhashing algorithms it would be unsafe to store passwords using standard hashing functions (e.g. MD5 / SHA256) as it is quick and easy to unhash this type of entry.
password_hash() as referenced in other answers and comments should be you're #1 way to safely store passwords as it uses a one way hashing algorithm.
You should read this page!
And then in response to your original question, use hash_equals() function to compare passwords.
As many guys here said, you should use password_hash php function.
Here you can see a simple example how to use it:
<?php
$password = '123456';
$userInput = '123456';
$storedHash = password_hash($password, PASSWORD_DEFAULT);
if (password_verify($userInput, $storedHash)) {
echo 'OK';
} else {
echo 'ERROR';
}
Also as mentioned before, if you use older version of PHP, you can install polyfill.
Did you trim the input before saving in db and while making the comparison. Since the input is coming from browser this may be a reason why it is not matching. otherwise this https://stackoverflow.com/a/41141338/1748066 seems appropriate.

Convert PHP's password_verify to Ruby on Rails

We're in the process of converting our site from an old PHP framework to Rails, and would really like for users to continue being able to login with their old password. On the old site, we're using password_hash and password_verify to hash and verify the passwords. However, on Rails I can't seem to get it to verify the old password.
Here is what we have in PHP:
Hash:
password_hash($user['salt'] . $password . $user['salt'], PASSWORD_DEFAULT);
Verify:
password_verify($user['salt'] . $password . $user['salt'], $user['password'])
On the new Rails framework we're using Devise and have built a custom migration script to move everything over and identify the correct password hashing method based on a password_version stored in the db, and this is what I'm using inside my User model:
def valid_password?(password)
if password_version == 'legacy'
hash = BCrypt::Password.new(encrypted_password)
hash_str = password_salt+password+password_salt
return hash.is_password? hash_str
end
super(password)
end
Any ideas would be greatly appreciated
The format of a PHP password_hash password looks roughly like this:
$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a
The default Ruby Bcrypt method produces passwords of the form:
$2a$10$GtKs1Kbsig8ULHZzO1h2TetZfhO4Fmlxphp8bVKnUlZCBYYClPohG
For a clean solution here you can always differentiate between the two by the $2y or $2a prefix. There's no need for a format column when it's already baked into the format.
For example:
case (encrypted_password[0,3])
when '$2y'
# Legacy PHP password
BCrypt::Password.new(encrypted_password.sub(/\A\$2y/, '$2a')).is_password?(salt + password + salt)
when '$2a'
# Ruby BCrypt password
BCrypt::Password.new(encrypted_password).is_password?(password)
else
# Unexpected type?
end
What you'll want to do on a successful verification of password is re-write the password to the database using Ruby's method to gradually replace all the old PHP formatted ones.

Codeigniter password matches not working with md5

When I use the following code in a validation form the password matches do not match the two passwords even when the two passwords are same.
$this->form_validation->set_rules('password','Password','required|md5|trim|xss_clean|matches[rpassword]');
$this->form_validation->set_rules('rpassword','Repeat Password','required|md5|trim|xss_clean');
But when I remove the md5 function then the password matches is working properly.
Can someone understand why this happens?
When you do matches[rpassword], it's looking at the current value of password after the md5 but rpassword before the md5.
Switch it to this so that it does the match validation BEFORE converting to md5:
$this->form_validation->set_rules('password','Password','required|matches[rpassword]|md5|trim|xss_clean');
$this->form_validation->set_rules('rpassword','Repeat Password','required|md5|trim|xss_clean');
Also, if this is an application where security truly matters - please know that md5 is very easy to crack and that if someone is able to ever get into your database that they will be able to hack all of these passwords. So basically using md5 is almost the equivalent to not encrypting in the first place.
For password storage, use CRYPT_BLOWFISH or PHP 5.5's password_hash() function. For PHP < 5.5 use the password_hash() compatibility pack.
This is happening because the operation do comparation of "matches[rpassword]" it is before of variable "rpassword" be found, see below:
Your code:
$this->form_validation->set_rules('password','Password','required|md5|trim|xss_clean|matches[rpassword]');
$this->form_validation->set_rules('rpassword','Repeat Password','required|md5|trim|xss_clean');
Updated and working:
$this->form_validation->set_rules('password','Password','required|md5|trim|xss_clean');
$this->form_validation->set_rules('rpassword','Repeat Password','required|md5|trim|xss_clean|matches[password]');

How to verify hash created with php-crypt in node.js

I must migrate my backend from php to node. We used php crypt (with default random salt) to hash the passwords.
For instance, for the password 'd1692fab28b8a56527ae329b3d121c52', I have the following crypted pw in my base (depending if I used either md5 or sha512, as the $i$ specify) :
$1$7JxJYjJK$oFtCGyVvflspPtxB7YrWP.
$6$CVx6KL5l$wzk3YXlqUaz42Kb9r2lmEJhx/FBUXPRoLWN.20/XMBbgQrhp3vSHkEDF3bJEtpM3M96VZ.AMKatLGSKYZZKNH/
And in php I can verify them with crypt :
echo crypt('d1692fab28b8a56527ae329b3d121c52', '$1$7JxJYjJK$oFtCGyVvflspPtxB7YrWP.');
echo "\n";
echo crypt('d1692fab28b8a56527ae329b3d121c52', '$6$CVx6KL5l$wzk3YXlqUaz42Kb9r2lmEJhx/FBUXPRoLWN.20/XMBbgQrhp3vSHkEDF3bJEtpM3M96VZ.AMKatLGSKYZZKNH/');
echo "\n";
Which returns the correct crypted pw.
I did not manage to obtain such results with any node function. I tried stuff like :
require("crypto").createHmac("md5", "7JxJYjJK").update("d1692fab28b8a56527ae329b3d121c52").digest("base64");
And many others, but without any success.
Can someone please help me to do this ? I abolutely need the MD5 version ($1$) ; the sha512 would be somewhat nice (I know it's horrifying, but it's the md5 version that was used on the prod server, and the sha512 that was used on the test server...).
I just converted the original crypt_md5() (as used in PHP) to JavaScript for one of my projects. You can find it here:
https://github.com/BlaM/cryptMD5-for-javascript
(Supports only $1$, but that's at least a part of what you are looking for.)

crypt() breaks when migrating from PHP 5.2 to 5.4

I have a system running on PHP version 5.2.10 Unfortunately the original programmer misunderstood how crypt() was implemented.
$crypt = crypt(trim($cuPassword), CRYPT_BLOWFISH);
// The programmer thought this is how you configure a blowfish cipher
nb CRYPT_BLOWFISH has a value of zero on this machine.
This works in as much as it produces a random looking password hash eg 0$oZ534I2VvSw
Today, I migrated the software to PHP 5.4.9 and discovered that $crypt becomes *0 , ie an error due to the invalid salt.
My problem is that I have a table of login passwords that I can no longer validate. My question: Is there going to be a way I can recreate the original cipher that ran under version 5.2? What hash was implemented when you passed "0" as a salt?
Your description doesn't really add up. In PHP 5.4.9, I tested this:
var_dump(crypt('hello', 0));
Output:
0$ny0efnQXFkE
Now in PHP 5.5, you'll get *0 when calling crypt('hello', 0). But that's okay! Because this is still true in PHP 5.5: this crypt('hello', '0$ny0efnQXFkE') == '0$ny0efnQXFkE'.
All you need to do is change how you generate your hash for new passwords. Validating existing passwords will continue to work.
For good measure, after people successfully log in, check if their hash begins with 0$. If it does, rehash the password (since they entered it, you know what it is) with the updated, proper crypt call.
I tried all valid two digit combinations (CRYPT_STD_DES) and I found that "0q" is equivalent (nearly).
PHP 5.2.10
crypt(trim($cuPassword), CRYPT_BLOWFISH);
Result = 0$txv6CWBxJ9Y
PHP 5.4.9
crypt(trim($cuPassword), '0q');
Result = 0qtxv6CWBxJ9Y
All I need to do is adjust the second character and I can match passwords again.
No, there's no way you can recreate the original cipher. Otherwise even a boy scout would be able to break blowfish.
Your best chance is to generate a random password for your users and hash it once again, then force them to change the password as soon as they login.
"$" is not a valid salt value according to crypt(3) so you need to find a crypt implementation that's equally broken as the one PHP/libc used to have :)
If verifying old passwords is enough, use Matthews answer, else try e.g. openssl which currently still seems to accept "0$" as salt:
$ echo -n "secret" | openssl passwd -crypt -salt '0$' -stdin
0$z.PXBBy6uY.

Categories