RFC 7636, "Proof Key for Code Exchange by OAuth Public Clients", September 2015Source of RFC: oauth (sec)
Errata ID: 6179
Publication Format(s) : TEXT
Reported By: Dmitry Khlebnikov
Date Reported: 2020-05-18
Section 7.3 says:
7.3. Salting the code_challenge To reduce implementation complexity, salting is not used in the production of the code challenge, as the code verifier contains sufficient entropy to prevent brute-force attacks. Concatenating a publicly known value to a code verifier (containing 256 bits of entropy) and then hashing it with SHA256 to produce a code challenge would not increase the number of attempts necessary to brute force a valid value for code verifier. While the "S256" transformation is like hashing a password, there are important differences. Passwords tend to be relatively low-entropy words that can be hashed offline and the hash looked up in a dictionary. By concatenating a unique though public value to each password prior to hashing, the dictionary space that an attacker needs to search is greatly expanded. Modern graphics processors now allow attackers to calculate hashes in real time faster than they could be looked up from a disk. This eliminates the value of the salt in increasing the complexity of a brute-force attack for even low-entropy passwords.
The section misrepresents the information about "salting" and the whole idea
of "salting" is not applicable to a standalone hash. I suggest to drop the entire
section as irrelevant to the rest of the standard.
For some reason the section implies that "salting" is protecting and increasing
entropy of a single hash, which is not what "salting" is about and is not the
reason for the technique. The section is also making a speculative assumptions
about the low-entropy tendency in password hashes and makes an incorrect
conclusion on the benefits of "salting" for a password hash.
One could argue that the entropy and the complexity required to bruteforce a hash
and a salted hash for the same password (where the same hashing algorithm is
applied) are approximately the same in most cases (or just slightly more
complex for the salted version if the producer of the hash used a non-standard
routine in relation of mixing in the salt, e.g. instead of appending the salt
it inserts in in the middle of the password to be hashed). In any case, that
public data is already known to the attacker and it is just a matter of the
configuration for the bruteforcing tool (such as JohnTheRipper) to incorporate
Just as an illustration: consider an example password ('abc'), an example salt
('123'), and that the hash is generated using a concatinated version of these
two (e.g. HASH('abc123')). Since the salt is included with the hash in plain
text, the bruteforcer would just need to set their tool up with the "^.*123$"
pattern making the salt essentially a string terminator which is not affecting
the bruteforce effort in any way).
More and more people I meet are confused about the problem area the "salting"
technique was invented to address: it is to increase the entropy of a set of
passwords, so the same password would not result in the same hash value, with
the primary goal is to prevent attackers to be able to re-use pre-calculated
hashes (e.g. rainbow hash tables) or, in the early stages of the attack, to
make it impossible to quickly assess what hashes the attacker should focus on
(e.g. when you have 1000 hashes and without salts you can easily spot that
some hashes are the same, which means breaking these one would gain much more
in comparison to unique hashes in the same set).
This being said, I am suggesting to drop section 7.3 completely as irrelevant,
since what we currently have is very confusing and seeds unnecessary and
wrong ideas that "salting" can improve the security of a single hash by itself.