There is no way to validate the public key the data is encrypted against, so a man in the middle is possible by injecting a new public key and intercepting the cypher-text on its way back.
Just my though, if this type of security is needed, why forego SSL?
The author claims SSL is neither supported by every webhost nor it’s easy to install/apply sometimes.
Not sure if I totally buy that - if you are collecting data you want to protect, surely it's worth it for you to use a host that's capable of installing SSL. It's a pretty simple operation.
Injecting a new public key? Heh. You can MITM this library just by inserting a JS tag into the DOM that turns its "encryption" off. No need to be clever.
This will tip the server off as it won't receive the expected cyphertext.
By doing a mitm interception with a newly injected public key and re-encrypting with the real key before sending to server, you can let the client-server carry on a conversation as usual, while you intercept the entire conversation.
I don't think it needs to be that complicated. Just add a new comment field that contains the session key in plaintext. Neither the server nor client ever knows the difference.
Ironically, it looks like the talk I gave on common crypto flaws also made HN today (http://news.ycombinator.com/item?id=748164). What's funny is it explains exactly why Javascript crypto is a bad idea, but it appears to have less votes than this one.
I think this library is a great idea. We can add its signature to automated scanning tools, and feed it to Google Code Search queries, and periodically generate lists of catastrophically insecure web applications. I much prefer a single, easily-detected security failure than a diverse population of more subtle failures. Kudos to this guy.
I will send a Matasano poster to anybody who posts a valid flaw in actual implementation of this library, excluding the fatal design flaw of delivering encryption code via Javascript to browsers.
I'll get you started (I've already got a poster): this library uses PHP's builtin mt_rand() to generate keys.
Not a crypto person. I'm pretty sure this is going to be ripped apart by tptacker, NateLawson or cperciva. But I'll speak up anyway :-)
I see a lot of sites use HTTP basic auth to do usernames/passwords (especially startups). Or worse, they send it over the clear (for e.g., some very popular APIs out there which I shall not name). Their reasons vary but typically it is one of cost and convenience. It is of course a terrible practice.
Compared to HTTP basic auth, this seems less evil. In this case, with no implementation issues, I assume you need an active attacker. With HTTP basic, you can just grep logs and decrypt credentials.
Yes, basic auth with no encryption is bad. In some cases, this is no better though.
For example, if the key and JS are provided by the server, then it is the same as basic auth (all data needed to obtain the plaintext password is in the HTTP session). If the key is generated locally on the client, you have the problem of including a good enough PRNG, seeded from enough entropy that the attacker can't guess it.
And those are all purely passive attacks (no MITM interjection). Active attacks could include modifying the JS to insert another field in the FORM POST response that is the plaintext key.
javascript encryption will anyway only stop people at quickly decoding your data on sight. anyone who is willing to spend some time on decoding your data is able to do it, no matter which javascript library you use.
also: nice idea, modifying the js to add a plain text field to the form :P
That's true. Someone sitting with a wireless card in Monitor mode with Wireshark just sniffing passwords at the local cafe will probably have easier targets.
Then just XOR your passwords against 0x41 in Javascript. Most attackers sitting the local cafe won't read this HN comment to learn your secret XOR key, your encryptor is a one-liner, and it's 95% as secure as Javascript RSA.
"For example, if the key and JS are provided by the server, then it is the same as basic auth (all data needed to obtain the plaintext password is in the HTTP session). If the key is generated locally on the client, you have the problem of including a good enough PRNG, seeded from enough entropy that the attacker can't guess it."
What about if a public/private keypair is generated on the server and the public key is sent to the client? That sounds fine to me (implementation bugs notwithstanding) and it's what the second FAQ (http://www.jcryption.org/faq/) says happens.
Of course, this is still an awful idea because, as other posts have pointed out, the library itself can be doctored in transit, but I don't see a problem with the key handling design.
Even if you didn't have the JS problem here, you have the fundamental problem of not having trust anchors. You get a key over the network. How do you know it's the server's key?
I know next to nothing about crypto, but just a bit of Googling came up with:
"Mersenne Twister is not cryptographically secure. (MT is based on a linear recursion. Any pseudorandom number sequence generated by a linear recursion is insecure, since from sufficiently long subsequence of the outputs, one can predict the rest of the outputs.)
To make it secure, you need to use some Secure Hashing Algorithm with MT. For example, you may gather every eight words of outputs, and compress them into one word (thus the length of the output sequence is 1/8 of the original one)."
I don't think he's wrong, but I think you may be following his logic and overshooting the right conclusion; he's saying it's possible to use MT as a component of a CSPRNG, not that MT itself can become a CSPRNG.
A good place to get your bearings on this is Kelsey et al's "Yarrow" paper. My (unqualified) opinion is that the Yarrow CPSRNG is awkward, but the paper is a good survey on what design tactics go into a modern CSPRNG --- in particular, entropy collection and refreshing, both of which PHP's MT lack.
no, he meant /dev/urandom. /dev/random is reserved for hardware random generating devices on some operating systems (which may not return anything). /dev/urandom is a device that will always output pseudo random data without blocking when the entropy pool runs low.
What a weird little subthread. urandom and random are both CSPRNGs --- the same CSPRNG, in fact --- the only difference between them is whether the device blocks to fetch more entropy. Go ahead and use /dev/random if that question freaks you out. Either way, don't rely on mt_random.
All security is about levels though - nothing is secure. This library obviously fills a specific level, and provides some protection. It'd certainly make some guy in the IT dept packet sniffing likely give up.
You're not going to use it for a banking website, but saying it's useless as you seem to be, seems odd to me.
In that vein, Javascript's Math.random, while the implementation is JS-engine specific (so I'm hesitant to condemn it across the board), hardly qualifies as a CSPRNG either.
So, you're saying in effect there's no way to properly do encryption in pure JavaScript at all? That you'd have to get the random numbers from a Java applet or something of the sort?
No, using DH would be even worse here than using RSA; JS crypto is intinsically vulnerable to MITM attacks, but so is DH --- an attacker just runs DH independently with both sides of the transaction, zeroing or fixating the key.
More comments about how they used RSA? Fire away, I'll send you a poster. They're pretty neat, if bigger than I expected.
They just pass the plaintext right through to RSA. No OAEP, just bang right into the BigInt. There's some random gibberish appended to the plaintext ("hey, this needs some salt"), but they're not padding a damn thing. Bleichenbacher's chosen-ciphertext attack; game over.
The RSA decryption, server-side, isn't blinded at all. Timing attack free-for-all there. Boneh's timing attack might work, as long as you can pin the session down. (And since this is for folks who don't get SSL, I'm sure you could.)
And key generation is equally horrible. The lack of a real CSPRNG was pointed out by someone else. They're also not protecting against Fermat factorization: when they generate p and q they only check equality and primality, not distance. Same with small decryption exponents. Unlikely to be serious, but it sure doesn't speak to their skills as cryptographic implementers.
40 comments
[ 2.4 ms ] story [ 87.3 ms ] threadJust my though, if this type of security is needed, why forego SSL?
Not sure if I totally buy that - if you are collecting data you want to protect, surely it's worth it for you to use a host that's capable of installing SSL. It's a pretty simple operation.
By doing a mitm interception with a newly injected public key and re-encrypting with the real key before sending to server, you can let the client-server carry on a conversation as usual, while you intercept the entire conversation.
[Client] ---(fakekey)---- MITM ----(realkey)---- [Server]
I will send a Matasano poster to anybody who posts a valid flaw in actual implementation of this library, excluding the fatal design flaw of delivering encryption code via Javascript to browsers.
I'll get you started (I've already got a poster): this library uses PHP's builtin mt_rand() to generate keys.
I see a lot of sites use HTTP basic auth to do usernames/passwords (especially startups). Or worse, they send it over the clear (for e.g., some very popular APIs out there which I shall not name). Their reasons vary but typically it is one of cost and convenience. It is of course a terrible practice.
Compared to HTTP basic auth, this seems less evil. In this case, with no implementation issues, I assume you need an active attacker. With HTTP basic, you can just grep logs and decrypt credentials.
This seems the lesser of two evils.
Please be gentle :-)
For example, if the key and JS are provided by the server, then it is the same as basic auth (all data needed to obtain the plaintext password is in the HTTP session). If the key is generated locally on the client, you have the problem of including a good enough PRNG, seeded from enough entropy that the attacker can't guess it.
And those are all purely passive attacks (no MITM interjection). Active attacks could include modifying the JS to insert another field in the FORM POST response that is the plaintext key.
also: nice idea, modifying the js to add a plain text field to the form :P
What about if a public/private keypair is generated on the server and the public key is sent to the client? That sounds fine to me (implementation bugs notwithstanding) and it's what the second FAQ (http://www.jcryption.org/faq/) says happens.
Of course, this is still an awful idea because, as other posts have pointed out, the library itself can be doctored in transit, but I don't see a problem with the key handling design.
I'm assuming most people who would choose to use this library will just copy his example code and use 256 bit keys, which are very easy to factor.
this says in the 90's a 512 bit key could be factored for under $1 million
"Mersenne Twister is not cryptographically secure. (MT is based on a linear recursion. Any pseudorandom number sequence generated by a linear recursion is insecure, since from sufficiently long subsequence of the outputs, one can predict the rest of the outputs.)
To make it secure, you need to use some Secure Hashing Algorithm with MT. For example, you may gather every eight words of outputs, and compress them into one word (thus the length of the output sequence is 1/8 of the original one)."
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/efaq.html <-- And since that's the "Mersenne Twister Home Page", I'll take his word for it. :-)
So, looking at the PHP source code for mt_rand():
Which doesn't seem like it qualifies as a cryptographically secure implementation; I don't see any Secure Hashing going on.If you need secure random numbers in PHP, the best advice I have off the top of my head is to take it from /dev/urandom.
A good place to get your bearings on this is Kelsey et al's "Yarrow" paper. My (unqualified) opinion is that the Yarrow CPSRNG is awkward, but the paper is a good survey on what design tactics go into a modern CSPRNG --- in particular, entropy collection and refreshing, both of which PHP's MT lack.
You're not going to use it for a banking website, but saying it's useless as you seem to be, seems odd to me.
I came across this attempt: http://tim.dierks.org/2007/03/secure-in-browser-javascript-p...
But Billy Hoffman disapproves: http://www.webappsec.org/lists/websecurity/archive/2008-01/m...
So far as I know, there's no cross-platform way to get secure random numbers from Javascript.
You can, for instance, get them from Mozilla from the "crypto" interface.
This is another reason why Javascript crypto is a bad idea.
More comments about how they used RSA? Fire away, I'll send you a poster. They're pretty neat, if bigger than I expected.
They just pass the plaintext right through to RSA. No OAEP, just bang right into the BigInt. There's some random gibberish appended to the plaintext ("hey, this needs some salt"), but they're not padding a damn thing. Bleichenbacher's chosen-ciphertext attack; game over.
The RSA decryption, server-side, isn't blinded at all. Timing attack free-for-all there. Boneh's timing attack might work, as long as you can pin the session down. (And since this is for folks who don't get SSL, I'm sure you could.)
And key generation is equally horrible. The lack of a real CSPRNG was pointed out by someone else. They're also not protecting against Fermat factorization: when they generate p and q they only check equality and primality, not distance. Same with small decryption exponents. Unlikely to be serious, but it sure doesn't speak to their skills as cryptographic implementers.
Jesus H. Christ. What a train wreck.
The timing attack thought is great; would love to have an easy target for a classroom demo. Thanks!