1

Am I right in stating that SCrypt as an algorithm is useful where many passwords are stored in a database, but not against one specific encryption key derived from one password of one user?

For example, let there be a password, a salt, and parameters for the SCrypt algortithm. Let key = SCrypt(password, salt, params). The salt is supposed to be stored with the hash/key itself. If an attacker has a table containing the password, can't he/she brute-force the password given the salt? That defeats most of the purpose of a KDF, as the only goal achieved is an addition of a few seconds in the brute-force process.

Sure, the addition of a few seconds will increase the time needed if many passwords need to be tried, but if the password is an easy password like "ilovesteak", which will not take many tries to guess, instead of seconds to brute-force, it will take hours. But the time taken is still feasible, especially if the data is extremely confidential.

How can I derive an encryption key from a password which makes it mathematically difficult to brute-force derive?

  • 1
    WRT, 'If an attacker has a table containing the password, can't he/she brute-force the password given the salt?' - Yes. The reason that we use a salted hashing function is not to make it more difficult to brute force the password from the hash; it is to thwart the use of [rainbow tables](https://security.stackexchange.com/questions/379/what-are-rainbow-tables-and-how-are-they-used). See https://security.stackexchange.com/questions/211/how-to-securely-hash-passwords for more info. – mti2935 Feb 17 '22 at 01:24

1 Answers1

0

The goal of using a memory-hard hash function like scrypt with a random salt is, generally, to make brute-forcing much more expensive. This has two side effects:

  • First, if the database leaks, it will be expensive to try to crack all the passwords. Because each has a random salt, this is O(M*N) in the number of passwords and guesses. If we had no salt, then guessing would be O(N) in the number of guesses, since we could reuse or precompute guesses.
  • Second, it can make a password which might otherwise be marginal provide a little more security by making it harder to crack. This is due to the nature of the memory hardness, which limits the use of GPUs for cracking and therefore makes each attempt more expensive.

You are correct that if you have one single, weak password, then it is easy to attack, even with a properly salted scrypt. That's because the secret, the password, has low entropy: it comes from a small set of inputs. There is no magical cryptographic technique that can create entropy where it doesn't exist: cryptographic techniques are assumed to be publicly known, and the attacker can always try to use brute force to guess. This is why we generate keys with 128 or more bits of entropy: because it makes brute-force computationally infeasible.

Ultimately, that means that you need your inputs to have reasonable entropy. For many API interfaces, that generally means credentials are pseudorandomly generated and provided to the user instead of the user choosing their own. For websites, this means that we encourage the use of password managers and pseudorandomly generated passwords. If you have to read a password from the user, you may encourage a passphrase by forcing a longer password (e.g., 16 characters or more) and rejecting known weak passwords to make the likelihood of choosing a good password better.

bk2204
  • 8,695
  • 20
  • 19
  • The goal of salting is resistance to precomputation. https://security.stackexchange.com/a/174555/6203 – Royce Williams Feb 17 '22 at 09:58
  • 1
    Right, I think my answer covers that in "since we could reuse or precompute guesses". The first sentence addresses the general use of the use of a memory-hard function in conjunction with a random salt. – bk2204 Feb 17 '22 at 22:00
  • Thanks @bk2204, for your answer. So just one more query; will the system be more secure if I restrict the access to the salt? The real question is, can an attacker easily and feasibly form the end derived key with the right password but the wrong salt? If it not possible, then to make a password-based system more difficult to break into, I can encrypt the salt in many ways and thus make attacking a password a two part effort instead of a single part one, where the salt can, for example, be encrypted by the server or an application, and be decrypted only for authentication. – Neev Penkar Feb 18 '22 at 22:59
  • The salt will be required to reproduce the password. However, the salt is cryptographically assumed not to be secret. If you're using a secret salt, then that's called [a pepper](https://en.wikipedia.org/wiki/Pepper_(cryptography)). You may choose to use both if you like. – bk2204 Feb 19 '22 at 02:58
  • To clarify further: the purpose of a salt is to ensure that two equal passwords for two different users do not produce the same hash, thus revealing one user's password to the other, and to prevent mass precomputation of hashes so that hashes can just be looked up in a database to recover the plaintext (this is what rainbow tables used to do). For these purposes, the salt is only required to be unique, or very likely to be unique - it does not have to be secret at all. This answer may help with broader context: https://security.stackexchange.com/questions/17421/how-to-store-salt/17435#17435 – Polynomial Feb 19 '22 at 06:52
  • The use of a secret salt, or "pepper", only makes sense in a threat model scenario where an attacker can access the location in which the password hashes are stored, but not the location in which the pepper is stored. The most common implementation is a single very long pepper string stored in a config file, applied to all passwords, to make it impossible to crack passwords if a breach was limited to SQL injection. The downside is that it adds implementation complexity, and that can introduce bugs which can weaken security (and there are real-world examples of this happening). – Polynomial Feb 19 '22 at 06:57
  • Example of weakened security from the use of a pepper: `bcrypt(pepper+salt+pass)` with a 32 char pepper, 32 char salt, actually means only the first 8 characters of the password are used for the hash, because the BSD implementation of bcrypt silently truncates inputs to 72 bytes. (side note: use argon2id if you can) – Polynomial Feb 19 '22 at 07:01