1

Currently I'm just fooling around with PHP, but I came across an idea I want to expand on and need to know how secure it is in your opinion, and how I can improve it to make it acceptable for practical use.

This is how I store the passwords in the database:

plain text password -> hash password (I use whirlpool, but any method will practically work)-> shuffle/scramble the hashed password (with the str_shuffle() function).

I store the users password in the database like so, to make sure if the database is compromised, it would make it impossible for the attacker to reverse the broken password hash inside the database. (Because how can you reverse in a sense, random text that use to be a hash? - Although I'm sure you can create a list of possibilities by comparing a list of hashes that share the same chars.)

The way I check if the users password they entered on the login form is correct (compared to the broken hash in the database) is by counting the individual letters+numbers (a-f & 0-9) in both strings/passwords , and see if they match up, and if they do, I assume they're correctly logged in.

And again, I want to know how secure this is in your opinion, and how can I improve it to make it acceptable for practical use. (If possible.) & I would also like to try my best to avoid a "reversible" hash. (i.e the idea of creating my own way of ensuring the passwords match, I want to make it more of an A best guess Assumption, to completely help ensure it will be impossible for an attacker to reverse the passwords in the database.

& Yes I know this is stupid because it most likely causes more security flaws rather then helps fix them. But this is just something I'm fooling around with, and maybe hope to make it practical.


OTHER INFO:

1) Passwords are stored with unique salts (so not 1 account shares the same salt)

2) Password salts are always changing (Each time a Successful Login happens with a users account, it will change the users salt in the database. I do this to change the hash in the datbase, causing a password collision to be less frequent (hopefully) & also to prevent unwanted users from using the same incorrect password multiple times to login (If they manage to come across one, only way to achieve this is by bruteforce or 'guessing' which any login system is vulnerable to).

When I say password collision, I mean the slightest chance that the word "hello" & "blue" share the same exact char count (as I explained, I count the individual chars + numbers, and compare them, to ASSUME its the correct password.)

3) I will also MAYBE keep the first 3chars/numbers of the hashed password unaffectedd by the str_shuffle, to also help ensure the passswords are correct. (By creating 2 checks, 1) check if both strings share the same FIRST 3 CHARS/Numbers & 2) Then compare the count of chars in each string. (Hoping to make password collisions, again, less frequent).

4) Obviously other security measures will be added (i.e max login attempts, captcha , etc.. to help protect against automated bruteforcing, to make it harder for a hacker to find a possible password or the real password.

I have made a successful PoC of this, and it works like a charm, although I have yet to test the PoC against a Dictionary Attack / Brute Force Attack, to see the chances of password collisions. & How frequent they are.

If I stated a lot of 'useless' information, ignore it. I'm just trying my best to explain this reasonably.

4 Answers4

2

This seems terribly ineffective and insecure to me.

Most notably: Collisions. You mentioned that already in Other Info.

Just checking for the count of characters in the hashed & scrambled lets collision probability go through the roof. You enable one password to be also valid for all permutations of its hash. Considering the length of 128 characters in a whirlpool hash, this is a veeery large number.

So, basically, by allowing this, you allow a would-be bruteforcer to check many many thousand passwords at once, by entering a single one.

They will not gain permanent access to the system, since you said you alter the hash after each login, but the probability that they gain access ONCE is increased substantially.

Concerning the altered salt... how do you do that? I can't think of a way unless you apply the salt after hashing instead of before, which is not how a Salt works in hashing.

If you want to make it more secure then just use multiple hash iterations. Store the hashed password and the number of hash iterations. Every time the user logs in hash the hash again, store it, and increase the iteration count. This will change the stored hash sufficiently without introducing too many cryptographic weaknesses.

kasoban
  • 2,107
  • 17
  • 24
  • For the salt thing, when a user correctly logs in, it uses the plain text password (after it checks that its the 'correct' password compared to the one in the database) then generates a new salt for it, and re-hashes it, the shuffles it again. and then stores it back into the database. & Thanks for the comments, I will look into more of what you're saying right now :) . – user3106858 Jan 29 '14 at 09:15
  • 2
    Oohh.. Well, think of the following. I am a bruteforcer and just successfully created a collision randomly. Now my random password just overwrote your original password, because a hash based on my random password is stored in the database. This gives the bruteforcer full permanent access, and shuts out the initial user/password. – kasoban Jan 29 '14 at 09:21
0

Your shuffling scheme will make the password less secure. Comparing the number of instances of letter and numbers after a shuffle increases the chance of two people having the same password value (collision, as you said).

The re-salting is something you could use. Each time the user successfully logs in, you can re-salt the password and save it again. This could be even better if you modified the PHP password procedure to use a hi-res time value, increasing the unique-ness. Essentially you're continuously rotating the salt of the password. You would have to save the clear password, compare its hash to the saved one, re-salt and hash the clear password and save again.

dbone
  • 16
  • 2
0

The output of a cryptographically strong hashing function is for all intents and purposes already pseudo-random. Attempting to add entropy by scrambling it does nothing. It does nothing to make the hash less "reversible", since the only way to "reverse" a hash is by choosing an input, hashing it, comparing it with the hash; that's the same thing you have to do when logging the user in, it's the same thing an attacker has to do, changing the comparison algorithm does not change this basic operation. (As others have pointed out, your weakened comparison algorithm actually aids an attacker.)

The accepted way to deal with this problem is already sufficient:

  1. Make sure your input is unique by salting it with (pseudo) random noise, this forces an attacker to do actual brute force hashing.
  2. Choose a hash that is slow (preferably bcrypt or scrypt, with a high enough cost factor that makes it feasible for you to do once, but infeasible for an attacker to do billions of times), this makes it computationally infeasible for an attacker to brute force a hash in his life time.

If both steps are done correctly, it's already infeasible to "reverse" a hash. No additional mind games needed.

deceze
  • 510,633
  • 85
  • 743
  • 889
0

Don't fiddle around with your idea any longer. It is insecure.

There are only about two ways for password security that provide a sufficient level of resistance against tampering:

  1. Use a hardware security module executing something like HMAC-SHA1. The module is external hardware, the outside world does not know the internal secret (only available by physical access to the module) inside the module, and without that module the generated hashes will never be reconstructed. Being dedicated hardware with a "fast" hashing algorithm makes this a viable solution for lot's of password checks. See http://en.wikipedia.org/wiki/Hash-based_message_authentication_code for details.
  2. Use very slow hashing algorithm. Things like "scrypt" or "bcrypt" will execute very slowly, thus hindering the fast bruteforce scan of list of passwords against a list of known hashes. PHP only has support for "bcrypt" at this time.

You may wonder why you should use external hardware encapsulating a secret. Simple: Anything that is accessible from the machine that is doing the hash can be stolen. Stealing the secret is like using the same salt (or none at all) for all keys: You end up "only" having a very fast hash algorithm with every other component known, and can start bruteforcing passwords right away.

So if there is no dedicated hardware, the only other option is a slow password hash algorithm.

There is a solution for PHP: password_compat is a library that reimplements the PHP password hash API for versions before PHP 5.5. If you are already using 5.5, you simply use these functions.

Sven
  • 69,403
  • 10
  • 107
  • 109