Can you correct my understanding of Argon2? I'm a bit new to the cryptography field (completely new), and could really use your guidance.

Please, correct my understanding, as defined by the following statements. 


The Argon2 Hash Generator has won the Password Hashing Competition, and is therefore believed to be the best solution at the moment for safely hashing passwords. Is is recommended to be used instead of bcrypt or pbkdf2
The Argon2 requires additional configuration, through parallelism factors, memory cost, iterations and hash length in order to be used in the most effective. However, default parameters are usually just fine.
The Argon2 also requires a 'salt' for security reasons - this one is meant to be generated using Cryptographically Secure Pseudo Random Number Generators (CSPRNGs for short), but any reasonably random value can be used here.
Some implementations of the Argon2 (such as this one), allow to secret keys and additional data to the function, but these are optional and are not required for the resulting hash to be secure.
Since any reasonably random value can be used as a salt, the result of another hashing function, such as Blake3, could also be used as a salt.
If I want to store both email hash and password hash securely in a database, for the potential attacker to have as little information about the user as possible, I could:


Store the registration date (RD) of a user
Generate the Argon2 hash of the email address, using the Blake3 hash of the RD as the salt
Generate the Argon2 hash of the password, using the Blake3 hash of the Argon2 hash of the email as the salt

The point above would not compromise the security, offered by the Argon2 hash, and would make it quite difficult for anyone, even those with a direct access to the database and the source code, to figure out what the email and the password of the user actually are - but would make it trivial to verify whether the user's input was correct or not


Any criticism, comments, thoughts, opinions (grounded in facts) - are more than welcome.



Correction: as Marc pointed out, 6.2. doesn't make any sense - it would make it (nearly) impossible to look the email up for a registered user. If we substitute the step 6.2. with a random scrambling of the user's email - such as Fisher-Yates Shuffle, repeated for X iterations - to make it consume time, using a random generator from this function, with a seed number derived from the email once again, would the rest still make sense?
A) Don't hash Email. Store it as plain text or don't store at all.

If hashed, then looking up will be impossible. One would need to iterate through every single record in the database. On average 50% records need to be tested each time. In case there are 1 000 000 users, for every login case the application will need to check on average 500 000 records. Hashing needs to be expensive. Suppose it takes 1s. It means, checking of a single login will take 500 000 s, which is about 6 days. Even for a small database with 1 000 user this will take 500 s = more than 8 minutes to check login every time user logs in. No user will accept it.

B) Store login ID as a plain text, exactly as entered by user, without any transformation and obfuscation.

If you use any transformation, it must produce each time the same result, otherwise you will not be able to look up login in the database. If the result is always the same, then also an attacker will be able to easily generate the same code. Means, not more security, but more obscurity and thus more error prone.

C) Where random data are needed, use random generator, don't add anything else.

The RD is not random. Thus Blake3(RD) is also not random. Thus the salt is not random. Instead, use random generator. Furthermore, adding complexity or making an algorithm more obscure does not make it more secure, not even a little.

Also don't make Email address or any other fixed data a part of the secret. Such data are not really random. Each user has some more or less limited number of such attributes (nobody generates a new Email address every day). That's why such data don't give much entropy. But using them makes the algorithm more obscure and gives a false feeling of security.

D) Try to keep an algorithm as simple as possible.

Think of Kerckhoffs's principle. Adding obscurity does not give any more security. But more obscurity means more complexity in the implementation, which makes implementation more error prone and thus actually less secure.

E) Separate different goals clearly. Don't mix them.

Hashing of secret data (password) is one goal. It seems you want to protect personal data that easily identify a person (Email address). This is another goal. It is not good to mix them. This leads to dependency between them. Trying to reach one goal can lead to problems achieving another goal. In our case, Email should not be a part of secret used for login. Furthermore, if you want to keep Email secret, encrypt it with a password that only user knows (not necessarily the same as login password). But then also your application will not be able to use this Email address, e.g. to send info to restore forgotten password. And if your application can decrypt it, then also an attacker can easily decrypt it. Means, either store it as is, as a plain text, or don't store at all.

F) "The best" doesn't mean "approved".

It is true, that Argon2 has won the competition. But before deciding to use it please consider also following (this happens not so often, but still there are such cases):


Make sure your customer approved using of Argon2 for password hashing. It may be that this customer has some conservative process and Argon2 is not (yet) approved for usage in this organization. May be they still accept PBKDF2 only. Especially some organizations close to the government may have such regulations.
Make sure your customer approved usage of particular library that implements Argon2 for your software platform (depending on what you use - C++, C#, Java, etc.). If not approved, I would not recommend to implement Argon2 by yourself. Instead, use some other algorithm provided by some of the libraries approved by this customer, even if it is PBKDF2, bcrypt or scrypt.