Hashing algorithm needed

Nicolas Williams Nicolas.Williams at oracle.com
Wed Sep 8 13:21:01 EDT 2010


On Wed, Sep 08, 2010 at 05:45:26PM +0200, flj at mail.dnttm.ro wrote:
> We do a web app with an Ajax-based client. Anybody can download the
> client and open the app, only, the first thing the app does is ask for
> login.
> 
> The login doesn't happen using form submission, nor does it happen via
> a known, standard http mechanism.
> 
> What we do is ask the user for some login information, build a hash
> out of it, then send it to the server and have it verified. If it
> checks out, a session ID is generated and returned to the client.
> Afterwards, only requests accompanied by this session ID are answered
> by the server.

I understand why you're doing this, but it's not really any better than
sending the password to the server in the first place via a POST from an
HTML form (where the GET and POST of the form happen over HTTPS).  The
reason there's no real difference is that the script comes from the
server, so it could do anything at all (and besides, you'll end up with
a password equivalent at some point if all you do is hash the password,
but read on).

And since you'd still be teaching your users to type passwords into web
page elements, you'd still leave your users susceptible to phishing.

Still, if this is what really you want, then I recommend that you use
SCRAM (RFC5802).  SCRAM uses HMAC-SHA-1.  You can find implementations
of SHA-1 in JavaScript; implementing SCRAM given a JavaScript SHA-1
implementation isn't hard.

Note that if mechanisms like SCRAM were provided by the browser, then
it'd safe (indeed, good!) to use them.  Implementing them in a server-
provided script doesn't provide anywhere near as much security as
implementing them natively in the browser (or in a browser plug-in/
add-on).

If you can afford to develop a browser add-on, then I recommend you
implement SCRAM there.  The key is to make it possible for users to
distinguish web page elements from UI elements of the browser/ add-on --
this is hard.

> What we need is a hashing algorithm that:
> - should not generate the same hash every time - i.e. should includen something random elements

We calls those random elements "nonces".  SCRAM has those.  Browsers
provide a random() method.

> - should require little code to generate

SCRAM is rather simple.

> - should allow verification of whether two hashes stem from the same
> login data, without having access to the actual login data

I'm not sure what you mean here.  I think you mean that the verifier
shouldn't be the password nor a password equivalent, in which case
you're completely correct.  SCRAM has that, though the server obtains
enough information, the first time that the user authenticates, to keep
a password equivalent for later use.  Also, SCRAM is susceptible to
off-line password dictionary attacks.  SCRAM is best used over TLS
(HTTPS), with channel binding (see below), to defeat passive attacks and
to make MITM attacks harder to mount without the user noticing.

> We need to implement the hashing algorithm in Javascript and the
> verification algorithm in Java, and it needs to execute reasonably
> fast, that's why it has to require little code. None of us is really
> into cryptography, so the best thing we could think of was asking for
> advice from people who grok the domain.

"Little code" does not imply "fast".  Nor does "much code" imply "slow".
If you don't understand this then you have bigger problems than not
being into cryptography.  You should want "little code" so that
development and maintenance are cheap, not so it runs fast.

> The idea is the following: we don't want to secure the connection, we
> just want to prevent unauthenticated/unauthorized requests. Therefore,

You should definitely want to secure the connection.  If you don't then
your users will be subject to MITM attacks.  (But then, your users will
be vulnerable to phishing attacks anyways, since they'll be used to
typing passwords into spoofable web page elements.)

> we only send a hash over the wire and store it in the database when
> the user changes his password, and only send different hashes when the
> user authenticates later on. On the server, we just verify that the
> stored hash and the received hash match, when an authentication
> request arrives. Cleartext passwords aren't stored anyway, and don't
> ever travel over the wire.
> 
> However, we could not imagine a reasonable algorithm for what we need
> until now, and didn't find anything prefabricated on the web.
> Therefore we ask for help.

Well, you did the right thing in coming to such a list.  You should have
done more reasearch, but it's not a big deal that you didn't, because as
you can see, the real problem is that we don't have a good solution for
you (that is, the browsers don't provide what you really need).

> br,
> 
> flj
> 
> PS: reusing the session ID is of course a security risk, since it
> could allow session hijacking. We're aware of this, but don't intend
> to do anything about it other than warn customers/users. Since it's a
> web application, its client code is open, and anybody being able to
> watch the connection can deduce whatever is needed to hijack the
> session, no matter what algorithm is used, unless the connection is
> encrypted right from the start. Connection security is however outside
> the scope of the web application. We can't encrypt communication in
> Javascript for efficiency reasons, it has to be done in a lower layer
> (VPN or SSL, for example). It may in theory work using a preshared
> key, but it's not reasonable to believe that the application users
> will be able to cope with such a mechanism.

I don't understand: why not use HTTPS [with server certs]?  Granted,
you'd still depend on a "PKI" with so many root CAs as to be nearly
useless.  But even so, HTTPS is much better than nothing.  And yes, TLS
(SSL) is at a lower layer, but that's not a real problem.  Moreover,
SCRAM provides for "channel binding", which allows you to bind the TLS
channel into the SCRAM authentication, which in turn helps the weak PKI
situation.

Nico
-- 

---------------------------------------------------------------------
The Cryptography Mailing List
Unsubscribe by sending "unsubscribe cryptography" to majordomo at metzdowd.com



More information about the cryptography mailing list