Hashing Passwords
Password Hashing - Python
What is Password Hashing
Passwords are something that pretty much everyone has! And, under the Data Protection Act of 1998(UK), all passwords must be kept safe and secure. If a hacker gains access to passwords, then you are responsible for not keeping them secure.
svg files cannot be displayed: https://replanalytics.repl.co/track/59b7e74d-b703-4533-8b2a-14974645be0a/empty.svg
So, what's the solution?
Password hashing is converting passwords to a string of characters that can't be turned back into the password. Think of it like this:
password = 'hello world' # password is set hashword = hash(password) # password gets hashed password != unhash(password) # password can't be unhashed with our knowledge of maths
Example
I've written a Python script to hash a string.
from werkzeug.security import generate_password_hash # pip install werkzeug password = 'hello world' hashword = generate_password_hash(password, 'sha256') print(hashword)
Output: ha256$Wz1CerC5MmrinjlW$56f1b796758634f1c17640dcfbc1905938a20caa3434c0ec8ca09fd8cdc9669d
So, what does this do?
Well, werkzeug
is a python package developed by palletsprojects, the creators of the Flask framework. werkzeug
means tools
in German.
Anway, werkzeug
has a security file with a function called generate_password_hash
. This hashes the password that you pass to it. You also need to pass a hashing method to it. I used sha256
which is one of the most popular hashing methods.
Once hashed, the password becomes a long string of letters and numbers. The ha256
at the beginning of the hashed password defines the hashing method that was used.
Benefits
The benefits of hashing a password are that:
- You can't find the original password with our knowledge of maths.
- The original password isn't stored in the database, so data is useless to hackers
- More security for websites on Replit
@ruiwenge2, you might want to integrate hashing into your websites!
How to hash
As I mentioned earlier, werkzeug
is a great python module for hashing!
from werkzeug.security import generate_password_hash, check_password_hash
generate_password_hash
hashes the password that you give it.check_password_hash
can be used to check if the inputted password is the same as the hashed password. More on this later.
You might think that you could hash the inputted password and compare it to the password in the database, but you can't because it gets hashed differently. This is demonstrated here:
password = 'hello world' hashword = generate_password_hash(password, 'sha256') print(f'1: {hashword}') password1 = 'hello world' hashword1 = generate_password_hash(password1, 'sha256') print(f'2: {hashword1}')
Output:
1: sha256$hoRRG7sXinkSjcBY$5ede7c11b9658239e9319f97ea2da55ef5044e87b5311bce3c230ce155f31a35 2: sha256$iDw7mL3jt6Jyf7D5$1a8e1f5cacf6e3bb33dd59548c05e515fff4d59354a63463025858a3f95286aa
Now, let's check if these passwords are the same:
from werkzeug.security import generate_password_hash, check_password_hash password = 'hello world' hashword = generate_password_hash(password, 'sha256') print(f'1: {hashword}') password1 = 'hello world' hashword1 = generate_password_hash(password1, 'sha256') print(f'2: {hashword1}') checked = check_password_hash(hashword, password1) print(checked)
Output:
1: sha256$0pMTuRIPZAgIY9rj$7c0f65d63608f483d4e0c8713b0ec7a725b8db102cd01a22a5dcd5dd5e278a5b 2: sha256$HkBW2kGoKAobLNbH$6b4e6e091ea619e3e3a62a998da91f651dc753e7794291987e648d8c22b90c87 True
To use check_password_hash
, you need to pass the hashed password, and the raw password to check it with. If the passwords are the same, check_password_hash
will return True
. If it isn't, you'll get False
.
This is how you can check passwords on websites (or apps!) to make sure that they are secure and can't be accessed by anyone!
Repl: @DillonB07/HashingDemo
Nice!
It's always possible to convert codes back and forth though.
Someone could find a complex method to reverse that.
@TheTesterz This is true, but as of right now, there isn't a way to do it and there isn't with our current knowledge of maths.
All of the websites you use, probably even Replit, use some form of password hashing.
From what I can tell, hashing uses a derivative of exponents to make an un-reversible string. I know I'm a bit late, but this Wikipedia article has some great examples. @TheTesterz
you should always make your password hashes salty, or even peppery. https://cyberhoot.com/cybrary/password-salting/
https://security.stackexchange.com/questions/3272/password-hashing-add-salt-pepper-or-is-salt-enough
@nixinator The function salts the passwords by default. Learn more on the documentation.
https://werkzeug.palletsprojects.com/en/2.0.x/utils/#Security%20Helpers
No salt? π₯Ί
Salting passwords to impede a rainbow table? How to salt.
@DillonB07
This method can not generate unsalted passwords but it is possible to set param method=βplainβ in order to enforce plaintext passwords.
@Highwayman Oh, the method does that itself by default. You can learn more here: https://werkzeug.palletsprojects.com/en/2.0.x/utils/#Security%20Helpers
ah! wait but then why were you able to directly compare?
@DillonB07
@Highwayman If you're talking about check_password_hash
then idk how it works. Just that it works. The module is open-source if you want to see the code for the functions.
https://github.com/pallets/werkzeug/blob/main/src/werkzeug/security.py#L172
ohh you used a function, nevermind then that makes sense now. @DillonB07
@Highwayman Great!
No offense, but I think Replit DB (db
) is a better option, it doesn't use as much data and it is easy. You don't need to go through all this hassle, but btw good job!
@Highwayman Yeah but this is just complicated, because if you want to make an account and log in, the problem is that you can't UNHASH
the passwords into the usernames, etc..
wh- you're not supposed to. that's the entire point. "unhashing" is very explicitly not ok. and what do you mean "unhashing the passwords into the usernames"?
@CodingElf66
@Highwayman Nvm I just mean unhashing the passwords
Ah. But why would you wan't the unhashed version of the password?
@Highwayman For perhaps, security?
how so? what kind of security exposes you to danger like that?
@CodingElf66
@Highwayman I don't know, but I just think Replit DB is a lot easier to apply and use.
Edit: You've got me lol
π make a wrapper around ReplDB
@CodingElf66
-
The point of hashing passwords is that you can't unhash them. This makes it secure because if you put the hashed password in, then it will hash the hashed password it won't be the same as the original password. And, you can't get back to the original password so if the data gets stolen then it doesn't matter as much. Though you still might get prosecuted under the Data Protection Act of 1998(UK).
-
For ReplitDB as far as I know, it stores information in plaintext and anyone can get it if they know the database id/link. And as that's the Repl id(I think) it isn't too hard to get.
-
Anyway this is really easy! You just use one
import
statement and then a function around the password you're storing and a function against the password you're checking. -
You could even use this with Replit DB to store the hashed passwords!
cool
yeah sure
although my next projects won't need login systems
@ruiwenge2 Sorry, I forgot that it mentions you. And I only said that because I've seen comments on your repls saying to hash them
@ruiwenge2 the battleship game?
@DillonB07 yeah and the other multiplayer game i'm working on :)
@ruiwenge2 sounds fun! Good luck!
The first time I read the password, I read it as sn236 instead of sha256. ππ. Btw nice.
@sn236 Lol! Also, thanks!