I was reading here on Hashes and Salts and I thought about another method to do user authentication. I need your thoughts on this as I might be overlooking something.


For web application authentication, the general trend is to hash the password appending a random salt, with a strong hash function. The random salt and generated hash gets stored in database. Later, when the user wants to authenticate, the user entered password is hashed again with the stored salt and the generated hash is compared with previously stored hash.

Now about my method:

  1. We store one master secret text (as long as it needs to be) in our database and we use unique salt per user.
  2. Instead of storing password hash, we symmetrically encrypt (hash(master secret + salt)) using user password as key and store this encrypted value in our database.
  3. When user wants to authenticate, this previously stored encrypted value will be decrypted using user password as a key and we will get a hash(master secret + salt). This decrypted hash will be compared with newly calculated hash(master secret + salt)
  4. If user enters a wrong password, the decryption will fail and we will get a wrong hash which will fail to compare against hash(master secret + salt)

In this way we are not storing user password in database in any form (plain text, hash, encrypted). I want to know how this method compares against our usual method of password hashing.

  • 1
    I would at least suggest moving the "master text" to the file system, in case an attacker got hold of your DB. – JimL Jul 26 '13 at 7:50
  • @JimL: As I think more on this, I get a feeling that keeping "master secret" secret wouldn't matter. It just needs to be constant. – anilmwr Jul 26 '13 at 8:03
  • Can (hash + password) be used instead of just password as the encryption key? What about hash(hash + password)? I read that the symmetric encryption's strength depends upon key length in addition to the actual algorithm. This is just an attempt to increase key length as most users use 8-15 character passwords. – anilmwr Jul 26 '13 at 8:12
  • I meant (salt + password) and hash(salt + password) in above comment. – anilmwr Jul 26 '13 at 8:35

You do store the "hashed" password. To be precise, you store some data on the server:

  • A value S (the "salt").
  • The "master secret" M (which cannot be really secret, since the server stores it "as is" somewhere in its entrails).
  • E(h(M||S),K): encryption of the hash of the concatenation of M and S, using key K which is derived more or less directly from the user password.

Given these data elements and a potential password P, it is possible to do some computations which result in a boolean result: P is the correct password, or not. That's normal: the server must be able to verify an incoming password, using what the server "knows" only. But if the server can do it, an attacker who got a copy of the server data can do it too. That's unescapable. The stored data elements cannot be directly used to recompute the password, only to verify a given password, so that's one-way.

This is called password hashing. That there is a so-called "master secret" and that an encryption function is internally used are just red herrings; you are simply making a custom password hashing function.

There can be some value in the "master secret" if you actually manage to keep it "secret". The server must know it in order to operate, so it is not really hidden, but you can arrange for it not to be stored in the database, keeping it out of reach of usual SQL injection attacks. It won't do anything against an attacker who obtained a root shell on your server, though.

Using such a "secret" in a password hashing function is called "peppering" and the normal, cryptographer-approved way of doing it is to make the password hashing function a MAC with the "secret" as key.

See this long answer for a primer on password hashing, its concepts, tools and terminology.


I've understood your concept as follows:-

Master Secret = "ReallyRandomAndSecureStringToUseAsASecret"

**User Registration**
dbPwd = Encrypt((hash(MasterSecret,Unique Salt),Key)
Store dbPwd

**User Login**
Take key as input.
Obtain MasterSecret and Unique Salt from DB.

dbHash = Decrypt(dbPwd,Key)

If, hash(MasterSecret + Unique Salt) == dbHash
    //Valid Login
    // Invalid Login

Points to consider: If a server is compromised, the Master Secret, Unique Salt and the dbPwd will be revealed.

dbHash = Known from deviravtion of hash(MasterSecret,Unique Salt). dbPwd = Known from db.

Now, an attacker could offline bruteforce Decrypt(dbPwd,Key) wherein Key is varied using rules, a wordlist, etc. If the user key is encountered, the decryption will give the dbHash to confirm it.

Therefore, while quite innovative I do not believe that your method will give a security advantage unless you're hoping the obscurity of the mechanism will stop the attacker.



Any system’s security is dependent largely on the knowledge and mindset of the person using it. - Mati Aharoni

1) Your system requires an attacker to solve a symmetric decryption instead of computing a one-way hash. In either case, if the user password is weak, it will be broken.

2) Strength of the symmetric encryption algorithm used.

I believe one-way hashes are computationally more difficult to solve than a symmetric encryption, however this one is a comparison between the exact algorithms used.

Pros: Your method seems to ensure that if the user password is strong, then it will prevent hash collision. Hash collision is responsible (in certain cases) to allow access to an account even through the true password is unknown. Note however, that this comes at the price of your dbPwds being of variable length as opposed to fixed length hashes. This would have to be considered during development. Ref: https://crypto.stackexchange.com/questions/3952/is-it-possible-to-obtain-aes-128-key-from-a-known-ciphertext-plaintext-pair

  • Pardon me if I've got the cryptography wrong, as I said, I'm new to this. :P – Rohan Durve Jul 26 '13 at 8:44

Assuming an attacker has access to the secret, the salt and the encrypted hash value stored in the database, you then have to worry about the strength of your symmetric encryption scheme. Your encryption should be resistant to known-plain text attacks (http://en.wikipedia.org/wiki/Known-plaintext_attack). Currently, AES could be used.

  • I came to think about this method when I read about pre-computed hashes / rainbow tables which hackers use after getting their hands on password databases. – anilmwr Jul 26 '13 at 8:16
  • I would personally not try to enforce your idea because you could easily try to brute force it and AES will be quite fast to compute so the brute force will be rather easy/fast – someone Jul 26 '13 at 8:24
  • If I use hash(password) as encryption key, will it be easy to brute force? – anilmwr Jul 26 '13 at 8:38
  • 1
    Yes. You will still iterate over the passwords, the computation of the hash will be rather fast, then it's the same as before. – someone Jul 26 '13 at 8:45

If the attacker knows about the encryption/hashing algorithm you are using, which he can obtain from the source code, he can brute force as usual. First decrypt with the key he's testing, then compare the hashes.

Note that this will alter the hashing collision rate.

I would simply add some pepper to the hash instead - it would be more predictable for you and about as easy to exploit. Just try to not fit in to any of the common ones, such as the ones supported by oclhashcat.

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.