8

I'm quite a newbie at systems architecture and security so I just want to check that this plan makes sense. I'm building a web app and I need to store a password for each user. I've already read plenty about hashing algorithms, salt, and so on. I'm going to use Argon2 since it seems to be the current recommendation. My question concerns how the hashes are stored and checked in terms of overall architecture.

Since hashing with Argon2 is intentionally quite expensive, I want to create a service in a separate module/process so that it can easily be moved to a one or more separate machines if needed. Even if it lived on the same machine as the main app server, it would be trivial to monitor its CPU and memory usage to tune the cost factors for the hashing algorithm.

My app will send HTTPS POST requests to the service to either create, update, delete, or verify a password. All the details will be in the request body, including the password in plain text. The connection will be encrypted. The response will simply be an indication of success or failure.

The service will handle the logic of database operations, hashing passwords, and comparing hashes for equality. The passwords will live in a separate database from the users, so that even if an attacker dumps the entire password database they still don't actually know anyone's password, and vice versa. Also, if I ever migrate to a different storage solution for my other data, there is less migration to do since the passwords can remain as they are.

Does that sound good? Or does it somehow open up more weaknesses that I'm not aware of?

Alex Hall
  • 213
  • 2
  • 4
  • 1
    There's to much going on in this question. We don't need to know the algorithm, we don't need to know about the web app, and we don't need to know about if it lives on the main app server. What your question really is boils down to this: Is it a good idea to use a separate micro service to encrypt, verify, modify, and delete passwords that have a CPU intensive crypt cipher and then stores those in a separate database away from the users? The answer to that is yes, it's a good idea. Not the best, but not the worse. There are a couple of things you need to be careful of though. – Robert Mennell Mar 25 '16 at 22:49
  • @RobertMennell Each user will have an ID that has the same value in both the main database and the password database. When the user logs in that ID is looked up via their username/email and sent in a request to the service, which uses it to check that the password is correct. – Alex Hall Mar 25 '16 at 23:12
  • well yeah that's fairly standard if they aren't in the same table. – Robert Mennell Mar 25 '16 at 23:27
  • I was responding to you saying I need to be careful about the linking but I see that's edited now. So what else should I be careful about? That's really the point of the question. – Alex Hall Mar 25 '16 at 23:28

2 Answers2

4

Hashing being too slow means you need to use a faster hash, not a second process. Try tweaking the parameters on Argon2 or move to bcrypt (which is still really secure). Adjust the parameters to get the hash to a reasonable time (~0.2-0.4 seconds) and keep everything in one process.

If you want, you can still keep the passwords in a second database to reduce data loss if your primary database's contents get stolen, but I am not sure this is needed. Conventional wisdom says that bcrypt is secure even with all data being stolen. Now that is no guarantee, but unless you have the NSA coming after you, or you're storing something valuable enough to motivate large portions of the Bitcoin network to stop miming and start cracking your passwords, I'd be very comfortable with a reasonably performing bcrypt.

Neil Smithline
  • 14,621
  • 4
  • 38
  • 55
3

While this is a security question, I'd like to make you aware of another consideration:

Performance considerations

Creating a micro web service to handle authentication might be a good idea in some cases, this depends on the use cases.

Yet, you might want to consider that establishing many https connections (for many requests) comes at a cost as well. It might be useful in terms of load minimization (as that seems to be a concern) to have the two services establish a long lived tunnel that is used by multiple connections.

As to the security considerations

  • The actual, user facing web service will act as a TLS client in this szenario.

    It is extremly important that the trust store is working as intended (e.g. trusting only the certificate of the password service) and that the password services' private key as well as the web services' remains private.

    Else,

    • the service could become vulnerable to MITM attacks (especially when running on different machines)
    • attackers could directly interact with the password service, maybe DOSing it with extremely big payloads or being able to use indirect side channel timing attacks.
  • The web service and/or the password service should preferably use some strategy to be sure to mitigate possible timing attacks and DOS.

Also, of course, the increased scalability, seperation of concerns and especially network segmentation (which are good and important), comes at a price: Implementing the logic may become more complex and you might introduce subtle problems you are not aware of. This is especially true if you are not used to that.

An example of increased complexity could be: On email changes, who handles the actual commit atfer the new email as been verified and how, e.g. who is authorative for changing data that is duplicated across the databases? Do you want to start network IO within a database transaction?

As to the hashing function

There is a question here about hashing passwords securely that has very good answers.

Consider that there is no need for you to use bleeding edge research hashing functions. The others (PBKDF2, bcrypt and scrypt) are as-good for this purpose and you do not have to expect a severe problem to be found anytime soon as they have had time to be thourougly peer reviewed.

Tobi Nary
  • 14,302
  • 8
  • 43
  • 58