Hi Ed,

You're right about the salt, it's basically to make it so the same password
will not lead to the same hash, and also to prevent pre-computed dictionary
attacks, where an attacker can make a list of every hash for every possible
password (or a reasonable subset) and then just do a simple lookup. The salt
is not a secret, and should just be stored as the first N characters of the
password on the server. That's the quick answer to your question. For more
info, continue reading.

The problem with your scheme is that the security lies in keeping h(P+S)
secret, but that's what's going to be stored in your password file. So a
compromise of the password file will give an attacker access to the user's
account, because say the hashes in the password file are called C, then all
the attacker has to do is sniff the nonce and then compute h(C,N) and then
they'd have everything required to log in.  You follow?

What has to happen, somehow, is the nonce must be hashed with a secret. The
secret is the unknown for the attacker, but if your password file is
compromised, then the hash of the password+salt is known. So you can't use
the hash of the password+salt as the secret if you want to protect against
the problem of your password file getting compromised. If you're not worried
about the password file being compromised, then you don't need a salt at all
anyways. The important part to figuring out these types of schemes is to
define exactly what the secret is. In your case it's not the password, it's
the hash of the password+salt. And with your system that secret is stored in
plaintext in the password file.

So what you need is a secret that is only known to the user and the server.
That's obvious. You need that secret to be hashed with the nonce in one
operation. That's the hard part. You obviously can't just store the secret
on the server as is, yet the server needs to be able to perform an operation
using the secret. So it sounds like what you need to do is not only hash the
password, but you need to then encrypt that hash to store on the server.
Then when it comes time to authenticate, you decrypt the stored secret,
which gives you the password hash, then have both the user and server hash
that with a nonce, and compare. You follow?

If you're using Windows 2000 or XP, I'd make use of the DPAPI (Data
Protection API) for storing the key used to encrypt/decrypt the password
hashes on the server, or even better, just have the administrator key in the
password whenever the server is started. You can also store the key in the
registry and apply appropriate ACL's. Also, you don't really have to hash
the passwords, though it adds an extra level of security in case the
password file and the encryption keys get compromised, then at least the
attacker won't have the plaintext versions of the people's passwords, in
case they reuse those passwords elsewhere.

So it all depends on what you hope to overcome. If you want the system to
work even in the case of the password file being compromised, yet you still
want the authentication to occur over an insecure channel, then you need to
encrypt the password hashes for storage on the server, then decrypt them
when they are to be verified. Then an attacker with the password file still
needs to figure out how to decrypt the passwords before they are of any use.
If you aren't concerned with the password file being compromised, then you
can just store a hash of a password (salt not really necessary, though
optional and should just be of a fixed length, stored in plaintext prepended
to the hash), in a password file, then have both the client and server hash
a nonce with the hash of the password (again optionally salted, just send
the salt along with the nonce) and then compare on the server. Also, don't
have a TTL for the nonce, just only ever use it once and have a short
timeout for the entire login procedure. If in doubt it's better to just
generate a new nonce than to allow for a tiny window in which a replay
attack could occur. You follow?

If you have any more questions I'd be happy to help. Good luck with your
project.

Jordan Frank
eBusiness-Applications
www.ebusiness-apps.com
[EMAIL PROTECTED]

PS: Don't listen to that Craig fellow. Too many people have a quick read
through Schneier's book and think they're cryptographers. You can read the
RFC on CHAP, but it probably won't help you (it does not discuss storing the
secret on the server). If you really want to, you can of course do what
Craig suggested and implement some complex public-key system, but then you
get into key management problems, your users can only access the system from
one single computer (without going through the hassle of exporting the key
and importing it into the other system), etc... It just sounds like too much
of a hassle, and if password authentication schemes really are flawed (as
Craig is suggesting), well then the world is in trouble because more systems
use them than use public-key cryptosystem schemes.

All opinions stated in this email are my own and do not necessarily reflect
those of my employer, or anyone else for that matter.

----- Original Message -----
From: "Pinto, Ed" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Monday, January 06, 2003 9:50 AM
Subject: Re: [ADVANCED-DOTNET] Salt in PasswordDeriveBytes


| Hey Craig,
| Thanks for the reply.  I guess I should have been more clear.  I agree
that
| channel encryption is important, however, my question is about the
security
| protocol, not about the channel.
|
| I guess I'm somewhat confused about two commonly used terms - salt and
| nonce.  What you refer to as "random salt" I've always thought as a nonce
| ("number used once").  To me, the term salt has always represented a
| randomly generated, but persisted set of bytes that are used to make
| dictionary attacks impractical.  Using my definition of salt, here is my
| question in a little more detail.
|
| Let's say the user creates a password P and the system creates a salt S
and
| hashes the password and the salt creating a userkey K.  The system then
| stores the username U, the userkey K, and the salt S.  Then, for
| authentication:
|
| 1. If the client sends username U
| U
|
| 2. The server creates a nonce N with a short TTL and sends it and the salt
S
| N, S
|
| 3. The client applies hash h to the user's password P, and the salt using
| the PasswordDeriveBytes class, and then hashes this with the nonce
| h(h(P + S), N)
|
| 4. If the nonce's TTL has not expired when the client submits its
response,
| the server then uses the same function to verify that
| h(K, N)
| Matches whatever the client sent (where K = userkey as defined above).
|
| My question is about step 1 and 2.  Is this how the salt is supposed to be
| managed?
|
| Cheers,
| Ed
|
| You can read messages from the Advanced DOTNET archive, unsubscribe from
Advanced DOTNET, or
| subscribe to other DevelopMentor lists at http://discuss.develop.com.

You can read messages from the Advanced DOTNET archive, unsubscribe from Advanced 
DOTNET, or
subscribe to other DevelopMentor lists at http://discuss.develop.com.

Reply via email to