Using same password hash for account activation - hash

I've used password_hash($pwd, PASSWORD_BCRYPT) to create a hash and store in the user table. It will be used for login verification.
Since hashing is a one way function,
My question is can I use the same hash as the account verification code in the activation email send to user.
Will it compromise security since knowing the hash doesn't reveal the password.

Yes, it would compromise security because an attacker with access to the email account (either presently or at any future point in time if the email is never deleted), could run a password guessing attack on the hash.
If would be better to generate a 128-bit key using a CSPRNG, this can be emailed to the user as is. On the server-side you would want to hash this using SHA-2 for storage, because that way if your activation table data was ever exposed, an attacker could not activate accounts that do not have valid email addresses. Note that no salt is needed for automatically generated keys of this strength.
This approach is fairly simple, and mitigates the risk in sending the password hash directly.

Related

Why kerberos using hashes

Can you explain me the exact reasons and benefits of using hashes of password instead of the passwords themselves?
Because parcticly if you got hash of user you can authenticate as that user, and anyway the password is invisible.
It's more secure to store a hash of a password rather than a password itself (e.g. in keytab).
Kerberos only transfers over network encrypted Authenticator with its own copy of a secret key. Authenticator contains unique information about the client (for example, client name, client realm, the time on the client, and so forth). Each Authenticator is unique, because of the time information it contains.
So information transferred over network can't be reused (replayed later by an attacker), as Authenticator is unique and depends on time.
Hope this helps. With Kerberos you don't have password stored nor transferred over network. Which makes it more secure.

Right way to store encrypted info

I need to store a sensible info in a database (clients passwords). Is there a common practice? The information should be accessible by various users. Think about service company that should make maintenance of clients systems.
I'm thinking about using AES encryption. All the information is encrypted with the same main key. For every user this main key is encrypted with the user's password used as the key and stored separately. During login and authentication the main key is decrypted and saved in a session. Later the key is used to decrypt clients info. Is it a good practice?
Thanks
P.S.: Yes, I know that it's better not to use passwords, but it's not me to decide the way to access client's servers.

access token usage in authentication

I don't understand the point of having access token in authentication. Below is a paragraph of explanation I took but I still confused. Since every api call still go to the db look for the token, what's the different check for the username and password for every http request?
Instead of forcing clients to send username and password with every
request you can have a "get_access_token" function in your RESTful
service that takes the username and password and responds with a
token, which is some sort of cryptographic hash that is unique and has
some expiration date associated with it. These tokens are stored in
the database with each user. Then the client sends the access token in
subsequent requests. The access token will then be validated against
the database instead of the username and password.
Using the access token limits the amount of time the username and password are being used and sent across the wire.
How many times do you want your username and password, SSN, or other sensitive data do you want being stored and transmitted? Do you want that on every request?
First of all, access tokens are typically validated by checking the digital signature, which does not require the receiving service to talk to the issuing server. The client gets an access token once and uses it until it expires.
But even if the token had to be checked against the database on every call (when using reference tokens for example), tokens are still preferred over sending username and password on each call. They remove the need for the client to keep the password in memory (or elsewhere), where it can easily be stolen.
(1) Access token is less sensitive than your password. Access tokens typically expire after a short time (this is a requirement in the Oauth threat model), whereas passwords tends to be long term. If somebody grabs your access token, there is limited damage they can do. If they grab your password, then there is a lot of damage that they can do. Especially if you use the same or related passwords on multiple sites.
(2) If the server implemented password verification securely, then they should be using a slow function like PBKDF2, bcrypt, or scrypt to validate your passwords. These functions are designed to be slow so that if somebody gets access to the database, they will not be able to reverse many passwords: see Our password hashing has no clothes. Given that password checking is supposed to be slow, we don't want to be doing it often! Validation of access tokens is much quicker however.
(3) The system that grants you access to a resource ("resource provider") might not be the same as the system that checks your identity ("identity provider"). For example, many websites including StackOverflow allow you go login with your gmail account. In this case, Google is the identity provider and StackOverflow is the resource provider. Would you really want to provide your gmail password to StackOverflow? I hope not.

Protection measures against hash cracking when transmitting hashed credentials using a nonce

I need to authenticate users using an api key, but before handling it over to them I need to check their credentials, obviously. I think the process needs to go like this:
client->server: GET /user?username=fred
server->client: nonce=XYXY
client->server: POST /login?hashval={hash(username + password + nonce)}&nonce=XYXY&username=fred
server compares the result of hash(username + passwordFromDB + nonce) with hashval and responds with the API-key if equal
But if there was somebody eavesdropping the connection, although it wouldn't be able to directly discover my user's password, since it already knows the username and the nonce, if the password was easy enough the man-in-the-middle would be able to match my hash by trying all the generic possible values for the password.(brute-force attack)
I know connection over HTTPS and a strong password would make this process secure, but are there any other recommendations or ways of making this process more secure?
Thank you
This is basically a form of digest access authentication and as such has its same limitations.
Since all the details to compute the hash are sent along with the hash, the only thing that an attacker needs to "reverse" is the password. If that is weak, then rainbow table or brute force attacks could crack it. The only way to delay an attacker is to have a very long and strong password.
But since you are using an API key for service authentication, as a man-in-the-middle attacker I would let you authenticate with a password and then just get the API key from the response. I assume you use the API key for authentication of the rest of the requests (just like a session cookie is doing for web applications)?
There are of course other variations of securing a service, depending on what you are doing, but actually making it secure means using HTTPS as you mentioned yourself.

Is it possible to verify a password hash against another password hash?

Consider the following interaction:
A user stores their username and password on a web server. For the sake of security, the server records a hash of the password plus some unique salt.
While the user is using a client application, it makes a request to the server submitting their username and a hash of the password plus some other unique salt.
So you have the following information on the server and need to know whether or not the request is authentic:
The server's salt
The server's hashed password
The client's salt
The client's hashed password
Again ... client sends: clientSalt + MD5(clientSalt + password). Server has serverSalt + MD5(serverSalt + password). I don't want to know the password, I just want to know if the hashes were calculated from the same password.
Without knowing the password that was hashed, is there any way to verify that both hashes are of the same password?
My goal is to allow some form of secure authentication in a client-server environment without ever exchanging the actual password over the wire. This is just one idea I've had, but I don't even know if it's possible.
That would require unhashing the password, which is not possible. If the server receives: salt, md5sum, it can't see what went into the md5sum.
A challenge-response protocol would work instead. The server should generate a random value nonce and send it to the client. The client calculates md5(md5(password) | nonce)) and returns it to the server. The server verifies by checking md5(storedpassword | nonce).
No, you can't do this.
Once you add a salt into the mix it becomes practically impossible to compare hashes. (To do so would require "un-hashing" those hashes somehow before comparing the "un-hashed" data.)
Challenge-response authentication is probably the way to go, possibly using Kerberos, depending on your tradeoffs. One of the tradeoffs being the possibility for attackers controlling the clients to use compromised hashes to authenticate themselves.
Don't invent your own cryptographic protocols. Use one that is well-known and well tested. If possible, use an existing (vetted) implementation.
My goal is to allow some form of secure authentication in a client-server environment without ever exchanging the actual password over the wire. This is just one idea I've had, but I don't even know if it's possible.
For this, I advise looking into Kerberos: Official Site and Wikipedia
It's impossible. If you don't store password on the server, user must provide it.
OR
If you store password on the server, user can provide hash calculated using requested salt.
You will not be able to verify the hash with this setup.
If you don't want someone to see the password go over the wire, SSL is the easier way.
If you don't want to use SSL, you could check out SRP.
Additionnally: don't use MD5+Salt to store your password, use key strengthening functions like bcrypt or scrypt.