> It should be ok to reuse passwords at different sites - provided that the passwords are never exposed to those sites.
> To cryptographers, the phrase “prove you know something secret without exposing it” instantly suggests “use asymmetric cryptography.”
No, wrong, stop right there!
The phrase "prove you know something secret without exposing it" instantly suggests that you should figure out what "exposing" means before you try to design a protocol. If I'm a user reusing a password between two sites, then it's unavoidable that either site can try to brute-force my password. However, it would be rather nice if an attacker who hasn't compromised either site can't brute-force my password without interacting with one of the servers for every single guess.
That property is achievable using well-understood techniques, and this blind use of asymmetric cryptography fails to achieve this goal and is unnecessarily complicated (what's the PRNG for?). The primitive you want is an "augmented PAKE". The IRTF CFGR is very slowly working on standardizing one, but in the mean time there are several high-quality augmented PAKEs out there.
Also, note that I said "primitive". A strong primitive does not automatically make a good protocol. CBCrypt's docs say "Keypair is ECDH 256, derived from SeededPRNG". This raises all kinds of warning bells: while there are perfectly good protocols based on ECDH, ECDH by itself just gives an /unauthenticated/ session key, and from a 30-second look at the code, CBCrypt appears to be trivially vulnerable to a replay attack in which a malicious server A convinces a standard client to give it a valid authenticator for a session to a different server B.
ECDH by itself just gives an /unauthenticated/ session key, and from a 30-second look at the code, CBCrypt appears to be trivially vulnerable to a replay attack in which a malicious server A convinces a standard client to give it a valid authenticator for a session to a different server B.
Nice catch! This looks like a trivial (and thus educationally useful) instance of an unknown keyshare attack.
Take a closer look. The server has a copy of the client's public key on record before the authentication session begins. The server needs to authenticate the client. The server generates an ephemeral ECDH keypair. Now if an attacker manipulates the challenge or key sent to the client, the attacker has neither the server's private ephemeral key, nor the client's private key. So the attacker cannot provide a valid challenge response to the server. The worst the attacker might do is to generate a new ephemeral ECDH keypair and send that to the client instead of the keypair that the server generated - in which case the challenge response would be useless.
Also, "prove you know something secret without exposing it" instantly suggests Zero Knowledge Proofs. That is precisely the problem they solve, and it's a problem orthogonal to encryption.
If you don't know what the PRNG (DRBG more appropriately) is for, you didn't watch the tech video. An asymmetric key generation algorithm can't work from a fixed length seed. You need to stretch the seed to an arbitrary length, because the asymmetric key generator requires a random stream.
Your 30-second look at the code needs more than 30 seconds. If a client connects to malicious server A, the private key it would use for that connection is different from the private key it would use on server B. So malicious server A cannot replay an authentication session on a different server.
If you don't know what the PRNG (DRBG more appropriately) is for, you didn't watch the tech video.
Video is not suited for technical details.
It's not easy to quote / excerpt, to quickly refer back to previous (or later) parts, to take more time over parts that need it, etc; not the way text is.
My default reaction to "you'll understand if you just watch the video", is that someone is peddling bullshit and doesn't want me thinking too deeply.
More typically you would use a KDF and simply request the number of bytes that you require directly from there.
Note, however, PBKDF2 has a bug where each additional block of output bytes is recomputed independently, which means the work factor (iteration count of the underlying hash algorithm) is applied separately for each block of output generated. So if you ask for, say, 1,000,000 iterations of PBKDF2-HMAC-SHA256 with 64 bytes of output, you are actually running two separate independent runs of 1,000,000 HMAC-SHA512 under the hood. This allows attackers to derive the output block-by-block instead of having to compute all or nothing, which can increase cracking speed in some cases (see 1Password writeup [1])
More simply, you can use a hash/KDF to produce a single block of seed with all your desired work factor imputed into that one value, and then stretch the seed simply as: for 1..n { hash(seed || n) } to get however many bytes you need to produce your privKey. In other words, 1,000,000 iterations of work for the seed, and a single iteration of work for each final block -- effectively all or nothing.
This will let you reduce the number of primitives to the single hash function you choose, which personally I think is much cleaner than introducing a whole PRNG into the mix.
> An asymmetric key generation algorithm can't work from a fixed length seed. You need to stretch the seed to an arbitrary length, because the asymmetric key generator requires a random stream.
That may or may not be true for traditional DH. For ECDH it's false. A Curve25519 ECDH private key, for example, is quite literally a handful of random bits. (Depending on how you look at it, it's a 256-bit number with some fixed bits or just 252-ish bits. I say "ish" because I don't remember the exact number of fixed bits off the top of my head.)
Edit: Fixed bogus EdDSA reference. Also, I just looked it up. A Curve25519 private key (http://cr.yp.to/ecdh.html) indeed requires exactly 252 random bits (or the 252-bit output of a secure KDF).
> ECDH by itself just gives an /unauthenticated/ session key, and from a 30-second look at the code, CBCrypt appears to be trivially vulnerable to a replay attack in which a malicious server A convinces a standard client to give it a valid authenticator for a session to a different server B.
From looking at their tests and the PowerPoint file in their repo, they mention confirming that the hostname provided by the server in the challenge matches the SSL Certificate. Asking as someone who knows very little about crypto, under the assumption that they validate the hostname and are using TLS would it still be vulnerable to a replay attack?
That's a good question. Are they validating the SSL certificate? Are they willing to predicate the security of the protocol on the soundness of SSL certificate validation? Are they willing to assume that the malicious server and the attacked server have different host names or aren't covered by the same wildcard certificate?
All of these seem like pointless assumptions to have to make when a better protocol wouldn't have this problem in the first place.
In any case, I'm having a little bit of trouble understanding why this thing is useful at all. It helps against an attacker that compromises a server but isn't willing to inject malicious code into the JavaScript served up by the attacker, and attackers who want to target everyone without being detected might actually have that limitation, but more targeted attackers will just modify the JavaScript (unless they have some other deployment scenario in mind).
(Minor correction to my first post: I didn't actually mean "replay attack" -- I meant "relay attack". Whoops, silly typo. Although, now that I think about it, they might be vulnerable to replay attacks, too -- I make no effort to check for that.)
You say that as if existing authentication mechanism aren't predicated on the soundness of SSL certificate validation.
I'm not saying it's right, but as people keep reminding me there's a lot of grey area between 'bad' and 'perfect' and most of the time we don't get anywhere near perfect. 'Better' would be something for a lot of people.
When the SRP code was going around people kept saying "Hey use the javascript library" and for reasons similar to yours I said, "No thanks, when will the browsers support it?"
Because if we're going to use keypairs for authentication, it really should be integrated into the user agent, where it's extremely hard (and hopefully impossible most days) to inject code.
Ad networks get hacked all the time. Probably better than half the sites I visit will pop up a login prompt over the top of the ads, which means somewhere I'm logging in, an ad could very well be trying to get my credentials, and it only takes once for the UA to fail to prevent it and I'm in hot water.
PAKE only authenticates the password and generates a random session key. It doesn't enable the user to encrypt their data for a later session.
If you don't know what the PRNG is for, perhaps a cursory 30 second lookover and then crap all over wasn't enough. ;-) Watch the 9 minute Tech Video, which explains, the asymmetric key generator can't use a fixed length seed; it needs to be a random stream. Also, there's a challenge/response which can only be answered by knowledge of the client's private key, so your comment about the replay attack (I think you meant relay attack) is also incorrect - whichever you actually meant, you're wrong either way.
> PAKE only authenticates the password and generates a random session key. It doesn't enable the user to encrypt their data for a later session.
PAKE can be used to construct all kinds of things. You can generate a key for one session, you can generate a persistent key, you can run a PAKE to authenticate an existing session, etc.
While true, the risk of exposure is significantly smaller if the derived key is different for every site.
The algo can work by the site sending the user their personal salt. The algo will then encrypt the password, use the salt, and send the derived key.
This DOES remove the burden on the user of trusting every site with their password. The problem is quickly the password is only but one of a lot of data hackers look for.
That's not necessarily true; If it can generate multiple outputs for the same input, it could mean that the derivation function exposes something about the secret in the degree or nature of the variation.
So essentially this is a really convoluted way of concatenating username, password, and domain then running scrypt() on it, and sending that to the server as the password instead of the raw password itself?
I actually read the Github page for this, and glanced over the C#. There's no realistic example of how this would work in practice, and I have unanswered questions. This would legitimately solve some phishing scenarios and MIGHT slightly mitigate password reuse scenarios (since they know username + domain, they now need to spend time cracking scrypt() on the password). The arguments that it helps user privacy (NSA something something) are tin foil hat wearing jibberish.
Overall: Meh. If they're serious about this, they need more than a vague proposal.
PS - And a password manager solves all of the named issues with less complexity in my opinion.
Before submitting passwords to a website, they're replaced with a hashed version which incorporates the domain, so passwords are unique to each domain. (The hash isn't anything fancy, so it could definitely be modernized with scrypt or bcrypt or whatever is fashionable.)
I've used it for years and it always works well, apart from the sites that claim my password is too long. It requires no support from the website, just a simple browser extension.
What happens if your password is leaked? It seems to generate the same hash every time, so you would have to change the site password. And if you have to start remembering "Well my password for every site is 'pumpkin' EXCEPT for Wordpress, where my site password is 'bagel'," that list is only going to grow with time as websites inevitably get hacked. So once you've got five or so site-specific passwords, how is it any better than the password memory problem this was originally trying to solve?
I thought about using pwgen locally with a combination of domain, username and password as a hashed seed. But like you mentioned, trying to remember how often i had to change the password (or had restrictions applied only at a particular site, which are pretty ridicules sometimes) makes this not really a worthwhile solution. Albeit this, its not completely useless. If you have specific rules how to create new passwords (a counter for example) and to circumvent specific restrictions, one could iterate through the possibilities rather quickly. One thing that's unbeatable about this solution is that no password store is needed and so none could be lost, which drove my initial thought to this.
I don't hate the idea, but I could never use this while so many sites still have dumb validation rules. It would drive me crazy if I had to remember what sites this didn't work with.
Their generation isn't great. They should tweak the resulting password to ensure that it passes most common tests. I think I would enforce
- 10 characters
- at least one punctuation
- at least one digit
- at least one upper case
- at least one lower case
By coercing the password to have this form you're losing a trivial amount of entropy, but you'll pass the vast majority of password policies.
Also add a nonce to the password generation (1, 2, 3, 4) so that you can change it if needed or required. No need to remember the nonce, just try a few until you can login.
I don't remember where off the top of my head, but I'm pretty sure I've seen sites that had a "no punctuation in passwords" rule. I think at least one of them was a bank.
Nespresso is one that immediately comes to mind as it's the most recent I've encountered besides my bank. I went to order some pods for my mum as a gift only to discover that their password restrictions were not only draconian but stupid. The moment a site prohibits punctuation (especially single quotes as they did) is the moment I suspect they're storing passwords in plain text.
It's not directly related, but I'm reminded of this Hall of Shame I stumbled upon from some HN comment a few weeks ago: http://plaintextoffenders.com/
Also, some sites have things like capital letter cannot be the first character. Punctuation can't follow a digit. At most 8 characters... The list goes on.
See my other comment in this subthread about my own version of the deterministic password generator concept. It allows passwords to have site-specific rules for how they're generated and also allows rotating individual site passwords.
In particular, the fact that you type your password into the password field means that failing to invoke PwdHash means you either register with your raw password (making it worse than useless) or just leak your raw password with failed login attempts.
The password manager model (e.g. LastPass) is clearly superior in my opinion because the user doesn't know their passwords. Largely the only way to input your password is the correct way. Also determining the password for one site provides no information for others (assuming you're random generating the passwords). For PwdHash, if you crack the password you have a lot of information for breaking all the user's other accounts (because presumably they're reusing the same base password).
On the other hand, the odds you'll be the victim of such a targeted attack are presumably pretty low. This at least gets you out of the category of "low-hanging fruit" for an attacker.
I've been actually using a similar solution for my own passwords, having built a small utility myself: https://github.com/alexandru/parolamea ; it works by doing an HMAC+SHA256 between an easily rememberable service identifier (like the domain) and the secret master password and then I'm converting that to base 64.
Using SHA is of course discouraged, because compared to bcrypt the collision attack can be parallelized on top of GPUs and you can try tens of billions of combinations or more on top of commodity hardware. But here's the gist - with a good salt, the complexity of finding collisions is about 2^256. Basically without knowing the salt, you're shit out of luck, because all the PC or GPU power in the world cannot crack 2^256. You can't use rainbow tables either and there are no shortcuts discovered for SHA-256, like you've got for MD5. And then you've got things like bcrypt, an 11 years old algorithms that can't be parallelized over GPUs and that's still unbreakable.
I disagree with you. This doesn't just slightly mitigate password reuse. It actually solves it.
And for me it's way better than a password manager because (a) it isn't a single point of failure like LastPass, (b) you don't have to trust a proprietary binary blob like 1Password, (c) you don't run into the risk of losing access, as everything is in your head, (d) when one of your passwords is compromised, you have the incentive to change the master passwords which will trigger a change of all the passwords, everywhere and (e) best of all it's free.
I've been using something similar of my own making, and I've been meaning to clean it up and publish it at some point. Since I have enough side projects going that I have no idea when that will be, I'll share a couple features of mine that I think make it unique and which I think should be incorporated into the others.
The general concept I stole from somewhere else -- you've got a stored list of sites and when you type your master password in a field, each site in the list then gets a "copy password" button based on the site name + master password. But this isn't quite flexible enough for general use, so I added some features:
First, each site has a 'version' field which becomes just another piece of data input to the hash. This makes it so you can rotate passwords on a particular site without changing your master password: increment this number and you get a whole new password.
Second, each site has a password 'scheme' which allows for disparate password requirements on different sites. The underlying generation algorithm is the same, but rather than converting the hash output to a base64 number and using it directly, the hash output is used to deterministically select characters based on the rule set. Roughly, each scheme has an arbitrary number of character "classes" that may be included (e.g. "numbers", "letters", and "symbols") and each scheme may specify a minimum number of characters from each class (a typical rule being that that min=1 for numbers and symbols). So the class-specific minimums are satisfied, then the rest of the characters are selected from all classes equally, then a few more bytes of hash are consumed to deterministically change the order of the selected chars (otherwise you'd always end up with your minimum two special characters at the front, for example, which technically weakens the password). Each site also can have a distinct password length setting. Currently I only have three or four different "schemes" defined and haven't had the need to add one in a while so they're all hardcoded, but one could easily imagine having a "password scheme editor" which lets you define new ones with a few primitive rule types.
And third, each site has a "last changed" date which helps me keep on top of which site passwords haven't been rotated in a while. If you change your master password every time you need to roll one site's password, this probably isn't an issue for you, but I definitely prefer to avoid the ritual of changing passwords on every site I use at once.
My impetus for all the password scheme complexity is that I found that more straightforward password generators simply don't work on all sites, and I hated having exceptions. The site where I pay my electric bill, for example, doesn't allow exclamation points in passwords, and they must be between 6 and 8 characters. Lame to be sure, but I really have no choice but to go along, so my password generator must too.
All that said about my password generator, I think this is a fundamentally different approach to the problem and I think the cbcrypt approach is ultimately more interesting if we can get it incorporated into browsers. I've long thought we should expose some sort of modified SSH-agent functionality to the browser JS API so sites could do public key auth for login (with the appropriate user prompting, of course -- just allowing websites unfettered access to your SSH agent would obviously be a terrible idea).
I don't think that's right. There's a keypair and although the text of the article doesn't say it, I see evidence of a Challenge-Response in the source code (they have files named Challenge and ChallengeResponse).
I used it for years (for unimportant things) before switching to a password manager. It's technically not secure against a malicious site that sniffs for the existence of the bookmarklet window, but it's a good way to get slightly better security on sites you'd other reuse the same password for.
Password manager still have weaknesses. For one, you are still sending the private key to the server. This may happen in plaintext, or the password may not be encrypted/protected properly server-side. And it requires you to keep a database of passwords that you need to synchronize between all of your devices.
Using something like public key authentication allows you to use the same public key for every website. Your password management software and synchronization strategies are both suddenly a lot simpler. Server-side mistakes are less problematic to the end user.
It removes several points of failure, and has greater flexibility against user, server, and developer mistakes.
"CBCrypt deterministically generates a public/private keypair unique to each specific user, on a specific server, using a specific password. Any variation of any of these factors results in an entirely different and unrelated keypair."
If it deterministically generates a keypair from a password, then attacker acquiring a public key is equivalent to acquiring a password hash — the public key now becomes a verifier.
"The worst attack a malicious server can mount is an expensive brute force attack, attempting to overpower the rate-limiting function and eventually guess a password that recreates the exposed public key."
Almost the same result as if the server just stored an scrypt hash, but more complicated, and without a random salt. The solution for the problem just makes it worse.
It's not the same. The main point of asymmetric ciphers is that it's a very good way to prove I know something without ever revealing the thing I know.
Instead of sending the public key every time, the server sends a challenge, which only the private key holder can answer. This is a pretty basic usage of keypairs and an extremely brief perusal of their source code suggests to me they've thought of it.
So no, the public key is not the password, unlike hash based systems which do suffer from the problem you're concerned about. The hash IS in fact now your password in those systems.
Yes, there's a challenge/response scheme (like in SRP), so the communication part is slightly improved, but what I'm talking about is that the server stores public key, and this public key is deterministically derived from password, thus stealing the database of public keys from the server is equal to stealing the database of password hashes (like in SRP).
I haven't read their code or critiques of it, so I can't say if that's the case for this algorithm.
But for this class of algorithms, that doesn't have to be the case. Starting with a cryptographic hash could keep the key from being reversed to the input. There are probably other things that could help as well, like maybe not using the password in the public key at all.
How exactly does "starting with a cryptographic hash" solve this problem?
Remember, the attack is: start with "aardvark", run the deterministic key-generation process, hash, scrypt, elliptic curve and all, and check to see if you get the same result. If you don't, move on to "apple", then "ataxia" and so on.
The attacker has every piece of information in the system except the password string, which they can substitute with a dictionary.
It's not a question of reversing the hash, it's a question of what is the 'password validator' and what are the inputs to the algorithm which get you from 'candidate password' to 'compare result to the password validator and return true or false'.
Can you explain in more detail why you believe the public key "isn't the password" the way it is in a "hash based system"? I don't think this is true, but I'm not totally clear on what you're arguing.
Hey I got pulled away from this conversation and didn't continue.
In most systems where the server never sees your password, they store a hash that is generated from the password.
Then the login code on the client takes the password, performs the same operation and then sends either that same hash to the server, or one that's simple to calculate from it.
So if I steal your password file, I can log in as everybody without even knowing what their passwords are. I just change the code in the client to skip the hash generation part of the authentication algorithm and use the one I supply.
The idea with asymmetric ciphers (at least the ones that interest us) is that one party HAS to know the secret, and the other has no way to get it.
I think you're saying that this system is better because, since it uses public key pairs, an attacker who steals the password file doesn't know enough to log in as a different user.
Leaving aside that an attacker who steals your password file has probably mooted login security altogether, the attacker in this system seems to have exactly the same leverage as an attacker who steals a password file full of scrypt hashes.
I don't understand the second line of your pseudocode -- I read the description as not having any ("external") random bytes, just the PRNG initialized from the seed derived from scrypt:
"CBcrypt combines publicly known authentication factors (typically username and server id) with secret factors (password), applies a rate-limiting work function such as scrypt or pbkdf2, to deterministically generate a random seed. This seed is then used in a pseudo-random number generator (prng), and the prng is used as the basis for generating a public/private keypair."
EDIT: ah, got it (libc! :), secureSrand means "initialize PRNG with seed", so we're talking about the same thing.
Yes, "srand" was my shorthand for that, but since I just invented that shorthand, I'm not surprised it was confusing.
Also: is it safe to use a secret-seeded DRBG as a CSPRNG for ECDH keygen? The time it will take to generate the ECDH key will be secret-dependent, right?
(I'm sure it doesn't matter in this case. Just curious about the general case.)
I think it's safe, but we need real cryptographers to figure this out (does Matthew Green approving miniLock count?). With proper Curve25519 implementations key generation timing shouldn't be secret-depended: it's the same scalar multiplication (crypto_scalarmult_base).
No, I mean, you have to trust it to store password hashes, just like in any other scheme. The ECDH public key is generated deterministically from the password. If you have it, you can crack it to recover the password.
His underlying assumption is that given an ECDH public-key it is computationally infeasible to derive the private key / seed that went into creating it (via brute force). I suppose that's a fair assumption if your password has high enough entropy or is stretched sufficiently?
If a server just wants a hash, then that hash becomes the password. MITM attacks still work as long as all server credentials are public. EX: A fake wifi hotspot wants to MITM a connection and can fake any public information (public key's, IP's, DNS, etc.)
Further, a fake website can sidestep this by not using a secured connection and just faking the UI.
If you read the mechanism, you'll see that this involves more than a site faking the UI - it requires browser integration. This mechanism does not protect a single site, but rather the ability to pivot from one site to another with the same password or key. You also breeze over "can fake any public information" - I have no idea what you are trying to say by the ability to fake public keys - that is not really a thing. HTTPS rides on having a trusted intermediary and so even a malicious MITM couldn't simply fake a public key.
You run into the question, is this the 'magic' UI or a PNG send from HAXORU.
Windows reserves CTRL + ALT + DEL for this reason, but doing that on a tablet / phone that's already in production quickly runs into issues. Also, windows had plenty of issues with fake login screens.
PS: I suspect protecting people from such things ends up requiring fairly strong AI or significant compromises.
I think the Stanford folks were on to a better solution for this problem. (I have no affiliation)
Use all of the authentication data as the seed for generating a key pair. When you create a new password you send the public key to the server, where it is stored. The private key is regenerated on the client on every authentication challenge.
The exponentiation makes the brute-force attack a little bit harder than a simple salted hash, but not that much. You can obviously replace the salted hash with something else, and that's a good idea, but the point of this post is that password hashes are insufficient to protect user secrets.
I may be dense, but is the problem the same as with the usual discussions of salted password hashing, i.e. if H were bcrypt() it would be fine, or am I missing some simple mathematical thing?
... appears to have a straightforward, helpfully inlined timeable comparison of challenge responses.
I don't understand what this package is accomplishing. The description leads off talking about the grave privacy implications of storing scrypt password hashes. But then it stores what is in effect an scrypt password hash on the server.
> The description leads off talking about the grave privacy implications of storing scrypt password hashes. But then it stores what is in effect an scrypt password hash on the server.
I don't think it's saying that storing the hash is bad, it's saying that sending an unmodified password to be hashed on the server is bad since that server now has your cleartext password.
The website does a really poor job of emphasising that it's using asymmetric cryptography and some sort of challenge/response protocol, and how that is really where the improvement over the status quo is. It's _not_ just sending a hashed password.
I actually don't know very much about challenge/response protocols, and I'm struggling to find any good resources, so take this with a grain of salt. You could build a protocol out of digital signatures (probably there are massive things wrong with this, don't do this, here by dragons, don't build your own crypto etc. etc.):
1) When the user registers with the site, the client generates a public/private key pair and sends the public key to the server, which stores it.
2) When the user wants to log in, the server sends a challenge to the client. The client uses their private key to sign it and sends the signed message back to the server. The server uses the public key stored against the user to validate the signature.
Obviously this is more than just hashing the password on the client. If the server sends a different challenge each time (possibly time based like OTP?), you're protected against replay attacks.
The problem is you need a key pair. You don't want to generate a random one because then the user has to manage it and keep it with them and copy it from machine to machine etc. So the problem solved on the website is how to generate a good key pair from just a site identifier, username and password.
How effective it is at that, I have no idea.
[edit] other posts have helped me realise the public key is just an unconventially derived hash. Even if it's used in an unconventially way for authentication, you can brute force it the way you brute force any general hashing algorithm: key == generate_key(password_guess)
I'm still trying to figure this out but isn't it sending the ECDH of the private key which would be much longer then what the average user is going to use as a password (eg. I don't know, 1024 bit or something) and therefore more secure then sending a hashed password?
Edit: And then you (maybe?) use your password to encrypt the private key locally.. maybe? That's a total guess. That's what I'd do :P
How does public-key authentication work? Over things like, ssh, I mean.
Does the client send the private key to the server for verification? I'm not sure but I doubt it. At least I hope that's not what it does.
My guess would be that the server sends an encrypted message of some sort that the client cannot decipher unless it possesses the private key. It deciphers the message then sends it back to the server in deciphered form to say: hey, see, I have the private key, here's the proof: this is the message you sent me earlier. I couldn't have deciphered it without having the private key.
Can this scheme be used with passwords as well? As in, treat the password as a private key, so the client never has to send it over the network.
Server ---- [garbled-message-challenge] ---> Client
Server <--- [ungarbled-message-response] --- Client
Seems to be talking about encrypted communication.
I'm talking more about authentication over a channel that's not necessarily encrypted.
The point being, avoiding having the client send its "secret pass word" to the server, but still allowing the server to verify the identity of the client.
The secret that's being shared with DH is thrown away and generated brand new every time you start a new session. Your private key is never shared with anyone. The term shared secret refers to material that is totally unrelated to a private key.
In SSH's case public-key authentication simply involves signing datastructure that depends on the initial DH exchange. This does away with need to exchange some additional challenges and also binds the authentication to the encrypted channel.
Canonical protocol that involves generating (in this case symmetric) keys from passwords is Kerberos. Implementing same idea with asymmetric crypto is certainly possible, but of somewhat questionable utility, because doing ephemeral DH and then some kind of authentication handshake is both more secure (PFS and so on) and more efficient. True asymmetric encryption algorithms (e.g. RSA) have ciphertexts of considerable sizes (in comparison to anything ECC or sizes of DSA signatures), while discrete-log encryption algorithms essentially involve doing the DH exchange anyway.
In other words: asymmetric encryption is rarely the right primitive for network protocols. On the other hand converting password to keypair that is used for signing or something like SRP is useful for some applications (for most applications there isn't any practical benefit).
The main problem this project is trying to mitigate is the password reuse. If user A uses the same password for a lot of sites, a malicious person B is able to convince A to join a new service, like a cat photo sharing app or something like that. If A uses his/her same usual password, B automatically gets access to all A's accounts.
The way this project tries to solve the problem is by hashing the password from the client side so that sites never get the real password, but a hash instead. As other commenters have pointed out, this is not entirely effective because the attacker still can crack the hash. It just makes the problem more difficult depending on the size of the original password.
The real solution to this problem is to stop sharing password at all. Use a password manager for that purpose.
As the page points at, the malicious website does not recieve a hash of the password, but rather a public key derivied from the password:
"The worst attack a malicious server can mount is an expensive brute force attack, attempting to overpower the rate-limiting function and eventually guess a password that recreates the exposed public key."
That is a very different attack to try to pull off.
The hard part is getting browsers to all implement something like this (all with the same specification), which for some reason hasn't been happening, despite the fact that a mechanism like this is an obvious design that is obviously better than sending passwords.
A malicious server doesn't need malicious javascript to do it, it already receives the password in the plain, but that is what is trying to be mitigated in these efforts.
Using a JS lib would not mitigate any risk here unless the compromising of the server that hosts the JS is separate from the compromsing of your web server.
On the other hand, there's nothing that's made _worse_ by choosing to do it that way. Plenty of things that are the same, some things better, but nothing worse.
It's been done, most notably in IBM/Lotus Notes, but that also brings its own set of problems to the table.
In the Notes system, the user has an encrypted local credential store (part of the ID file) which contains, among other things, the user's private key and any shared secret keys the user may have been granted. The ID file also contains (in the clear) a certified public key, user name, and other information that should not be considered secret. The only password authentication is locally with the ID file. The password is salted and stretched with a key derivation function; the derived key is used to attempt to decrypt the encrypted portion of the ID file. "Success" is determined entirely by padding and checksums. Neither the password nor any variation on the theme of a hash of the password is stored anywhere. The "safe" portions of the ID (username and public key) are used to create a user account on the server.
Authentication proceeds much like this: "Hi, server! I'm this guy according to that guy." "Oh yeah? Well, this guy (if that's your real name), you ought to be able to answer this encrypted question and send me a signed response."
(Determining whether that guy actually vouched for this guy is standard signature stuff, assuming the check is needed at all. For stand-alone clients, a locally-generated certifier is SOP.)
That does raise a couple of potential pain points, though. One is simply managing the local store, making sure that the users always have access to their credentials. Another is that when a store dies, the private key dies with it (secret keys can always be re-issued to a new credential store once the user is satisfactorily vetted). And users have this horrible, horrible habit of either never backing anything up or "backing up" to the same physical medium. In the corporate Notes world, that's not such a problem since updated ID files mail themselves off to an ID vault, but who gets that trust in the civilian world? And there's the little matter of password recovery (in Notes, a KDF state accessible using a combination of something like Shamir secret sharing and the private keys of k of n trusted administrator IDs) — one probably doesn't want to throw recoverable credential stores into the wild hoping that trust is never broken. Without password recovery (which isn't actually password recovery; it simply allows the user to re-encrypt the I with a key derived from a new password they choose) of some sort, anything that requires your private key is lost when your password is lost. Automating the resetting of a server account brings us back into the realm of highly insecure things like "security questions" (since it's very likely these days that the second factor of 2FA is the same lost/stolen device that prompted the need to reset the account in the first place).
"If a user attempts to login to a malicious site accidentally or because they were tricked by a similar but different name, the malicious server will only gain knowledge of a derived public key. The attacker will not be able to impersonate the user at any other server, or even on the compromised server, because the attacker has not discovered either the user's private key for connecting to the compromised server, or the user's password that could be used to derive the private key on this or other servers."
Doesn't this assume a lot about the state of the internet? I mean a phishing attack could easily harvest the user's password, then the attacker effectively has their private key. Unless every user were trained well on how to determine whether the connection can be trusted, but that's still a problem today in 2015 even with https.
and the web browser would allow you to enter your credentials in a secure, NATIVE window. (At least secure from web stuff - keyloggers get a lot more powerful under this scheme.)
If it works as advertised, it's quite nice. Personally, I think this is very close to what we need.
I will note I still probably wouldn't use it because if your password is exposed, then you're screwed. It is very close though. A hardware element or something might mitigate this enough.
Ok, but how would a native window prevent an undereducated user from naively entering their password into an attacker's spoofed login form? In my mind this strategy more or less kicks the ball down the field as opposed to revolutionizing security.
Would this not still be phishable? All an attacker would have to do is make a website look enough like the real thing, then use a plain <form> element and capture the submitted form content.
I would think an out of browser app might work better for that task.
If this is traditional public-key crypto, having the password does nothing for the attacker without the private key. But I didn't watch his "technical details video" so I don't know what he's actually implemented. He mentions that getting the user's password would allow you to derive the private key, which makes no sense.
That's exactly the problem. The private key and the password are effectively 1-1. So if you can phish the password, you have the private key. This solves nothing.
No, that's not a problem at all; the key appears to be derived from more than just the password. The only weak spot is if you can run arbitrary code on the user's PC.
(I'm going by the textual description on the linked page as there doesn't seem to be a more detailed or formal one)
The key, as I understand it, is derived from a combination of the password and other deterministic elements, like the host URL. I suppose it's supposed to be ethereal, generated only for the session and the disposed after the user logs out. But for it to work, the user would have to be able to generate the exact same key on other machines using the same password. In which case, all an attacker needs to obtain the private key is the password and the vulnerability to phishing remains.
You can use client certificate for authentication using TLS. The main difficulty is how dire the UI experience is on the browser side - it's evidently little more than an afterthought for vendors.
I think its a chicken and egg problem: very few services use it, so no browser vendor cares to improve the UX; and the UX sucks, so very few services choose to use it.
It probably won't ever change unless one of the browser vendors that is also an vendor of popular online services decides that it would be good to enable it in its own services, and picks up the cost of upgrading its own UX to support that (creating pressure on other browser vendors, while also lowering the barrier for other online services.)
The problem is that all of the browser vendors that could do it are pushing their own, online authentications schemes, and have no interest in client-based authentication.
Why even have those if you are, presumably, presenting yourself as the same person in each case?
You are person 'A' and you have the private key (and maybe password used to unlock the key) to prove this fact.
You don't need different private keys for each and the remote end just has a public key that says the account belongs to person 'A' and that key is public.
The only usage case would be if someone wanted multiple accounts at the same site, and that would be rare indeed.
The only other real concern, site hacks/collaboration leaking where you're a member of by public key, wouldn't be alleviated by merely a handful of keys anyways: you'd need unique keypairs for each to be truly secure.
Passwords is one thing, but its sending information to servers that is the issue.
Things like U2F have a better chance of solving the password issue.
Information though.. i'm happy with google apps processing my data but i'd rather they can't actually store the data on their servers.
Ex: lets say you're a gmail user. Wouldnt it be nice if only your browser could read the contents and gmail servers only metadata?
Obviously, Google wouln't want that (remember, you're the product) - but that would be nice in the grand scale of things, wouldn't it? Like you know, instead of being slaves of corporations, just have them do stuff that's good for us and what not (dreaming out loud right now)
I still would not reuse passwords on different sites, unless the code that is being used to communicate with their servers is open-source and has been vetted by either myself or others who have some sense of cryptography.
Unfortunately, neither mobile applications nor the JavaScript on most web pages are open source, so there's no guarantee that they have implemented this strategy correctly. You don't know what happens after you type a password into a text box.
It's also too idealistic to expect that enough people will implement this kind of system such that you can advise people that it's "okay" to reuse passwords.
They are not the first to invent an "RSA-keypair-by-password" scheme and certainly not the last. The main issue with these is the fact that an estimated entropy of English language is 1.2 bit per symbol [1], so even if you are using pass-phrases, you are still generating an RSA keypair with a PRNG with only few tens of bytes in randomness in it.
[1] I think this was in one of Shannon's papers, but not sure. It should be very easy to find though. Basically once you start digging around a topic of using passwords as PRNG seeds all relevant research surfaces very quickly.
The state of the art for SASL is SCRAM-SHA-1. It uses challenge/response authentication and it allows the server and the client to only store salted hashes (using PBKDF2 with a configurable number of rounds). It also uses mutual authentication (the server also proves to the client that it has the hashed password, not just the other way around).
No idea how that compares to TFA, because they have no documentation.
And before SRP there was EKE. I thought the main reason it never saw wider use was because it was patented. Although according to Wikipedia, those patents expired in 2011 and 2013.
Challenge response schemes generally require the server to have the password in a recoverable format so that both sides can generate identical hashes. IMO the current state of things is better than it would be with 1000s of random websites with DBs full of clear-text passwords.
Nah. Hashes of hashes works just fine, and allows the actual password value to never be stored plaintext. A simple example:
Stored on server: x = SHA256("mypassword")
Server challenge to client: send a secure random nonce
Client sends: c = HMACSHA256(nonce, SHA256("mypassword"))
Server verifies: c == HMACSHA256(nonce, x)
In some implementations, the server challenge and 'c' are encrypted using 'x' or some derivation that both sides can create. In addition, salts can remove the sensitivity of the stored 'x' values (https://en.wikipedia.org/wiki/Salted_Challenge_Response_Auth...)
The problem with hashes of hashes is now instead of the password being directly grabbed, the hash is directly grabbed, which can be thrown through the challenge-response system with no problem.
This only mitigates knowing the password itself, not anything to do with authentication.
> The problem with hashes of hashes is now instead of the password being directly grabbed, the hash is directly grabbed, which can be thrown through the challenge-response system with no problem.
But now you have to grab the hash first from one of the endpoints, MITMing the connection no longer suffices to impersonate the user.
I suppose public key schemes would be preferable, but deploying those isn't feasible for a lot of use cases.
> Challenge response schemes generally require the server to have the password in a recoverable format so that both sides can generate identical hashes.
Do they? Doesn't the server just need to share the salt and algorithm parameters it stores anyway?
The server can store the salt and parameters, although it gets really hairy if you decide that MD5 is too weak and now you want to upgrade to SHA-1 or SHA-256.
My reaction is one of those "I'm not sure if I should feel stupid or not" moments, but: rightly-built applications already don't expose passwords to employees in that they aren't (or at least, shouldn't be) generally persisted. Usually the plaintext passwords live in volatile memory briefly while the server computes a hash of some kind for comparing with what is stored. I suppose an admin could run a web application under some sort of memory profiler, or take a dump at exactly the right moment, and capture a plaintext password, but that seems pretty far-fetched.
CBCrypt seems to me to introduce a lot more complexity into the entire application space with very little real gain. I'm certainly open to being convinced (especially because I'm waffling on whether or not this is a dumb reaction).
The idea is that you're implicitly trusting the company (or website), as well as anyone who has (whether legit or not) access, to only keep that password in memory, and it's preferable to authenticate without requiring that trust.
The momentary exposure in memory was the downfall of Lavabit. It is actually trivial to capture passwords submitted to servers during the momentary exposure. For example, when you login to a Drupal or Wordpress site over HTTPS, the POST gets submitted to a particular form - which is just a PHP file on the server, trivially editable. The password exists as one of the submitted form variables, which PHP then passes to bcrypt (or whatever).
People generally aren't carefully clearing passwords from memory after use, and ideally GC runs aren't happening all that often. "Exactly the right moment" could easily extend out to many minutes.
Right. So there's an I suppose in there somewhere, and my response is still pretty much: "meh". The people who might could possibly get access to that password already have access to all the data being protected by that password, and if they were so hell-bent on using your password to break into other sites, they could do that anyway by brute forcing what CBCrypt produces.
This is all nice; and as hinkley pointed, Stanford already proposed a better protocol. The primary issue in my opinion is how to trust the JavaScript arriving from the server that it does what it's supposed to do.
In my humble opinion; we need to use the blockchain to save hashes for trusted and open-audited JavaScript files to be confirmed by the user. This, however, needs to be done at the browser level to avoid an endless trust loop with JavaScript/browser extensions. blockstrap.com has figured out how to put file hashes on the chain; so technically it shouldn't be a major challenge to do the first part. The browser part is where it gets tricky!
> is how to trust the JavaScript arriving from the server that it does what it's supposed to do.
This is an orthogonal problem. Something like CBCrypt would solve a real problem we have right now, which is most service providers don't secure their password database correctly.
If a service provider gets hacked to the point that they their javascript is malicious, all your content on that service is probably already pwned.
The server has all the inputs except the password and enough information to validate if it has guessed the right password. So password guessing/dictionary attacks are still viable, especially with state level adversary. BUT users are given a false sense of security because "the password is never sent to the server". So we can expect users to (on average) use worse passwords and reuse passwords inappropriately.
IMO, if you are going to use client certificates you should be just be using standard client certificates with whatever your OS provides to generate them.
As far as my limited understanding goes, MS-CHAP v2 allows you to store a hash of your password on the server rather than storing the actual password. Then through a convoluted sequence of hashing algorithms it generates another hash and compares that with a hash you have provided. I think it's been around since at least 2003 and though it has itself been cracked (cf Moxie Marlinspike) I don't believe it's ever expected to be used outside of an encrypted tunnel (cf Matthew Gast).
This is only a tiny improvement. Any password cracker can figure out your password just from the hash anyway. What we really need is industry support for and general acceptance of two-factor passwords. I want to generate one-time passwords from my smartwatch, have them sent to my keyboard or computer directly, and be able to log in to gmail and through ssh alike.
Is it just me, or does the current way we handle passwords feel archaic, even while we still use them?
"due to Third Party Doctrine, users forfeit their legal right to privacy by merely making it possible for sysadmins to access their information. This means the sysadmins can legally share users' information and passwords with additional third parties, and the NSA can legally spy on it all, without any need for a warrant or probable cause."
This sounds super fishy to me; feels like a misinterpretation made through tin-foil lenses. Citation please?
He keeps talking about how this is going to prevent malicious employees from getting at your data or sharing it with the NSA. It's not. Facebook, Google, and every other website you use will still have unencrypted access to all of the information you give them on their servers. The only thing this would keep them from having is the password you use to protect that other stuff they already have access to anyway.
Servers are far more secure then a users computer so I would trust a server over even my own computer. All things a user can do very badly if they don't know what they are doing, will. I have been in software long enough to know that. Good luck but I just don't think this is the solution as it still relies on SSL which I think is the weakest link, not the server or the make believe bad employees.
The problem is bigger than that - we should stop making users type password at all. There should be an authentication module any website could use to store and retrieve credentials from. Check out Truefactor.
> The problem is bigger than that - we should stop making users type password at all. There should be an authentication module any website could use to store and retrieve credentials from.
We have the solution already in HTTPS client certificates. Browsers all have mechanisms for generating and storing them. The only problem is that no one uses them.
Open truefactor:// app. Currently there is only a Web version and it has serious downsides (web crypto is a bad idea), but think of it as a Light version. Desktop apps to come later.
I was looking for more of a write up. I'm just wondering how/where the credentials get cached and how you securely know the user re-connecting is the user who previously disconnected.
Email itself is salt (or rather public part of passphrase). So from email+passphrase encryptionKey is derived using scrypt. So it's actually sha(scrypt(email+passphrase))
Password on an x509 cert requires the x509 cert to be stored or made available to the client somehow. The whole point of CBCrypt is to allow password authentication and encryption without the user needing to change any behavior or learn anything.
Sounds a good idea. I'd like to see a more technical description of how it derives the public/private key pair from a password. In addition, the language choice of C# is probably going to limit its popularity, given how C# is still tied to Microsoft world (I know they are open sourcing .Net, but that has not matured yet).
I don't see how this can claim to prevent phishing attacks. A fake site can still just steal your username and password as usual, and then go to the real site and log in with them.
Am I missing something?
Obviously there is still a benefit to not sending your password to the real site, but their anti-phishing claims seem… phishy.
This looks very similar to my password authentication method PSPKA or 'password seeded public key authentication'. See https://github.com/phlay/pspka, if you are interested.
How is this not functionally equivalent to TLS client-side certificates? Yes, I understand that there's a UX problem, but CBCrypt has to solve that in addition to the crypto problem.
I think it's amazing that there are so many security conscious people that are very sensitive about passwords and storing them as plaintext is worse then hitler, but nobody questions how we're still stuck with plain shared secrets for authentication in 2015. If the concept of passwords wasn't so fundamentally broken a password leak wouldn't be an issue, not even if it's plaintext.
"Oh no, my shared secret for this site got compromised and now all my accounts are compromised because I authenticate to 50+ other sites with the same secret."
This is like putting your only private key on every service and complaining if bad things happen.
It does one thing better than a password manager: it prevents rainbow attacks via forced localized salting. That's about it... Next HTTP can solve other problems...
Client certificates already exist. The problem is that nobody uses them, because every step of the process is a complete and utter pain in the ass. Much like how standard HTTP authentication is ugly, making the existing infrastructure prettier would be much more useful.
I agree, but only the browser vendors can do that. The point of DSSID was to try to force the issue by implementing a usable UI over what is essentially a client cert. If enough people started using it, that just might nudge the browser vendors into doing the Right Thing.
When you email a token, you're back to square 1 and will need 2 factor auth.
In addition the reset password is not possible when the data is encrypted on the client side. This is how TrueCrypt works - if you forget the password, all your data is lost.
As a client-side hashing approach, I think it's a bit overly complicated but probably not fundamentally flawed. I would use a singular hash function to produce the byte stream, instead of introducing a PRNG and seeding it from the hash functoin just to get a byte stream. But the bigger conversation is, what role can client-side hashing play, either as a full-on replacement to server-side hashing, or perhaps just to augment the server-side hashing everyone is doing today?
Stepping back a minute, it's helpful to consider the fundamental reality of almost any password validation scheme. In this case we are storing a "public key" on the server, but it is more aptly described as the "password validator". Almost all designs will have such a thing (a notable exception is PolyPassHash which cleverly avoids a one-to-one mapping of users to validators, and uses this to try to defeat some offline attacks, with some interesting trade-offs).
If you combine public information, the password validator, and the correct password, your 'password validation function' will complete and return 1. Therefore, if you have the necessary public information (i.e. domain name, username, whatever else is stuffed in the hash) and you steal the password validator database, you now have everything you need in order to run the so-called "offline dictionary attack".
In SRP, an obvious inspiration to this CBCrypt design, the password validator database is basically computed entirely by the modexp() work required to generate the pub/priv keys. There is no additional/configurable key stretching which can be applied other than choosing the bitlength of the keys.
Here we have a configurable round of hashing (Scrypt or PBKDF2) which is applied before the key derivation step. This provides additional protection against offline attacks, depending on how hard the work factor is set. History has shown us, a key detail in ensuring secure password storage is actively managing the hashing function and work factors over time, or else watching Moore's law strip away any protection we thought we had.... So the next key question is, how do we actively manage and maintain a sufficient work factor?
When evaluating a hashing function, one key question to ask is can we add to the work-factor of existing passwords offline (without having the password in RAM) or do we need the user's password resident (somewhere, client or server-side) in order to recompute a new hash with the new work factor? In this case, by design it's impossible to offline harden the existing passwords. You would need to first login the user, verify their password, and then recompute a new hash (perhaps transparently, perhaps with some UI component if it is too slow otherwise) and re-derive and update the key server-side, in order to change the work factor.
But really, the primary consideration with any client-side hashing design, is how to support the extremely wide array of devices which will need to register/login to your site, and what's the user experience when they click the Login button?
From CBcrypt.cs, where the proof of concept is written in C#.NET using BouncyCastle's Scrypt library:
/* cost 4096, blockSize 8, parallel 1, cause SCrypt to take ~175-350ms on Core i5-540M, 2.5Ghz
* This is in addition to the approx 100ms-200ms to generate ECDSA keypair.
*/
Now, in reality we are going to be running Scrypt in Javascript on a mobile device. I found what seems to be a highly optimized implementation [1] and plugged it on Dropbox [2] so I could point my browser at it to see how slow just the Scrypt ran. On my laptop it was taking about 800ms and on my iPhone 5 about 2500ms. I would say that means for about 25% of the mobile population this function runs about an order of magnitude too slow for comfort... it will impact user experience, it could impact bounce rate, etc. This doesn't even include the ECDH part of the calculation.
This is definitely the hardest question to answer with client-side hashing, or even simply "sever-relief" hashing where a portion of the overall hashing may optionally be pushed to the client, particularly during DDoS type events. How do you identify which clients are sufficiently powered to reasonably perform the hashing, or what kind of UI needs to be presented if you could be potentially locking up a browser for 5+ seconds while the hashing is running? Users are not well trained to expect logins to be slow -- a stall in the browser is almost always a reason to simply resubmit the form. It would be great if users associated their browser tab locking up, their fans spinning to full speed, and their battery power plummeting with "Whoohoo, this site is ROCKING a awesome work factor!" but in the real world we see that companies want hashing run on powerful CPUs server-side, with the capability to offline-upgrade hashes over time.
The final nail in any client-side hashing approach is when the claims start to cross over to "server never sees the password". I don't see this as a valid argument any time the code to perform the hashing is being sent over the same trusted connection from the server itself. There are corner cases, for example if you are shipping compiled and signed code which is hashing client-side, or if you take special precautions with browser plugins to ensure you are running a specific build of the Javascript, but that simply doesn't apply to 99.99% of use cases, and so I personal dismiss those benefits as not likely to be achieved in the real-world. What we're left with is technically a sub-optimal user experience with additional trade-offs. So in conclusion, I am currently quite bearish on client-side hashing on the web in general.
> To cryptographers, the phrase “prove you know something secret without exposing it” instantly suggests “use asymmetric cryptography.”
No, wrong, stop right there!
The phrase "prove you know something secret without exposing it" instantly suggests that you should figure out what "exposing" means before you try to design a protocol. If I'm a user reusing a password between two sites, then it's unavoidable that either site can try to brute-force my password. However, it would be rather nice if an attacker who hasn't compromised either site can't brute-force my password without interacting with one of the servers for every single guess.
That property is achievable using well-understood techniques, and this blind use of asymmetric cryptography fails to achieve this goal and is unnecessarily complicated (what's the PRNG for?). The primitive you want is an "augmented PAKE". The IRTF CFGR is very slowly working on standardizing one, but in the mean time there are several high-quality augmented PAKEs out there.
Also, note that I said "primitive". A strong primitive does not automatically make a good protocol. CBCrypt's docs say "Keypair is ECDH 256, derived from SeededPRNG". This raises all kinds of warning bells: while there are perfectly good protocols based on ECDH, ECDH by itself just gives an /unauthenticated/ session key, and from a 30-second look at the code, CBCrypt appears to be trivially vulnerable to a replay attack in which a malicious server A convinces a standard client to give it a valid authenticator for a session to a different server B.