Bcrypt Encoding Error - python-3.x

I'm creating a flask-app and using wtforms. I have password stored in my database that is created from a form using the following:
salt = bcrypt.gensalt()
hashed_password = bcrypt.hashpw(form.password.data.encode('utf-8'), salt)
Now I want to check the password using:
if bcrypt.checkpw(form.password.data.encode('utf8'), password_from_db):
When I do this the following error arises:
TypeError: Unicode-objects must be encoded before checking
Not sure exactly what is causing this or how to resolve. It is something to do with the form and the data type though as I can follow standard python examples.
Many thanks
EDIT
I've checked this question here but it didn't resolve my query. My query is using data from forms. I'm using the same method as in the answer but am still receiving the error.

salt = bcrypt.gensalt()
hashed_password = bcrypt.hashpw(form.password.data.encode('utf-8'), salt).decode('utf-8')
# While checking:
password_hashed=bcrypt.hashpw(form.password.data.encode('utf8'), password_from_db.encode('utf-8')).decode('utf-8')
if password_hashed == password_from_db:
print('User succesfully logged in')

Related

Cant use original password, after hash (pgcrypto)

I have succeded in hashing my password for my admin user, the problem is now that i can no longer use the original password to log in (no errors, exept the correct response for invalid passwords). I am able to to select the user table and just copy in the hashed password from PGadmin (using PostgreSQL). Im not really sure where to go from here.
1. I think i have to get my login form to recognize the hashed password, and somehow match it up with the original.
2. figure out how to add salt and pepper to the hash
I am not looking for the exact solution, but maybe some hints to get further :)
Code
function createAdmin(){
var usertypeid = null;
const type = "adm";
pool.query(`INSERT INTO usertype(type) VALUES ($1) RETURNING userTypeId;`, [type], function (error, results) {
if (error){
throw error;
} else{
usertypeid = results.rows[0].usertypeid;
console.log(usertypeid);
insertAdmin();
}
});
function insertAdmin(){
pool.query(`
INSERT INTO users(
usertypeid, userName, email, password)
VALUES($1, 'admin', 'admin#admin.com', CRYPT('admin', GEN_SALT('md5')));`, [usertypeid]);
}
}
As mentioned in the comments, don't use MD5 anymore as it's deprecated a long time ago.
The other thing is that hashing is different from encrypting. You can't decrypt a hash like you do with a cipher.
What should happen is that you run the plaintext through the hashing algorithm and then see if it matches the original hash computed at the beginning.
For Node.js there are good libraries out there like bcrypt which can be used to simplify the process and perhaps make it more secure.
If you insist to perform your own validation procedure, then it should be like the following:
Get the user's password from the login form
Run it through the hashing algo of your choice (no MD5 please)
Query the database for the hashed password
Compare if the hashed password from the login form is the same as the one in the DB
As the docs say, you want something like this (renaming table and columns to match your example):
SELECT (password = crypt('entered password', password)) AS pswmatch FROM users where username='admin';
The value stored in users.password from your insertion is a combination of the algorithm, the salt, and result of hashing the actual password with that algorithm and salt. Now you pass users.password into crypt again, so that it can extract from it the algorithm and the salt. It then uses that algorithm and salt to recompute the hash of the alleged password. If the re-computed value matches the stored value, then the alleged password is correct.

Node Js SHA 1 multiple times

Hello I have this Java code which uses the following encryption method to encrypt password.
MessageDigest digester = MessageDigest.getInstance("SHA-1");
value = digester.digest(password.getBytes());
digester.update(email.getBytes());
value = digester.digest(value);
This returns base64 encoded string like qXO4aUUUyiue6arrcLAio+TBNwQ= This is sample not exact.
I am converting this to NodeJs not sure how to handle this. I have tried like
var crypto = require('crypto');
var shasum = crypto.createHash('sha1');
var value = shasum.update('hello');
shasum.update('abc#xyz.com');
value = shasum.digest(value).toString('base64');
console.log(value);
The string base64 I get in node js is not similar to get from java. Not sure why?. I need to have same encoding as java as its old system migrated to new one cant lose old details.
Can someone help me how I can achieve same base64 string.
In Java you're calculating the first value as the hash of the password alone, then overwrite it with hash of the email alone. (digest gives the result and resets the hash, in Java).
In Javascript, on the other hand, you're having an undefined value, then overwrite it with the hash of (password concatenated with email).
PS that hash is conceptually wrong: you should always put a separator between two fields, to avoid ambiguity and, thus, possible attacks.

Yii2 - how to properly use generatePasswordHash()?

I'm trying to generate a random password for a user in a Yii2 application.
I have the following code:
$rand_password = Yii::$app->security->generateRandomString(8);
$user->password = Yii::$app->security->generatePasswordHash($rand_password);
After that I save the $user model and the hashed string is also saved in the database. However, I cannot log in with the $rand_password string after that as I'm getting Invalid Password error message.
The generatePasswordHash description says that the hash is generated from the provided password and a random salt string. Indeed, I called the function with the same password string several times in a row and I got different result every time. So my question is, if that salt string is random and different every time, how can I use this function at all to verify passwords? When I try to login I call the same function with the password string provided by the user but this time the salt will be different so I'm unable to produce the same hash as before? What am I missing here?
Well, after hours of debugging and looking for resources and explanation, it turns out the the user module I'm using: https://github.com/amnah/yii2-user is actually automatically hashing the passwords before saving them in the database. In other words, as soon as you call:
$user->password = SOMETHING;
that SOMETHING is automatically going through the generatePasswordHash() function upon save. My problem was that I was dropping it in there in my code as well so basically the password got hashed twice.

Validating a Devise User password WITHOUT changing it

i am using Devise and devise_security_extension.
https://github.com/plataformatec/devise
https://github.com/phatworx/devise_security_extension
I tried to figure out how i could validate a provided password WITHOUT updating a User record.
Validation (password was not used before, password is complex enough ....)
For example:
john = User.find(1)
john.password = "Testing"
john.password_confirmation = "Testing"
result = john.save
Result would return true or false. With result.errors i would get the related error messages (Thats exactly what i want but without really change this user password).
My Problem is that this would really change the password of this user (object). That would cause problems with old_passwords.
Is there any way to do a dry run ? (result = john.save_dry_run)
FYI:
I already tried to change the User password and change it back after i got the result. But this is really ugly and also make much trouble with devise old_passwords table.
I hope my question is clear enough. If you need any further information please let me know !
You should call valid? rather than save in your example. This will only run the model validations without actually saving any data to the database:
john = User.find(1)
john.password = "Testing"
john.password_confirmation = "Testing"
result = john.valid?
You can find more information in the Rails documentation.

Returning a string from LINQ

For a school project we have to create an evaluation website that requires a login.
For the database connection I chose LINQ, because it's new and is supposed to be easier/better in use.
I managed to create a login check with the following:
public static Boolean Controle(int id, string wachtwoord)
{
DataClassesDataContext context = new DataClassesDataContext();
var loginGebruiker =
from p in dc.Gebruikers
where p.GebruikerID == id
where p.GebruikerWachtwoord == wachtwoord
select p;
return true;
}
Now I'm trying to create a "forgot password" option, where you enter your id and the password gets returned (later it would be emailed to you, don't know how I would do this either, suggestions?)
I tried with the following code:
public static string Forgot(int id)
{
var context = new DataClassesDataContext();
var wachtwoordLogin = (
from p in dc.Gebruikers
where p.GebruikerID == id
select p.GebruikerWachtwoord);
return wachtwoordLogin.ToString();
}
Code behind the button on the page:
lbl1.Text = Class1.Forgot(Convert.ToInt32(txt1.Text));
Now when I enter the an id of the first user (1), lbl1 becomes this:
SELECT [t0].[GebruikerWachtwoord] FROM
[dbo].[Gebruiker] AS [t0] WHERE
[t0].[GebruikerID] = #p0
I don't know how to solve this and I have been looking everywhere, I hope somebody can help me.
Thanks,
Thomas
LINQ uses delayed execution, so your 'wachtwoordLogin' is really just "how to get your data." Its not until you apply an operator that LINQ will actually attempt to retrieve your data.
Your first statement:
var loginGebruiker = (
from p in dc.Gebruikers
where p.GebruikerID == id
where p.GebruikerWachtwoord == wachtwoord
select p).FirstOrDefault()
if (loginGeruiker != null) {
//Valid login
} else {
// invalid
}
FirstOrDefault means, take the first item in the list, or return none.
In you other case you need the same thing:
user = wachtwoordLogin.FirstOrDefault();
Further reading: MSDN 101 LINQ Samples
For your question about emailing a forgotten password, have you ever thought about implementing the golden questions algorithm instead? Its simplified, and does the same thing.
Basically, at the time of registering just get them to answer some questions, and if they can verify them, allow them to reset the password.
you enter your id and the password gets returned
What, then, is the point of having a password if anybody who knows a username can see it? I know this isn't what you're asking, but for someone getting started in programming I feel a duty to point this out. What you're creating here is essentially a completely broken login model. Nobody should ever use a system like this.
You should never ever display a password. Not on the screen, not in an email, never.
Passwords, if they even need to be stored at all (CodingHorror has had a couple of good posts on this lately, advocating things like OpenID), should be stored in hashed form and essentially unable to be retrieved. When a user logs in, similarly hash the password they provide (immediately upon reaching the application code, before transporting it anywhere else in the system) and compare that to the stored hashed version.
If the user asks for his password, you don't have it. You can't give it to him. This is for his protection. Instead of providing the user with his password, if it's forgotten then you provide the user with a means to reset his password (sending an email to the address on file with a temporarily available URL, a set of "security questions" to verify his identity, etc.) so that he can enter a new one to overwrite the old one. But you shouldn't be able to "show" the user his password because even you as the administrator of the system shouldn't be able to see it in any usable form.
wachwoordLogin will be an IQueryable so you can get this by using FirstOrDefault() which will return null if not found:
(from p in dc.Gebruikers
where p.GebruikerID == id
select p.GebruikerWachtwoord).FirstOrDefault();

Resources