I'll wait for the cryptographers to weigh in; but, it's in Javascript.. already a language that's going to be hard to Do It Right in. (The first third of the code is a BigInteger implementation)
Then, I looked to see if the standard constant-time comparisons were in there to resist timing attacks. No dice there.
So... cool. He put a nice wrapper on JSAES[1], jsSHA2[2] by way of webtoolkit.info[3], RSA and ECC in Javascript by Tom Wu[4], and seedrandom.js by David Bau[5].
But then then says it's "New BSD license"[6] when it should be GPL[7].
I didn't start this comment sound negative. But, I think a few things are important:
* Credit authors.
* Respect their licenses.
* Put a big fucking notice on top of your slick webpage: "FOR DEMONSTRATION PURPOSES ONLY-- NOT REAL CRYPTO"
He credits the authors in his doc, but agreed on the warning - I am not a cryptographer, but my knowledge of side-channel attacks has me pretty worried that the RSA implementation is not safe.
Does anything qualify as 'real crypto'? Every implementation will always and forever have weaknesses. I don't have a problem with someone putting together a package that makes it easy to do crypto stronger than rot13 - isn't that a step forward? We'd all like GPG/PGP easy in the browser with native code, but until then, what's wrong with an intermediate step that appears to be at least pretty good and fairly easy to use? Maybe it's not enough for organizing a coup, but for keeping your fantasy football strategies a secret - why not?
Code that has been written and/or audited by cryptographers would qualify as 'real crypto.' I don't think anybody has a problem with someone putting together this package; the only problem is with the lack of a proper notice that the code hasn't been audited.
That's a fair point. The idea that it could be used "for demonstration purposes only", though, seems to go too far in that direction. It seems like a useful library, just not for organizing a coup.
I would argue that rot13 is better than unencrypted, and that this is a step up from rot13. Sure, it's imperfect, but it's still better than nothing, and while I'm only a mediocre programmer, it appears to be easy-to-use, to boot. Better-than-nothing and easy-to-use seems like something more useful than "for demonstration purposes only", don't you think?
The company I work for (who for obvious reasons I will refuse to mention) refuses to implement standard cryptographic practises in its product. Several months after starting there, and after a lot of loud complaining, I managed to get them to switch to using bcrypt instead of plaintext passwords in the backend database. Only in the next release are they switching to using TLS for logins, and even then sometimes defaulting to a clearly fucked Javascript implementation of cryptography to send the password (using public key crypto with global server key that only changes on server restart, with replay attacks galore).
The one thing I can say about the JS cryptography is that it normally protects somewhat against passive sniffing attacks, but when it's as broken as this, it doesn't even accomplish that task.
This sort of thing seems chronic in the industry, and it's dismaying.
And as we both know, the "passive sniffing attacker" is a myth. If you can sniff packets, you can intercept traffic. We don't reason about security mechanisms by tying the attackers hands behind their back.
Management made the decision that my trivial change to eliminate replay attacks was "too much effort". I am inclined to agree, since even with such a change the effort required to circumvent their entire so-called security is minimal.
Next quarter they're introducing e-commerce solutions. Dear god.
One might argue that, if an unnamed company's e-commerce solution would put a lot of people at risk, and an unnamed engineer can prove it, that unnamed engineer has an ethical obligation to discreetly report the vulnerability first to the unnamed company, then to successively more influential and more public venues (e.g. consumer protection groups, security research groups, etc.), until the company responds.
Even if this wasn't browser Javascript and thus totally boned, it think it would still be pretty boned. I'll send a neat looking laptop decal to anyone here who spots any of the flaws in this cryptosystem.
But it is written as browser Javascript and is thus totally boned. Here's my attempt to be exhaustive about why:
Off the top of my head, reasons why this appears broken even if it didn't use Javascript:
The passphrase almost certainly doesn't have 1024 bits of entropy in it, and since they describe it as "used to repeatably generate this RSA key", they can't have introduced any additional entropy. And indeed, they just use the SHA256 of the passphrase to seed a PRNG.
They claim that a PublicKeyID "can be used to uniquely identify Sam's public key". Fingerprints help identify keys more easily, but certainly not "uniquely" since they don't have as many bits as the key; pigeonhole principle.
Worse, the PublicKeyID uses MD5.
They use a public exponent of 3, rather than the usual 65537 or larger. It looks like they might protect against small-exponent attacks, but I don't have enough expertise to know that for certain, and in any case this seems like a bad idea.
Neither cryptico nor the rsa-sign library they use mentions anything about HMACs; I haven't dug into the code to figure out if they actually use one or just use a hash directly.
I don't think this code protects against even the e=3 broadcast attack, because it doesn't verify the padding (as someone downthread noticed; I owe him a sticker now too).
Of course, not verifying the padding also means the signatures are straightforward to forge.
(Ping me with a shipping address and I'll send you swag).
"actually, i think an honest look at the security/privacy mechanisms provided by today’s tools precisely describes a case where ‘a little better than awful’ would be preferred. my mother emailed me some bank account information just last week. there isn’t any exploit required there. security software experts have failed horribly to provide tools that actual living breathing human beings might use and this is why most of them have just given up and use hotmail.
i personally find it astounding that the kind of people who will deny this probably have an actual brand new credit card sitting in their unlocked mailbox and feel perfectly comfortable with this fact.
your information’s security is only as strong as it’s weakest link. this includes the locks on your home, your mailbox, and the granularity you shred your trash with."
This sentiment falls victim to the fallacy that something is secure because it should be secure. The commenter is right that the "security software experts" have failed to protect his mom. But Javascript cryptography doesn't care. It's still insecure. Engineering is a spectacular douchebag, but it is in charge nonetheless.
Given the option between his mom sending it unencrypted, and encrypting it with an easy-to-use extension he set up for her, why not encrypt it? Surely it can't _hurt_ an already horrible situation?
Both of these options are worse than not mailing banking information at all. Both of them are worse than encrypting properly, which, in this mom's case, means installing PGP.
Yes, in this case, bad crypto can make a bad situation worse: it can create a false sense of security.
And in the general case, bad crypto does much worse things than that. Logging in without a password. Flipping bits in a cookie to become any user on the system. Gaining admin privileges. Spoofing authorities to collect secrets from users.
Bad crypto does not care how horrible your mom has it. Engineering says, bad crypto is going to be bad no matter how hurt your feelings are.
Link me to a well written PGP tutorial that even normally experienced people can use with Gmail. Perhaps this would be more useful than all this JS Crypto.
I simply disagree on practical terms. If I have the choice between the two, I am going to make my mom encrypt it with this library. That doesn't mean I feel perfectly safe and secure about it, but I feel better than not having encrypted it at all. Much like using a car alarm - I know it cannot ultimately prevent someone from stealing my car, but it certainly weeds out all but the most persistent attackers.
Moreover, for noncritical things, like my example of fantasy football plans, this appears to be a perfectly reasonable solution.
This thing won't replace https anyway, because if transferred over http, Javascript code could be intercepted and modified by adversary before it reaches client browser and before it is actually executed.
And if this JS code is transferred over https, what's the point of it? Don't we already have crypto in this case?
Not all uses of cryptography are for encrypting information sent over a channel. Consider bitcoin, which uses public/private keys and hashing functions to create a digital currency. No encryption is even involved.
You cannot verify the integrity of a browser Javascript cryptosystem by checking a SHA2 hash of the Javascript file containing the crypto.
That's because any other piece of content, from Ajax requests and whatnot to, in many browsers, the CSS files, some of them cached and some of them loaded on the spot... any other piece of content that contributed to the page that hosts the crypto code can alter the runtime to trivially intercept secrets or fix keys.
Until browsers provide a primitive to verify the whole runtime, cryptographic hashes won't do anything to ensure integrity for Javascript.
At that point, why bother implementing crypto in JavaScript anyway? You might as well just use a proper clientside app (a halfassed version of which is your suggestion).
Unless you are an expert cryptographer and write your own code from scratch, including the compiler and if you are really paranoid building your own hardware, you are always relying on third parties as your source for crypto code and the devices upon which it executes, and you have to trust they they have not inserted backdoors.
Can you expand on "trivial to alter" part? I get an impression there that many claim that altering JS you get is almost as easy as sniffing your traffic, I'd like to know more why it is so.
I threw together my own implementation of that from scratch when it hit hacker news a few months ago. Mine uses an arbitrary sed script, not sure what theirs does but I believe they've released their source now.. It took about 2 hours max.
Just one possible scenario is pretending to be the access point of your local coffee shop. Some of the coffee shop patrons will connect to your fake access point. Your system can subsequently run their traffic through a proxy that alters web pages to defeat any JS-based crypto, install malware, etc.
There's an interesting problem that is still unsolved in this space. Most people want JS crypto so that webapps can provide "end to end" encryption, relieving participants from having to trust the webapp service with their plaintext. The problem is that trusting you get the correct JS from the webapp for every message you'd like to send is reducible to trusting the webapp with your plaintext.
I think there are probably some novel solutions to this problem, but it would require work to be done by the browsers.
We seem to be on a track now such that in 5 years, all the mainstream browsers will support a set of crypto primitives built into the browser, implemented in C, and exposed via Javascript bindings. And that's fine.
But it means that we're not going to have end-to-end crypto in web applications for another ten years, because these schemes don't degrade gracefully; the majority of users will have to upgrade before they become useful.
And I'm not sure that this would be enough, either. Crypto primitives are nice, but you still have to trust the webapp to deliver JS which calls those primitives every time you visit the webapp. I believe that this is again reducible to trusting the webapp with your plaintext, since the webapp could selectively intercept any message it chooses.
A bigger related problem: the argument that browser crypto extensions should be high-level (autogenerating secure keys, automatically MAC'ing ciphertexts, picking the block cipher mode for you) is not winning the day. So what we're going to end up with is an OpenSSL-style interface:
x = new Cipher("AES");
x.blockmode = "CBC";
// defaults to all zeroes
// x.iv = "ABCDABCDABCDABCD";
x.key = "YELLOW SUBMARINE";
x.encrypt << "This is my plaintext";
In a sense, this is great news for me, because it means I get another 5-10 years of crypto vulnerabilities to get paid to eradicate. But if you're hoping for simple, usable cryptographically strong security in common web apps... well, keep hoping.
Writing crypto in dynamic languages is hard but not impossible. Writing crypto in dynamic languages with content-controlled code is probably impossible.
Then, I looked to see if the standard constant-time comparisons were in there to resist timing attacks. No dice there.
So... cool. He put a nice wrapper on JSAES[1], jsSHA2[2] by way of webtoolkit.info[3], RSA and ECC in Javascript by Tom Wu[4], and seedrandom.js by David Bau[5].
But then then says it's "New BSD license"[6] when it should be GPL[7].
I didn't start this comment sound negative. But, I think a few things are important:
* Credit authors.
* Respect their licenses.
* Put a big fucking notice on top of your slick webpage: "FOR DEMONSTRATION PURPOSES ONLY-- NOT REAL CRYPTO"
[1] http://point-at-infinity.org/jsaes/ [2] http://anmar.eu.org/projects/jssha2/ [3] http://www.webtoolkit.info/javascript-sha256.html [4] http://www-cs-students.stanford.edu/~tjw/jsbn/ [5] http://davidbau.com/archives/2010/01/30/random_seeds_coded_h... [6] http://code.google.com/p/cryptico/ [7] http://code.google.com/p/cryptico/source/browse/trunk/aes.js