How to get plaintext from hashed text? - python

So, I'm working on a project where I'm storing passwords in a mongoDB and using Python. Python do has bcrypt build-in module which allows us to hash a plaintext. Now, I can hash a password and store the hashed password in database. Cool. And If I want to know if saved (hashed password saved in database) is same as a given password or not. (i.e. If I hashed a password 'Password' and saved it in database, bcrypt allows us to compare this hashed password and a plain password to check if they are same or not) I can check it with some built in functions.
But, what I really want is, I want to take that hashed password and want to print original plaintext.
(e.g. If I hashed a password (say Plain password is 'Password' and hashed password is 'Hashed_Password' ) and saved it in database along with UserID and email for a specific website, now at some point I want to know what was the UserID and Password. So I can get UserID (since I'm not gonna hash it) but I'll only be able to get hashed password (i.e. 'Hashed_Password) and not the real one (i.e. 'Password') I saved.)
I hope you can Understand my problem and give me a solution. In summary, is there a way to get plaintext (i.e. original text) from hashed text or Should I used any other method to do so (like encryption or something).

The whole purpose of hashing passwords before saving them in a databse is, others should not be able to see(calculate) the oraginal password from database.
Simply you cannot get oraginal value from a hashed value.

From what I know,
We hash passwords so that even if the attacker gets access to the database the attacker will not be able to have the passwords without using a technique like brute force to get the password. I.E. assuming the attacker know how you hash the password a dictionary of passwords can be hashed and compared with the database to see which passwords match.
Now if you want to reverse the hash I am pretty sure that can't be done other than you trying the brute force method explained above. We can't reverse the hash but only guess by giving passwords.
In terms of encryption which is often used as another layer. For example you could use encryption before the hash and then hash the encrypted password. This way even if the attacker inputs the correct password and only hashes that password the attacker will simply not get it right when compaing the hashes.

Related

Why generate_password_hash() creates a different hash for the same password?

from werkzeug.security import generate_password_hash
password_hash = generate_password_hash(password='qwerty', method='sha512')
print(password_hash)
I get a different hash every time I run it on pycharm. Here are some results:
sha512$C6Q28TMjmhzqiJ9I$4d59ead48cde4dc1b0dcc359e5479cede957cb49013602bd2028f3f3eeba55386e441d70866feb70e2eeb7ab1108aad9980241fb87275282a7181f22da329b44
sha512$Y48EzPVVB3OgFvTp$294f00b6129e870480661090b5f946f601020c601c90bb12ecb17c8b8fa9b214cf8afd4954f5d3c50b65f14aa21caf9e0f41aaa718f1a5d22d18da49a70b1f12
sha512$RN4rNnGhSV95T806$1dfa460209d297e682e610c4f33178125719cc3f6c670f4110b5be405e63ad312a09e0dff8800f3fc23afaff2d892f73e433d53be447a268aacaede2f8d2a461
Shouldn't it be this and be the same all the time?:
sha512$0dd3e512642c97ca3f747f9a76e374fbda73f9292823c0313be9d78add7cdd8f72235af0c553dd26797e78e1854edee0ae002f8aba074b066dfce1af114e32f8
Good quality password hashing makes use of a salt:
In cryptography, a salt is random data that is used as an additional input to a one-way function that hashes data, a password or passphrase. Salts are used to safeguard passwords in storage. Historically, only a cryptographic hash function of the password was stored on a system, but over time, additional safeguards were developed to protect against duplicate or common passwords being identifiable (as their hashes are identical). Salting is one such protection.
A new salt is randomly generated for each password. Typically, the salt and the password (or its version after key stretching) are concatenated and fed to a cryptographic hash function, and the output hash value (but not the original password) is stored with the salt in a database. Hashing allows later authentication without keeping and therefore risking exposure of the plaintext password if the authentication data store is compromised. Note that due to this, salts don't need to be encrypted or stored separately from the hashed password itself, because even if an attacker has access to the database with the hash values and the salts, the correct use of said salts will hinder common attacks.
this was supposed to be a sandbox example of a hash that was pulled from a SQL table, there were a few things I did wrong:
for check_password_hash I accidentally was checking 2 hashes in pwhash and password
SQL password change wasn't committed to the database so it didn't check the most up-to-date password

Convert hashed password to string werkuzeug python

I am using Werkzeug for password hashing so that the passwords entered by users will be safe(atleast).
Lets say my application is as follows:
When a user gets logged in I will use check_password_hash and then login the user inside.
After the user is logged in, I want to show them their password.
The problem I am encountering:
How do I convert the hashed password back to string to show the user their password?
My code is as follows:
>>> import werkzeug.security as ws
>>> ws.generate_password_hash('abcdefg')
'pbkdf2:sha1:1000$fYAXLNA6$637528ae2fa195304c328d585e805b164f1c718f'
>>> ws._hash_internal('pbkdf2:sha1:1000', 'fYAXLNA6', 'abcdefg')
('637528ae2fa195304c328d585e805b164f1c718f', 'pbkdf2:sha1:1000')
Now how do I convert this '6375.....' back to 'abcdefg'?
I have access to database and the all the other stuff required. Basically I am the admin!
Note: I cannot use the password which user entered while logging in. I can only use the password from database.
After the user is logged in, I want to show them their password.
The whole purpose and reason of hashing a password is that you can never do this. Not you, not anyone else.
If someone has access or steals the database with the list of passwords, converting the hash back to the original password is really, really expensive. You will need a million years to break and reverse one single password.
We cannot get the original text back while using hashing. Generally all the passwords are stored as hash value, in order to make the passwords private (known only to the user). All the servers implement this. If you want to get the password back then you should use symmetric key cryptography. Where a secret key will be shared between the clients and the server (But it is a very bad practice) It better that you go with hashing.

should I store all encrypted password to database using generate_password_hash()

When I use generate_password_hash() function, I get a encrypted password string which contains a random salt.
>>> from werkzeug.security import generate_password_hash, check_password_hash
>>> generate_password_hash('password')
>>> 'pbkdf2:sha1:1000$3j8Brovx$9acddcd67da9e4c913817231c882a0f757e2d095'
If I store this string to database, someone else hacked into my database and get this string, it's easy to get the origin password using brute force cracking becasue the encrypted password contains the salt.
check_password_hash('pbkdf2:sha1:1000$9HycZ0Qa$94f08a91fba1c040c5bffb6c7e1ab5a6ad4818de', 'password')
Should I encrypt the origin password using my own salt first before using generate_password_hash() or is there a better solution?
Thanks.
it's easy to get the origin password using brute force cracking because the encrypted password contains the salt.
No, it's "easy" to brute force, because you're having a low iteration count of 1000.
Should I encrypt the origin password using my own salt first before using generate_password_hash() or is there a better solution?
No, encryption is reversible and since a lost database also means that the encryption key is probably lost too, this would mean that the additional encryption is useless.
An easy fix would be to increase the number of iterations to a million or 10 million depending on what you can afford on your server that your users don't run away because of a slow authentication procedure.
generate_password_hash('password', method='pbkdf2:sha256:1000000')
The problem with PBKDF2 is that it can be easily parallelized, because it doesn't need much memory. There are alternatives such as scrypt and Argon2 which can be configured to require much memory. Memory is currently the main limitation of dedicated password brute forcing machines based on ASICs.
Ultimately, nothing you do, will lead to a secure authentication system if your users are using "password1" as their password. You should require your users to use complicated passwords with at least 12 characters including uppercase letters, lowercase letter and numbers (optionally including special characters). Those should also not be part of a dictionary.
See more: How to securely hash passwords?
When you store password hashes, the main assumption is that it is too difficult to retrieve the password using brute force. If you want it to be safer, go for slower hash algorithims and longer passwords.
Encryption is worse than a hash because hash is irreversible and brute force is the only way to retrieve the password. With encryption, brute force is just one of the options.
Once that is clear, you have the option to have a "secret" salt in the code or salt can be saved with the hash. Saving the salt with the password is safer! Why? Because you have a different salt for each password, so the intruder has to brute force each password separately. If you have one global salt value, brute force can be done for all passwords in the datbase in one go.

Recover a salted and hashed password in python

I have managed to salt and hash password using this method:
import hashlib, uuid
salt = uuid.uuid4().hex
hashed_password = hashlib.sha512(password + salt).hexdigest()
How do I reverse this process to recover the actual password?
Update: You are supposed to take a password from the user, apply the same salt and hash method to their password, and then compare it with the originally salted/hashed password to see if they match. That makes perfect sense.
You don't. Hashing is a technique which is only one way. This is the whole point of hashing.
You never store raw passwords in order to protect your user if you got a leak of information in your DB.
If you want to implement some "password recover" procedure, you need to do as everyone do, send a email to the person with a temporary link to reset password on send a new one randomly generated.
Hashing is one way as in you can only encrypt (for example) a string and then compare the user provided hash with the one your app generates.
However, there is simple-crypt and it may be what you're looking for if you want "2 way" hashing.
Good question.
First off: never send users their passwords in plaintext!!
It's considered a bad security practice for a few reasons.
If anyone gets access to a user's email account (gmail, etc), then they have the password and can hijack the user account.
Second, hashing is a one-way form of encryption where you turn the password into gibberish. The big value in hashing is that the same password will always be turned into the same gibberish: every time. This means you can do password matching without ever storing the raw password. The reason you're supposed to hash a password and not do 2-way encryption like AES-256, is that 2-way encryption requires the creation, management, and securing of encryption keys which can be hard. Hashing is just easier and more secure for the vast majority of developers.
Instead of implementing password reset stuff by sending a user their password, you should instead send a user a link to a secure page where they can reset their password with a one-time token that expires after a certain amount of time.
This way, even if an attacker gets a hold of someone's email account (gmail, etc.) -- there's only a limited amount of time they can do damage.
There are a variety of ways to do this stuff yourself, but an easy approach to getting a one-time use token you don't have to store or manage is to offload user management to a microservice like Stormpath where it takes care of all the user management for you: password reset, password storage, user profiles, authentication, encryption, hashing, etc.
If you wanted to implement something like this in a Flask web app, for instance, you'd use the Flask-Stormpath library like so:
from flask import Flask
from flask.ext.stormpath import StormpathManager
app = Flask(__name__)
app.config['STORMPATH_ENABLE_FORGOT_PASSWORD'] = True
stormpath_manager = StormpathManager(app)
app.listen(3000)
NOTE: I work at Stormpath, but these rules apply regardless of what you're using and help make any application more secure.

How to create a user login section in Python with Tkinter module

I'm working on a small uni project where I have a program for a single user in Python using the tkinter module. I want create a screen where they will be required to enter their password. I'm not sure how to do this and where would I store the password?
I have no experience in database but I've heard of MD5 & SHA256 and I was thinking of writing the hashed or encrypted password to a text file and then reading it but I am not sure if this is safe.
The password functionality is to prevent others from looking at the users' personal diary entries.
This answer takes the simplest route in achieving a measure of security. #J.F.Sebastian points out in comments that you can definitely explore more robust security procedures with greater encryption, but this really depends on your needs
If your goal is just to experiment and create a proof-of-concept login system, you can just go with the encryption + flat file approach. For storing a password, you probably only need SHA1 since what you are encrypting is a variation of the password, and not sensitive data itself. What I mean is that you don't care about the data itself. You only care about comparing encryption results...
First you would pick a secret character set as a "salt". Unfortunately you are using an uncompiled language, so your salt will probably live within your program. But at least the password files by themselves are not useable. ("salt" is being used here as your only secret value. In a more secure approach, the secret would be a separate key used outside of the hashing of the password+salt)
import hashlib
salt = "-WOu#p.Za,>W+6&`A63/"
user_password = "password"
sha1 = hashlib.sha1()
sha1.update(user_password + salt)
encrypted = sha1.hexdigest()
print encrypted
# 476dc4076d1c7eb43152b78e9dc20d892f660f24
You can store that encrypted sha1 value to a file. Its of no use to anyone without the secret salt value. All you will do is use this value to compare against the future sha1 value when a user authenticates
test_sha1 = hashlib.sha1(raw_input("Enter password: ") + salt).hexdigest()
# Enter password: password
print encrypted == test_sha1
# True
You never actually know their password. You only know the sha1 value derived from it plus the salt. Think of it like two guards each needing to provide a key, turned simultaneously, to open the vault.
Otherwise.... you can store this in a database, along with the salt value. The procedure would still be the same but you move the salt to a more secure location that requres auth to even query it. No matter what, your salt secret is the most prized possession.
Addressing the SHA256... Greater encryption algorithms are needed for the act of storing the real data in a tangible format that needs protection (or when creating a slower hashing process for your passwords to make brute force cracking take longer to accomplish). For instance, if you decided to store a users private diary entries, you might encrypt against their password, and only store this encrypted format either on disk or in a database. When the user authenticates, you can deliver to them the decrypted data by way of their password. You never store the password, so even you as the author of the software can't access their data without their original password.
Again, as #J.F.Sebastian points out, the more robust approach would be using a bcrypt library:
http://www.mindrot.org/projects/py-bcrypt/

Categories

Resources