Where to store password salt and how to get it - database

I'm in charge of doing the authentication in our .Net MVC 4 Web Application and I have hit a bump concerning password hashing, storing and authenticating.
Plan is to currently use 2 Salts, 1 Dynamic (Per User) and 1 Static (Web App Constant) and a strong Hashing function.
Given a simple User table that contains a username and password:
Do I store the per user salt in a column in the User Table?
My worries is that by doing so, I will have to get the user from the database in the web application memory with its username only. Is there some sort of attack where that could be problematic?
Ideally I'd like to have this be a one step/one SQL Request authentication.
Am I worrying too much? Is there an alternative to a "Per User" salt where I can still do a one step authentication?

The salt can be stored together with the password-hash, so you can create a salt per password instead of per user. It is a common practice for password hash functions (slow key-derivation function like BCrypt or PBKDF2), to return the salt cleartext as part of the password hash, what means that you can store salt and hash together in a single database field.
To verificate an entered password, you first have to search for the password-hash (using the username or email), and then the function can extract the used salt from the stored password-hash and use it to compare the hashes. That should actually answer your question, databases usually don't have appropriate functions to hash passwords, so you cannot do the verification within an SQL-query, the verification will be done in the code.
The second salt is actually called a pepper, the best way to add this server-side secret is, to encrypt the already hashed password with this secret. In contrast to the hash, this will be a two-way encryption, what allows to exchange the key should this once be necessary.

You don't need an external library for doing this. The framework has its own PBKDF2 implementation built in. I prefer storing the salt in a separate field in the database but that's just a matter of taste I guess.
I've written up my thoughts about password hashing here

Related

What could be a decent workflow to a user registration application to store password?

I am developing an application (web\mobile). The user have to register the account using a form on the application (it contains some data as username and password).
These data have to be stored in a database table, these data travel on Internet so I think that it is not a good idea that the password is in clear.
I think that the client have to encrypt the password in some ways and that this crypted password have to be stored in the DB.
What could be a decent workflow for this task?
A common way to do this is to send the password as clear text via a HTTPS connection. HTTPS is a must when anything confidential is sent through internet, not only for passwords.
On the server, calculate a hash. There are many algorithms for this, some more secure than others. A hash function works only for one direction: the password cannot be derived from the hash. Store that hash to the database instead of the password. When a User logs in, calculate a hash from that password, and compare it to the hash stored to the database.

Hashing vs Database Lookup Efficiency

I'm intending on using a hash to generate a verification token for verifying email addresses. The hash would be generated like so:
email:username:salt
The hash is generated with the SHA256 algorithm and the same salt is used for each token generated.
The alternative, and more commonly used, method is to generate a one time UID which is stored in the database and acts as the verification for the new email address.
My question is: is this an efficient (taking processor and disk utilisation etc.. into account) way of achieving the generation of a token for email validation.
The whole purpose of email verification tokens is to generate a token from your secure web server, and email that token out to someone so that they can click a link which contains that token, so you can then verify their account.
The important things to keep in mind:
The token must be impossible for the end-user to reproduce, otherwise it can be faked.
The token needs to be cryptographically signed by your web server (ideally), so that the CLIENT knows this is a valid token. This also is important because when the user sends this token BACK to your server, you can verify that YOUR server is the one that created it.
The token needs to be expireable: you should be able to 'expire' this token if it is not used within a certain amount of time: 24 hours, 3 days, etc.
For this reason, I would not recommend the approach you're taking.
Instead, I would use a JSON web token (this is an ideal use case for them). This other SO question has a decent summary.
Using a JWT will let you:
Create the token on your web server.
Set an 'expirey' date on this token so it can't be used after a certain time limit you specify.
Encode any user-specific data in the token you want: usually a user ID or something similar.
When the user sends the token back to your web server, a JWT will:
Guarantee that the token was generated by your server and not someone else maliciously.
Guarantee the token is still valid (in terms of timestamp).
Guarantee the token hasn't been tampered with.
Let you view the previously encoded token data (user ID / etc).
I hope this helps =)
What you're doing is somewhat secure.
I would refer to your salt though as a key - you are generating a keyed hash. Ensure that you generate a key with sufficient entropy. I would recommend a strength of 128 bits generated by a CSPRNG.
Some keyed hashes generated in this manner are vulnerable to a length extension attack. That is, if an attacker has generated a validation token for foo#example.com then they will be able to work out the hash for foo#example.com.example.org. This is because the output of a hash algorithm also betrays its state. To mitigate this, you could use the HMAC algorithm.
Your current approach also has the limitation that an email address always has the same token. If an email address expires (say Bob Smith with email bobs#example.org is fired from his job at Example Organisation, he will know the verification code that the next Bob S. will get when he starts working for Example Organisation). Whether this is any risk to your application is for you to decide. To mitigate this, you could use JWTs instead, which will enable you to put an expiry date into the token that can be validated. JWT's HS256 algorithm also uses an HMAC, solving that problem too.
Using keyed hashes should be efficient, and doesn't have the storage, maintenance and overheads of database lookups.
By UID do you mean UUID?
Remember that:
the purpose of a [UUID] is to be globally unique, not to be unguessable.
and
[UUIDs] are designed for uniqueness, not for security.
You would be better off generating an 128 bit token on the fly using a secure source of entropy (say another CSPRNG). You may want to hash these (without salt) on the server-side using SHA-256 to prevent any data leakage vulnerability from meaning an attacker can validate any email address.

Do I need to encrypt secret access key?

I'm creating a mobile REST API.
Currently, when user signs in with email and password, I generate secret session key (64 chars long), store it in database and send it to the user so that user doesn't need to log in again for the future request until they logged out.
For the next requests, I just check if the provided session key is equal to the one in database.
But, there is a big security loophole I see in this scheme. If the attacker got access to the database, they can use the secret key and impersonate anyone without knowing the password at all. What's the point of encrypting the password in this case besides obscuring user's real password - it doesn't prevent anything else.
So, my question is how do you store these access key correctly?
Twitter will send session key on sign in on their API. So, how do they store these keys?
Thanks.
It's even better to hash the session key, just as if it was a password, and store the hashed value in the database.
The only difference from password hashing is that, since your session keys are (I hope, at least) generated by a secure random number generator and long enough to be unguessable by brute force (I'd recommend at least 128 bits of randomness), you:
don't need a separate salt, and
can use a simple cryptographic hash function like SHA-256 instead of a deliberately slow password hashing scheme like PBKDF2.
Not using a salt also allows you to use the (hashed) session key to look up session records in the database, so you don't need a separate session ID for that.
So, to sum it up:
When starting a new session, generate the session key using a secure RNG, store the SHA-256 hash of the session key in your database, and send the (unhashed) session key to the client.
When the client makes a request, hash the session key sent by the client using SHA-256, and look up the corresponding record in the database.
You may also wish to limit the lifetime of session keys, and to provide some mechanism for the client to explicitly invalidate all of the user's sessions, to mitigate the effects of a compromise of individual session keys.

How to move CodeIgniter user passwords to Laravel

I have a CI project and want to migrate its database to the Laravel's one.
The only problem is that they have different ways of hashing user passwords and so I cannot find a way to move them from one database to another.
I have already googled for the answer but nobody I found speaks about migrating passwords.
Thanks in advance.
I have no experience with CodeIgniter and don't know how it does password hashing, but here's how I would approach the problem.
To make something clear: You can only "convert" the password to a Laravel hash if you have the actual password (in plain text). As you don't store the plain password you only have it at the moment the user logs in our enters the password somewhere.
Therefore you have to realize that this migration isn't done in a few hours. It will take some time for all your users to enter their passwords.
So what I'm getting at is you should add a field to your users table for the CodeIgniter password. Let's call it ci_password. (Or probably you just have to rename the old password column to this and create a new one for the Laravel password).
Now every time a user logs in, you first check if a Laravel password is stored in the database and attempt a log in. If there is no Laravel hash stored, check with the ci_password. (For this you will have to make CodeIgniters hashing work inside your Laravel application. Sorry can't help you with that)
If the ci_password is valid use the password input from the user and generate the Laravel hash (using Hash::make('secret')). Store the new hash in the database and delete (set to NULL) the ci_password.
This way the passwords will be migrated one by one and you have to do nothing. And maybe, on one lucky day, all old hashes will be migrated and you can remove this logic and the column in the database.

should I hash username in OTP based two factor authentication database?

I currently dealing with a ssh two factor authentication plugin.
It can be used like this:
$ ssh localhost
password: [ssh password]
Name: [your name]
OTPCode: [your code]
there is a list of username and OTP Secret in sqlite db.
if the sqlite db leaks, it is dangerous. should I hash the username and add a nick name to distinguish a which one is which. will this design cause any problem or is it neccesary?
To be honest, if someone gets hold of the database in the clear with the secrets in it, they aren't going to be too bothered about hashed/obfuscated usernames. They already have the secret information.
An attacker could realistic generate all the OTPs against all the secrets from the database in a fraction of a second and then try them all for any given username. Moreover if they have sniffed the username in the past and know when they authenticated (For TOTP), they can create all the OTPs for all the secrets in the database for that window and then see which secret corresponds to that user.
Basically if you loose your token's shared secret, loosing the corresponding username is going to be the least of your worries.
Focus on locking down the database or even better getting the authentication mechanism off of the machine.

Resources