Disclaimer: I know about the dangers of rolling your own auth, this example is intended to be used in a demo for various hashing methods.

I wrote this Node.js func to run server side to reinforce why we should not roll our own but use an existing lib (Bcrypt mainly) but I may be undoing my own argument as I cannot see how this can be easily broken.

The only way I can imagine is if the attacker can work out the fixed salt (pepper), perhaps by obtaining a known hashed pw, extracting the random salt (they would need to know the length) and constructing their own rainbow tables to try crack the fixed salt (this is very long and has high entropy).

function checkPw(pw, fullhash) {
    //random one time salt is first 12 chars
    var salt = fullhash.substr(0,12);

    //hashing the full pw, our random salt, the pw and a global fixed salt
    var hashpart = crypto.createHash('sha256').update(salt + pw + process.env.SALT).digest('hex');

    return (hashpart === fullhash.substr(12));

My questions is where is the flaw here? There must be something obvious I am missing?

  • You might get more joy over at Crypto stack exchange - crypto.stackexchange.com – iainpb Sep 14 '17 at 12:14
  • Thanks Iain, I will consider it, however at this point I am reluctant to join another board especially when I know there are some crypto experts on here. – Trickycm Sep 14 '17 at 12:16
  • @allo there are 2 salts though, 1 random, 1 fixed. – Trickycm Sep 14 '17 at 13:08
  • Such a fixed salt is sometimes called pepper, maybe you can find information with this keyword. When you have one dynamic salt, the static one at least cannot hurt. On the other hand its kind of built in into your algorithm, which means it does not honor kerckhoffs principle. – allo Sep 14 '17 at 13:23
  • 1
    Rolling your own auth is far less dangerous than rolling your own crypto, IMO. Storing passwords securely is not overly complicated: use a good hash function, include a random salt (which can be stored with the hashed password), and add a pepper if you want to (which is what your fixed "salt" is more commonly called). The only problem you have is that sha256 isn't intended for passwords (which has already been pointed out in comments). Otherwise, your implementation is following best practices, and I wouldn't reject it out of hand simply because it is your own. – Conor Mancone Sep 14 '17 at 18:59

There are several flaws:

First, I don't see why you would want to "reinforce the use of existing lib (Bcrypt mainly)". Either you use a solid password hashing algorithm (BCrypt is good) or you don't. If you don't, you should not attempt to 'reinforce' it, but switch to a solid algorithm instead.

Second: Your code is, as you say, Javascript. Javascript implies client side hashing. Client side hashing is mood, there are several answers here on security.SE that explain why this is the case. (If you only choose to use Javascript for demo purposes, ignore this point.)

Third: Your 'fixed salt' is typically known as a 'pepper'. A pepper can add security in some very specific cases. A pepper works by being a secret. As a result, a pepper has no benefit whatsoever if used for client side hashing.

Fourth: SHA256 is a general purpose hash. It is designed to be fast. Fast is exactly what you do not want for password hashing.

Fifth: Your final comparison operator is vulnerable to timing attacks.

But is all comes down to the first point: pick a solid password hashing algorithm (BCrypt) and don't attempt to improve upon it.

  • thanks for the detail. The JS I am talking about is Node.js so this is all server side (so a secret pepper, thanks for the correct term). The timing attack point is very relevant though. Never even considered it. I will amend the original question to clarify the Node.js part. Thanks again. – Trickycm Sep 14 '17 at 17:10

If someone steals your database, you can bet they can steal the source code too. So they will know the hashing scheme, the salt size, the salt position. With this information, a dictionary attack can be used against your data.

The main weakness of this function is time. You can build relatively cheap rig to bruteforce billions of combinations per second with a couple GPUs. Using bcrypt you can define how much hashing rounds you will employ. A bcrypt with 1000 rounds is about 1000 times more expensive to crack.

  • Ye totally accept that Bcrypt gives me a lot better protection against brute forcing and is always my choice in production. I thought there may have been something else I was missing from a pure implementation stand point. Thanks very much for taking a look. This info helps. – Trickycm Sep 14 '17 at 12:50

As @ThoriumBR said, if a cracker want to crack the hash, he need to hack into the system first. When a attacker hacked in a system, we can assume he gain full control of it, no matter the database which hold all the password, or the system performing the hashing action. Since attacker gain all the info he need, he just need to start a dictionary attack against the hash set. You add a fixed salt seems it increase the security, but it isn't, because the attacker can simply extract the fixed salt from the server. Furthermore, your hashing method has flaw since it only hash 1 time, which every computer can calculate it very fast in terms of single calculation. You should consider KDF function like PBKDF2, rather add a fixed salt.

  • The fixed salt is not public though and the scenario you describe requires computation of the dynamic prefixed salt length. Also there would be no way to capture a hash over the network as it is never sent that way, this is all server side. Without having the source code it would be very difficult to deconstruct the hash salting structure. – Trickycm Sep 14 '17 at 14:07
  • You just said you have to sent the dynamic hash with the hash which is public. What happened? Full quote on what you said: I have to send the dynamic salt with the hash so it is public, the fixed salt is effectively the secret. – Hartman Sep 14 '17 at 14:10
  • Ye the dynamic salt is public, i.e part of the hash so if you had a hash you would have the dynamic salt. I think you may have misinterpreted public as being client side. Sorry i just mean it is not secret it is bundled with the final hash. – Trickycm Sep 14 '17 at 14:12
  • I don't think I misunderstand. Your words explain it perfectly: if you had a hash you would have the dynamic salt. In other words, if I get the hash, I will get the dynamic salt. It is not related to client, as long as you sent it over a public network, unecrypted, Eve can crack it like what I said. – Hartman Sep 14 '17 at 14:20
  • It is never sent over a network and there are 2 salts, 1 fixed (secret) and 1 dynamic (public i.e included in the final hash). I can categorically say you are misunderstanding my intended meaning. – Trickycm Sep 14 '17 at 14:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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