Results 1 to 9 of 9
  1. #1
    Join Date
    May 2008
    Posts
    6

    username/password

    Is it best to store the username and password encrypted or just the password?

  2. #2
    Join Date
    Oct 2002
    Location
    Baghdad, Iraq
    Posts
    697
    I'm assuming you're doing a username/password based security to something like a web app. The problem you're facing is that each user should have some secret token (a password) that authenticates that user.

    Encryption is the wrong tool to use. Symmetric encryption (which is the type you're talking about) is a pair of functions that transforms plaintext P into ciphertext C with a key K, such that E(P, K) = C and D(C, K) = P.

    Here's the problem: if you encrypt your passwords, the attacker only has to get a single key K to decrypt all of them. Encrypting user names is out completely because it just introduces way too many problems.

    The standard mechanism is known as challenge-response, and it enables you to demand a password for a user without ever storing the password on your system or having any key that can expose the password. Now, if the user loses their password you can't retrieve it, but that's not really a problem because you can simply reset it to a completely new password. It's actually a benefit because if someone fools you into resetting the password, the real user will find out when they find they can't log in anymore.

    Challenge response depends on a "one-way" function, examples are MD5 and SHA160. Try to use something more modern than MD5, like SHA256. A one-way function, also known as a "hash" or "digest" function, works like this: Given plaintext P, the function D(P) returns a hash H. P can be any length in bits, but H is always a set number of bits. If D(P) is MD5, H will always be 128 bits. Further, D(P) always returns the same H for the same P, but if P is different by just one bit, H will be completely different.

    Also, let's define a function called concatenation, which is simply stringing two things together. So C("foo", "bar") = "foobar". This is used in conjunction with one-way functions.

    With that background, here's how challenge response works.

    We've got a client C and a server S. The username is U, the password is P.

    Creating a new user or resetting a password: The user enters U and P into C. C generates a random number known as the salt, X, and generates D(C(X, P)). It transmits this to S which stores U, X, D(C(X, P)) in the database. Because D is a one-way function, it is impossible to derive P from this information, but we don't need to.

    Authenticating a user.

    1. The user enters U and P into an authentication form on C.

    2. C sends U to S.

    3. S looks up X, D(C(X, P)) for U. S generates another random number, R, which is known as the challenge. S sends R and X to C.

    4. C calculates D(C(R, D(C(X, P)))) and sends this to S. This is known as the response.

    5. S calculates the same thing C calculated, and compares it with the transmission. Since they both know R and X, if both calculations are the same the user has entered the correct password.

    Now, the salt X might seem superfluous. It's not: remember that D(P) is always the same for any P? Well, some users are lazy and use obvious passwords or use the same password in multiple places. By adding the salt, you ensure that someone who gets hold of your authentication database can't zero in on people who have the same password twice.

  3. #3
    Join Date
    May 2008
    Posts
    6
    Heh, I should have said that I knew I wanted to hash to save you some time. I also know that I want to add salt to whatever is hashed to avoid dictionary attacks. But you lost me after that.

    You said salt is supposed to be a random number. I thought you had to know the salt every time you want to log in. For example, if I store the username and password on the server with a random salt, how am I going to regenerate that salt to see if the passwords match when the user attempts to log in?

    I'm a little confused by the C() in the directions, for example, D(C(X, P)).

  4. #4
    Join Date
    Oct 2002
    Location
    Baghdad, Iraq
    Posts
    697
    C(A, B) just means concatenation, only with binary objects instead of character strings. It doesn't even matter what order, so long as you're consistent.

  5. #5
    Join Date
    Oct 2002
    Location
    Baghdad, Iraq
    Posts
    697
    You said salt is supposed to be a random number. I thought you had to know the salt every time you want to log in.
    The server looks up the salt from the database and sends it to the client along with the challenge. Neither the salt nor the challenge are secrets.

    For example, if I store the username and password on the server with a random salt, how am I going to regenerate that salt to see if the passwords match when the user attempts to log in?
    You don't regenerate the salt, it's stored in the database along with the hash of the password.

  6. #6
    Join Date
    May 2008
    Posts
    6
    So, I store the salt and the hash of the password + the salt on the server.

    When the user logs on the user sends the username and the server gets the salt and sends it to the user and then the user adds the salt and hashes and sends to the server? I don't think I'm understanding this right at all. But I don't see how the user is going to match the hash without the salt.

  7. #7
    Join Date
    Oct 2002
    Location
    Baghdad, Iraq
    Posts
    697
    I suggest you get pencil and paper and go step by step through the algorithm with some invented values.

  8. #8
    Join Date
    May 2008
    Posts
    6
    Ok, I see how it works now. It took me a while to figure it out, but it makes perfect sense. My only question left is: does the server store the challenge until the client sends back the hash with the salt and the challenge or does the client send the challenge back with the hash?

    For example,
    4. C calculates D(C(R, D(C(X, P)))) and sends this to S. This is known as the response.
    5. S calculates the same thing C calculated, and compares it with the transmission. Since they both know R and X, if both calculations are the same the user has entered the correct password.
    I know the server generated the challenge, but since the server is sending it to the client, to me, it seems unnecessary to store it on the server when the client could just send it back. But, you didn't say to send it back so I'm assuming the server should store it. I just want to make sure.

    Thank you for all the help. You have been very helpful.

  9. #9
    Join Date
    Oct 2002
    Location
    Baghdad, Iraq
    Posts
    697
    Quote Originally Posted by _89
    My only question left is: does the server store the challenge until the client sends back the hash with the salt and the challenge or does the client send the challenge back with the hash?
    Yeah, you're optimizing the algorithm to work best with HTTP. The problem is that it opens you up to replay attacks if the same challenge can be sent twice. I'm not sure how hard it is, but if you allow the client to choose their own challenge, they might be able to exploit weaknesses in your hash function. Since you've got to track sessions anyway, it probably makes sense to tie the challenge to a particular session.

    Thank you for all the help. You have been very helpful.
    You're most welcome.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •