I am trying to understand how should I use argon2_cffi to store hashed passwords in my database.
Specifically, I am using this code to write the hashed password into my PostgreSQL table.
from argon2 import PasswordHasher
ph = PasswordHasher()
new_user = User(
name=POST.get('name', 'default_value'),
fullname=POST.get('fullname', 'default_value'),
nickname=POST.get('nickname', 'default_value'),
hashed_password=ph.hash(POST.get('password', 'default_value')))
session.add(new_user)
However, this produces a different password everytime the user inserts a password in my form, although the inserted text is the same.
Of course, I know this is he correct behaviour, but what should I do in order to verify that a given registered user has inserted the right password if I cannot produce the same hash?
Sorry, found out myself in the docs...
import argon2
ph = argon2.PasswordHasher()
def login(db, user, password):
hash = db.get_password_hash_for_user(user)
# Verify password, raises exception if wrong.
ph.verify(hash, password)
# Now that we have the cleartext password,
# check the hash's parameters and if outdated,
# rehash the user's password in the database.
if ph.check_needs_rehash(hash):
db.set_password_hash_for_user(user, ph.hash(password))
Related
I have created users in mysql with the same password then this code snippet changes the plain text passwords to a hash using bcrypt. Why is the hash different for the same string?
import mysql.connector
import bcrypt
mydb = mysql.connector.connect(
host="localhost",
user="root",
password="........",
database="briandb",
)
mycursor = mydb.cursor()
for user in ["bob", "alice"]:
password = "ttt"
print(password)
hashed = bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt())
print(hashed)
mycursor.execute(
f'UPDATE users set password = "{hashed}" where user = "{user}"'
)
mydb.commit()
You've discovered a key feature of robust password hashing: Each time you hash a password you get a different result. Why?
A different random salt (from bcrypt.gensalt() here) is used each time.
Why is this important?
If a cybercreep breaks into your system and steals your users table, they'll have your salted hashed passwords. When the hashing is done correctly, it is very difficult to recover the unsalted passwords. If they, next, break into a bank's system and steal their hashed passwords, we don't want them to be able to conclude that certain users have the same password on both systems. If they could guess that, they'd know which users to target for deeper cybercrimes.
user_password = 'admin'
salt = bcrypt.gensalt(rounds=16)
password = bcrypt.hashpw(user_password.encode('utf-8'), salt)
print(password)
sql_statementInsert = "INSERT into users
(crypted_password,login,uuid,external_login,external_identity_provider,external_id,is_root,onboarded,hash_method,active,name)
values ('{}','cosmin','1ea2ad82-b07c-11ea-b3de-0242ac130004','cosmin','sonarqube','user',false,true,'BCRYPT',true,'cosmin') on conflict (login) do nothing;".format(password.decode("utf-8"))
The generated hash for this example is: $2b$08$1KDDzD5DoVOEopOWUb0Rbu8A0FtYtI02BopFoY4Qxp5URuf3KA0s2.
I have this code which is generating some hash based on the user_password, but when trying to log in with "admin" value is not working. But when I am inserting directly the following hash in the crypted_password is working: $2a$12$uCkkXmhW5ThVK8mpBvnXOOJRLd64LJeHTeCkSuB3lfaR2N0AYBaSi
Solved this by using the good library, I needed py-bcrypt, the wrong one was bcrypt only. Also if you use the new lib you don't need to decode the password when you insert it.
I want to store userid in a variable after the users logged in and I am not sure how to do that. I used getpass.getuser(), but it gives me the username from my computer system. Does session work in tkinter? Can somebody give me an idea how should I approach this?
The user id is increased automatically for new user
class data:
def checks(name, password):
conn = sqlite3.connect('login.db')
cur = conn.cursor()
if cur.execute('SELECT * FROM user WHERE name = ? AND password = ?', (name, password)):
if cur.fetchone():
window.destroy()
login_backend.back()
else:
messagebox.showinfo('error', 'Username and password is wrong')
def login_student(self):
if len(self.namee.get()) == 0 or len(self.password1e.get()) == 0:
messagebox.showinfo("ERROR", "Mandatory Field is empty")
else:
data.checks(self.namee_text.get(), self.password1e_text.get())
Do you want to get a password and user name on the command line? If so, the secure way to do this is with getpass.getpass(). This will prompt the user. getpass.getuser(), as you discovered, is for the system user.
https://docs.python.org/2/library/getpass.html
You don't want to print the password on the command line because of the security risk. Generally, you want to consume the sensitive credentials only as long as needed to access the resource.
I like to create a secure login with Python but need to check the user table from a database, so that multiple users can log in with their own password.
Mainly like this, works like a charm but not secured of course.
while True:
USER = input("User: ")
PASSWORD = getpass.getpass()
db = sqlite3.connect("test.db")
c = db.cursor()
login = c.execute("SELECT * from LOGIN WHERE USER = ? AND PASSWORD = ?", (USER, PASSWORD))
if (len(login.fetchall()) > 0):
print()
print("Welcome")
break
else:
print("Login Failed")
continue
So then I tried hashing the password, work also of course, but then I can't store it on the database to check, so there is no check at all.
from passlib.hash import sha256_crypt
password = input("Password: ")
hash1 = sha256_crypt.encrypt( password )
hash2 = sha256_crypt.encrypt( password )
print(hash1)
print(hash2)
import getpass
from passlib.hash import sha256_crypt
passwd = getpass.getpass("Please enter the secret password: ")
if sha256_crypt.verify( passwd, hash ):
print("Everything worked!")
else:
print("Try again :(")
I tried like this so that the password hash would be taken from the database but with no success:
USER = input("User: ")
db = sqlite3.connect("test.db")
c = db.cursor()
hash = "SELECT HASH FROM LOGIN WHERE USER = %s"%USER
print(hash)
passwd = getpass.getpass("Password: ")
if sha256_crypt.verify( passwd, hash ):
print("Everything worked!")
else:
print("Try again :(")
So my question is, what is the best way to create a secure login for my program? And I do need different logins for different users as stated in the user table. I did it on MySQL before but for testing purpose I'm now trying on sql3. So that doesn't matter. As long as I know how to approach this.
Really you should avoid doing this yourself at all. There are plenty of libraries that correctly implement this kind of authentication.
Nevertheless, the pattern to follow is like this:
Don't store the plain password in the database at all. When the user account is created, hash the password immediately and store that.
When the user logs in, hash the value they enter for the password, then compare that against the value stored in the database already.
(Note that for decent security, you not only need to use a modern hash algorithm but should also use a salt).
I'm having a problem when trying to verify credentials ( I will post the code below ). I was wondering if it's happening because I stored username and password as a string within the database, should I have stored it as an integer?
The problem: I think it's easier to simply give an example of what the problem is, maybe it's easier to understand.
Information that is correct ( username = something and password = testing )
Example 1: You input "something" as username and "password" as password - that's fine it works, HOWEVER the next example is where things go wrong.
Example 2: You input the username "somethingfpsadadoia" and the password "testing" - the program will say it's correct as long as the password is correct. So as long as you have part of the username under username entry then the password works, but anything after that is not taken in consideration to say it's actually wrong.
Much appreciated if anyone can help !
"""
def Is_Valid():
UsernameValidity=UserName_Entry.get()
PasswordValidity=Password_Entry.get()
cursor.execute('''SELECT password FROM users WHERE username = ?''', (UsernameValidity,))
cursor.execute('''SELECT username FROM users WHERE password = ?''', (PasswordValidity,))
LogInAttempt = cursor.fetchone()
print (Is_Valid) # Testing to see if it works on shell
if LogInAttempt:
print (" One of the accounts have successfully logged in ")
IsValidText.config(text=" You have logged in! ", fg="black", highlightthickness=1)
myGUI.after(1000, CoreContent) # Ignore this one for now.
else:
print (" One of the accounts inputted the wrong credentials! ")
IsValidText.config(text=" Invalid username or Password! ", fg="black", highlightthickness=1)
"""
You are executing two entirely independent queries. The second call to execute throws away any results from the first one; what you fetch from cursor is the result of the second query.
You have to tell the database to check both values when looking at each row:
cursor.execute('SELECT 1 FROM users WHERE username = ? AND password = ?',
[UsernameValidity, PasswordValidity])
LogInAttempt = cursor.fetchone()