1
$\begingroup$

I'm developing a desktop application where the users will login with username and password, which is then verified against a database. After the initial login, the current user should be automatically logged in each time the application is started (until the user logs out or 1 month has passed).

I could encrypt and store the last successful username and password on the computer, but the decryption key would have to be known by the application and hence possible to extract. I could use the Windows Data Protection API to store the credentials, but I might need to support other platforms so I would rather not. Storing the hashed password (same as in the database) on the computer is not safe, since a malicious user with read access to the database could replace the username and hash on the computer with another user's data from the database.

So, my plan is this...

Create user account

  • Generate random salt
  • Hash the initial password twice using argon2id(argon2id(password, salt), salt)
  • Store username, salt and hashed password in the database

User login

  • Read user's salt from the database
  • Calculate hash1 = argon2id(password, salt)
  • Calculate hash2 = argon2id(hash1, salt)
  • Check that hash2 is equal to the hash stored in the database
  • If successful, store hash1 on computer

Restart application

  • Read user's salt from the database
  • Read hash1 from computer
  • Calculate hash2 = argon2id(hash1, salt)
  • Check that hash2 is equal to the hash stored in the database

This way, neither the plaintext password nor the hash used for verification in the database is stored on the computer. But since the general advice regarding encryption and hashing is "don't roll your own", I wonder if there is some better method that I have missed - or if there is some serious drawbacks with my method? (I'm probably overthinking this since the application is for internal use only and the data is not sensitive either - top notch security is not required.)

I do see the problem that the stored username and hash1 can be stolen from the computer but that will be covered by operating system security.

I have read about layered hash shucking but since the inner hash is both salted and using a modern hash algorithm, I don't think that will be a problem.

Is there a problem with reusing the random salt for both the inner and outer hashes?

$\endgroup$
1
  • 1
    $\begingroup$ It seems you are looking to create an authentication framework. This use case is normally solved by storing tokens, not by storing the primary authentication data as that might be used for any subsequent login attempt. $\endgroup$
    – Maarten Bodewes
    Commented Feb 15, 2023 at 10:43

2 Answers 2

2
$\begingroup$

The way this is typically implemented is by storing a token that is issued by the server. The token does not have to have any relationship to the user's credentials. So instead of it being a hash and validating it against the hash-of-hash in the database, there's a whole separate table for tokens that have been issued, their validity period, info about the machine it was issued to, etc. Complicated scenarios can use digital signatures or MACs, but in the simplest case the token can just be a random string.

The benefits to this approach are:

  1. It doesn't impact your normal authentication flow, this is a separate authentication process for tokens.
  2. The tokens can be invalidated by the server for any reason.
  3. It doesn't require cooperation from the client with respect to the validity period.
  4. The server has some ability to detect if the token is used from a different context than it was created in.
$\endgroup$
1
$\begingroup$

I'm not sure how replacing the password itself with a hashed version would do you much better. Are you not still storing a vector of authentication material on the local host, that if compromised, resulted in access to the remote system?

I understand your concept of attempting to prevent attackers from brute-forcing the clear-text password with the original salted password on the host, but I don't see the good in that besides preventing an offline-attack to then be used online at a later date (possibly after the 1-month period that you described initially).

I am not sure of a solution and am newer to cryptography, however I thought it was worth pointing out that you basically just add an extra step to the process, that I believe provides you almost no added security.

This is my thought process:

If hash1 is stored on the computer, it might as well just be the salted original password, because while that could be recovered using a brute-force/dictionary attack, it is still the same idea where even if it is hashed again, it is still a secret that cannot be disclosed. This surrounds the idea that the salt is reused in both hashes, because I think it has to be in your use case.

I'd love to listen to feedback from others, as I am here to learn. Thank you!

$\endgroup$
1
  • $\begingroup$ The main advantage I see of not storing the password in plain text on the computer is that if it is stolen, the adversary could potentially access other (more sensitive) systems if the user is using the same password for different systems. $\endgroup$
    – Anlo
    Commented Feb 16, 2023 at 7:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.