2

I've written a Go server with custom binary websocket protocol, and a Dart client. User authentication on the server employs scrypt and the recommended parameters N=16384, r=8, p=1 (with salt of length 16 and generated key length of 64), my i7 desktop takes maybe a second or two to crank through authentication on the server side. That's compared to practically instant, say, SHA-512 authentication.

I had trouble finding scrypt implementations for Dart and while this one works, generating the same hash with the same parameters in a browser (Firefox) takes too long to practically complete. I can get it down to a handful of seconds on the same machine using N=1024 and r<=8 but if I settle on that for compatibility, on the server side, the authentication time is for practical purposes instant again.

Scrypt is great on the server side but I'm wondering if its practical for a browser client. Admittedly I haven't seen any/many examples of people using scrypt for browser authentication. Should I persevere and tackle the performance (e.g. maybe using other javascript libraries from dart), or is this a basic limitation at the moment? How low can you wind down the scrypt parameters before you may as well just use more widely available, optimised crypto hashing algos such as SHA?

rino
  • 491
  • 5
  • 12
  • I may not be understanding your use case... but why are you doing password authentication in the browser? And what hash are you checking against? – Greg Mar 25 '14 at 17:08
  • 2
    Password hashing in the browser is generally a bad idea, because, as you've noted, JavaScript cryptography is slow, but attackers will have access to native code. – ntoskrnl Mar 25 '14 at 20:49
  • So the idea is for the user to enter their password in the browser, which sends the hash to the server for comparison. How is https more secure? – rino Mar 26 '14 at 01:29
  • Are passwords typically sent as plaintext over https for server authentication? – rino Mar 26 '14 at 01:35
  • Ok so having looked a bit more into this, it looks like yes "plaintext" over SSL is the usual practice, but of course its not plain text, its encrypted. Since I don't have a spare lunch break to reinvent the internet, and my app doesn't require extra special security, I'll go with that. Plus it simplifies the server protocol. I will note for the record, that if/when I do require extra security for another app, I would probably go with addition of a shared secret via a side channel (such as mail or sms but not email). I'd be interested to hear other thoughts on this. – rino Mar 26 '14 at 04:51
  • @ntoskrnl: But a single server serves many clients at the same time, which might offset it. Unfortunately, the clients very a lot and you can't count on V8 engine running on Core i7, when others run IE6 on 80386. But there are [scrypt implementations in Javascript](http://stackoverflow.com/questions/7617169), so it might make sense. – maaartinus Apr 25 '14 at 00:53
  • the slower hashing executes, the harder it is to reverse-engineer. – dandavis Apr 25 '14 at 19:27

2 Answers2

0

Use HTTPS. If you're hashing the password in the browser and then sending the hash to the server for comparison, what's to prevent an attacker from simply sniffing the hashed password and hijacking the session by sending the same hash himself?

Even if you come up with an encryption scheme to prevent that, the attacker could simply inject an additional <script> tag with a keylogger via a MITM attack to steal the password before it's encrypted.

Basically no matter how you cut it, you have to use HTTPS to ensure that your communications are not sniffable and no MITM attack has taken place. And once your connection is already secured over HTTPS, which is encrypted with a (minimum) 128-bit key and would take longer than the known age of the universe to crack, you might as well just use the HTTPS connection to send your password and doing additional encryption of the password client-side is probably not necessary.

James Duffy
  • 1,387
  • 8
  • 16
  • Unfortunately, the question doesn't state it (mine is only the bounty, not the question), but I've never thought about not using HTTPS. I'm curious if offloading the password-based key derivation overhead to the client makes any sense. – maaartinus Apr 28 '14 at 18:51
  • 2
    You'll still need to hash again on the server, otherwise getting read access to the DB will give the attacker everything he needs to log in as any user. But if you're asking strictly about performance benefits, I think security-wise a slow-hash on the client followed by a quick-hash on the server would be solid. But UX-wise, I don't know how well scrypt runs on my mom's iPhone ;) – James Duffy Apr 29 '14 at 00:41
0

@maaartinus ...

I've never thought about not using HTTPS. I'm curious if offloading the password-based key derivation overhead to the client makes any sense.

If I may, I can come at this problem from non-Web direction and come back to the browser-use case. Way back when, I worked with EFT*POS security standards and working with secure communications for financial transactions. For example; the credit-card machine in the supermarket. Just establish my grounding on this topic. That said, I think the original question HAS be covered comprehensively. I decided to add a comment to enrich the conversation on this area (it is quite topical).

The procedure is about the a conversation between the terminal (iPhone, smartphone, browser, etc). Premise: you naturally don't want anyone sniffing your username/password pairing. Assume your typical web page or login screen at work. Over the Intranet, LAN, WAN and VPN what every you type is dispatched from your keyboard to the host. These links may already be encrypted these days. The WWW web on the Internet has two main options: HTTP (clear text) and HTTPS (encrypted) via the browser. If we just stick with the (username, password) pair.

Your terminal (such as browser or mobile) needs to be "trusted" by the host (server, phone company, etc).

There's a lot of standard stuff you can (should do) first; and get creative from there-on. Think of it as a pyramid. On the bottom are things you can do on your PC. That's the base of the pyramid. And there's loads of good information about that (e.g. Electronic Frontier Foundation, EFF), it is about protecting yourself, your data (intangible property) and your rights.

That said here are a few points to consider:

  • Everything sent via HTTP is clear-text. It can be read and copied.
    • A hash sent over clear-text can be decoded to get the password. It is just maths.
    • Even if you use scrypt or another method the hash is decodable -- Given enough time.
    • If you're on the web, any hash implemented in the browser (terminal/client), is transparent to anyone who can load the web page and javascript code [pointed out by ntoskrnl above.

HTTPS on the other hand, sends Everything-as-a-hash. In addition the hash used is negotiated is unique to the conversation and agreed at session-completion time. It is a slightly 'better-er' hash over the whole-of-the-Message.

The main thing making it better-er in the first instance, is the negotiation. The idea overall is that message hashes are based on a key only known to both end-points.

Once again that can be cracked if you have enough time, etc. The main thing making this challenging is establishing the to-and-fro for the negotiations.

Let's back-up a little and consider cryptography. The notion is to hide the message in a way that permits the message to be revealed. Think of this a as lock and key, where the door is the procedure/algorithm and your message is the contents of the room.

HTTPS works to separate the lock from the key in a pragmatic fashion, in time and via process.

Whatever is done in the HTTPS room, stays in the HTTPS-room. You must have the key to enter, poke about and do unwanted stuff. Imho, any extra security should be ONLY considered within a HTTPS space.

There are methods to improve on that foundation. I think of security like a pyramid. about 4 or 5 layers above the base considerations like the transport protocol.

Such options include, ...

  • SMS authentication number to your phone.
  • Something like a dongle or personalised ID-key.
  • An physical message like an s-mail or e-mail with an authentication Number.
  • anything you come up with.

In summary, if your need say make it safe; there are many things that can be accomplished. If you can't use HTTPS, hashing password(s) locally needs to be managed extremely carefully. Hashes have vulnerabilities. When you are not using HTTPS, anything you can do in the browser is like wet-rice-paper trying to stave-off a sword.

Community
  • 1
  • 1
will
  • 4,799
  • 8
  • 54
  • 90