I'm working on a python script that will need to connect to a postgreSQL server. What the best practice for the username and password? In this tutorial ZetCode is just using the username and password (if needed) in the code itself. Is this the right way or should there be some sort of hashed file to read from?
http://zetcode.com/db/postgresqlpythontutorial/
Store the username and password in a file, then restricting access to that file would be a good start.
Storing a hashed username or password won't work, because you cannot undo a hash function.
If you think that storing the username and password in plain text isn't secure enough in your situation, encrypt them. When the script starts, it asks for the passphrase. That passphrase is then hashed using PBKDF2 or scrypt. Use that hash as the key for encryption/decryption. See cryptographic right answers.
This does mean that your script needs operator input every time it starts!
Related
I'm making an application where there are user accounts in play.
All data of the user is encrypted using a key. This key is encrypted itself, using the hash of the user password. This means that when the user logs in with the correct password, the resulting hash will decrypt the key which can then be used to decrypt all other data of the user. The user password is the "gate" to all user data.
Forgetting their user password means losing their account. I want to implement a way to recover their account.
To recover their account, it needs to be possible to recover the decrypted key without storing it in decrypted form in the database and without encrypting it using a password. It needs to be recoverable using email recovery or something similar.
I haven't found a way to make this work and that's why I'm asking help. I don't need code (it's written in python though if you really want to); just pseudo-code about how one should go about implementing this is enough.
I need user_password plaintext using Django. I tried many ways to get plaintext in user_password. but It's not working. So, I analyzed how the Django user password is generated. it's using the make_password method in the Django core model. In this method generating the hashed code using( pbkdf2_sha256) algorthm. If any possible to decrypt the password.
Example:
pbkdf2_sha256$150000$O9hNDLwzBc7r$RzJPG76Vki36xEflUPKn37jYI3xRbbf6MTPrWbjFrgQ=
As you have already seen, Django uses hashing method like SHA256 in this case. Hashing mechanisms basically use lossy compression method, so there is no way to decrypt hashed messages as they are irreversible. Because it is not encryption and there is no backward method like decryption. It is safe to store password in the hashed form, as only creator of the password should know the original password and the backend system just compares the hashes.
This is normal situation for most backend frameworks. Because this is made for security reasons so far. Passwords are hashed and saved in the database so that even if the malicious user gets access to the database, he can't find usefull information there or it will be really hard to crack the hashes with some huge words dictionary.
On the login route i retrieve the password. How do i find the user with the matching hashed password in the database without fetching the whole user table and traverse it on the server?
In mysql every user has a hashed password from registering. I generated it like this: bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
If i execute the same method at login (for the same plain-text password) i get a different hash.
So something like this:
select * from User where hash_generated_at_register = hash_generated_at_login
Fails, even if the plain-text password used in the login and register step is the same.
From what i understand password checking in bcrypt is done by bcrypt.checkpw(password, hash) instead of hashing again. Using this approach the only options i can think of is to select the whole User table and travserse it on the server side. But i want to to the traversal on the db-side! How do i accomplish this using the bcrypt hashing method?
The whole way bcrypt works is that it gives you a value that combines the hashed password and salt into one value for you to store.
This means that you cannot recreate the hash from the password without the salt, which you do not have.
You need to select the user from the database via some user_id that you may have, and then use the bcrypt library to compare your password with the combined value that you have stored.
bcrypt.hashpw(password, hash_and_salt_value_from_db)
You can use the same function you used to create the "hash", but instead pass in your stored value. The function is smart enough to realise that it is a hash+salt and will extract and use the salt for you.
So you then want to check
if hash_and_salt_value_from_db == bcrypt.hashpw(password, hash_and_salt_value_from_db):
# tada, valid password
Shout if this doesn't make sense.
Modern security encryption assigns a unique salt (random string) to each user so that if some user, say Alice, signs up to you website and uses the password "password" then the hashed database entry she will be assigned is:
Hash("password" + "random_string_for_alice") = "HASH_VALUE:MD51000:random_string_for_alice"
Here the hash string includes the hashing algorithm (MD5)x1000 iterations and the salt used ("random_string_for_alice")
Now if you are just supplied a password - only a password and not a username - in order to find out whose (if any) username it belongs to you will have to look at each user's hashed password, extract the public salt and apply the iteration and then compare it. You will need to do this for each user in the database to find the answer.
And this is, of course, the point of modern password encryption recommendation..
So I have a wiki site made with python using flask. In the site you have to register to submit a post. When I made my account I looked at the db file. Under users it has my username but my password looks something like this
pbkdf2:sha256:50000$trQqtDeG$fb666b434b1920c814101fd3afedf75c9e21e2eebbfe7e6aa9fe4aec3d69b1e3
I made my password poop ( dont ask why lol ) but thats what it comes up as. Lets say if I were to oneday forget my password, how can I check to see what it is?
Edit: Thanks for the explanation ! :)
You can't. This is a one way hash, and it's meant to be that way - it's a common practice not to store plaintext passwords on the database, so that nobody can ever see what is the users password.
The general concept is that given an user password (and a salt) you are able to compute the same hash value and compare it to see if the password is correct, but you are not able to (easily) get the password by obtaining the hash.
To deal with 'what if I forget my password' issue you should implement a password reset procedure.
My python-script (Python 2.6, on Debian Linux) asks the user for a password, wich is then saved in the users home directory.
Because i don't want to safe the password as plain text, i want to encrypt it somehow. So i thought that maybe i could use the (private) ssh-key of the user to encrypt and decrypt the password thats saved in the file, so that only one with access to the private ssh key can decrypt the saved password.
Is it a good idea to use the private ssh key for this? How can i use the key to encrypt a string in python?
(btw i don't want to use keyring and stuff like that)
EDIT
Okay i understand its a bad idea to use the users ssh key for stuff like that.
Instead i'm now just using base64 encoding, like described here:
How does one encode and decode a string with Python for use in a URL?
of course its not save, when someone reads my python script. But its enough for me, not having to save the password as plain text.
The only thing that's definitely worth doing is storing the file that only the user can read.
Your argument for using the ssh key seems to be something like the following:
I need to store a password, so I'll encrypt it
If I use the user's ssh key to do the encryption this will prevent someone decrypting the password even if they have the source of my script because only the user can read their ssh key.
If you store the encrypted password in a file only the user can read you get the same benefit as using the ssh key without having to bother with reading the users ssh keys at all.
I agree there's some benefit to not storing the password in plain text to prevent someone logged in as root just doing:
cat secret-password
to get the password but remember it would be easy to find the line in your Python script which said:
password = decrypt-password(data)
and add the following line:
print "The user's password is",password
Something like os.fchown() would do the trick to protect the file, as would just creating the file with the correct permissions in the first place.
You could base64 encode the password so it is not plain text, but if we assume an attacker can read and edit your script the only thing which will protect the user is the attacker not being able to read the file containing the encrypted password.
If you're really worried about this, just prompt the user for the password each time they run the script.
Is it a good idea to use the private ssh key for this?
No:
The private key could be password protected itself.
It's poor form to go reading user's secret keys.
It can be changed without regard to your script.
You also seem to be mixing up your terminology. You've used encoding, decoding and hashing when I'd assume you'd mean encrypting and decrypting.
As Dave Webb points out, your premise that the private key file is read-only to the user and not itself encrypted. You'd be going from "protected by filesystem user-read-only" to "protected by a different file that is user-read-only".