

JCryption - JavaScript data encryption - Oompa
http://www.jcryption.org/

======
tptacek
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.

~~~
sriramk
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.

This seems the lesser of two evils.

Please be gentle :-)

~~~
NateLawson
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.

~~~
swolchok
"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.

~~~
tptacek
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?

------
dryicerx
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?

~~~
tptacek
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.

~~~
dryicerx
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.

[Client] ---(fakekey)---- MITM ----(realkey)---- [Server]

~~~
NateLawson
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.

------
epe
Voted up in hopes that tptacek sees this so I can watch him rip it apart. ;)

~~~
NateLawson
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.

------
sweis
This does raw RSA in ECB mode. It is vulnerable to both chosen-plaintext and
replay attacks.

------
yread
Why do they use RSA? Isn't Diffie-Hellman a better method? Exchange keys by DH
and then encrypt traffic symmetricaly. Is it reasonable?

~~~
tptacek
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.

~~~
codahale
Oh, gross.

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.

~~~
tptacek
Want a poster? :)

The timing attack thought is great; would love to have an easy target for a
classroom demo. Thanks!

