Hacker News new | past | comments | ask | show | jobs | submit login
My weekend project - AES encryption for Gmail or anything else (encipher.it)
152 points by eran on June 14, 2011 | hide | past | favorite | 67 comments

Wouldn't it make more sense to revive FireGPG[1] and, while you're at it, port it to all other major browsers?

I am still disappointed that PGP in the browser never gained traction. Not only would it help with e-mail security, it could also be used for passwordless website logins, portable web identities, all that jazz[2].

One proper, user-friendly browser plugin could put an end to all those nasty kludges called OAuth, OpenID, LastPass, etc...

[1] http://getfiregpg.org/s/home

[2] http://en.wikipedia.org/wiki/Web_of_trust

I'm currently working on this. So far, recognition of encrypted text and decryption works fine. However, it breaks Gmail if the text is part of an email there - only reloading get's it to work again.

Since I have zero experience with JS, I'm thankful for any help. Code is on: https://github.com/Mononofu/CryptoChrome

The plugin I'm using was compiled on Ubuntu x64 and probably doesn't work anywhere else. It was written using firebreath, basically it's just a wrapper to gpg.

Are there any webmail providers out there that support PGP? GMail never will since it needs the ability to read your email to show you ads.

> GMail never will since it needs the ability to read your email to show you ads.

It could still read your email after decryption and show ads based on that, it would be easy to do with JS. Search would be broken though unless they encrypt each word separately, but that would make your inbox size grow quickly, still doable.

HushMail and Countermail do. I think it never really caught on because if you really care about end-to-end security, you wouldn't be using a webmail provider.

HushMail has a java based browser that's supposed to be all client side, but last time I tried hush, they generated keys that were incompatible with GPG2.

But yeah, like you said, if you're only checking emails on machines that are secure and in your control, you might as well just install Tbird/Enigmail. And if you're at the library or a computer lab, you can't trust the client to be secure.

If you had a working (and secure) crypto on the client side you could use a webmail provider and still be secure.

I can imagine an extension for Chrome or Firefox that will not be updated without my knowledge and has been peer reviewed like gnupg.

As long as the extension does not then place the cleartext back into the DOM. I would also want support on my Android phone too. So I guess basically, it's never happening.

If I can't safely check my mail from random computers anyway, I'd just as soon remove the browser from the equation and use a GPG-compatible mail client.

Your key derivation function is pretty weak. Looking at your code you are doing SHA256(password entered by user). You should take a look at using http://en.wikipedia.org/wiki/PBKDF2 for the key derivation. SHA256 is really fast and given that you are getting entropy from some user entered password (which is likely to be badly chosen) you want something _slow_ to derive the key. Hence PBKDF2 with lots of iterations.

Thank you point me out. Definitely, I need to implement PBKDF2 (and add salt to password). I planning this, but weekend is too short and finally I just put SHA256 for key derivation. But, until you describe, I do not recognize what the principal difference between hash and password based key derivation function, thanks.

I assume you know that the reason you add a salt is to prevent rainbow table attacks. Without a salt, if someone obtains the hash then they need to just run it through a single rainbow table and with very high probability, obtain the password.

A SHA{1,2,3,128,256,512} hash is very VERY VERY fast. So fast, in fact, that an attacker who has the hash could easily run through all 8 character passwords given a few GPU machine clusters.

PBKDF2 is very much like a SHA hash, but it is repeated over and over. Instead of just salt||SHA1(password||salt) you compute salt||SHA1(SHA1(SHA1(SHA1(SHA1(password||salt))))). This makes it so an attacker with the hash has to do much more work in order to brute force the password.

Now, that's not exactly how it works, but just read the wikipedia article for that.

What you described is essentially PBKDF1, which is similar to PBKDF2, but only supports a fixed output key length. It's also a decent option; just not as flexible as PBKDF2.

I was describing it in order to explain the general idea; not to explain the exact algorithm. The wikipedia article does a better job at that than I could do, but since he asked the question after the link to the wikipedia article I assumed that what he wanted was a simple explanation of what the difference is between just SHA(password) and PBKDF(password).

How does bcrypt stack up against PBKDF2?

They're both good. I'd pick bcrypt, but if you're using PBKDF2, it's probably because it's simpler to implement.

Today I've updated key derivation to use pbkdf2 (1000 cycles, google chrome execution time around 2 sec)

You should consider moving to https. After all, what's the point in providing this kind of script if anyone can MITM it ?

Besides that, this is pretty cool. Could you provide a standalone bookmarlet which doesn't need to download any scripts ?

He'd also need to HTTPS all the scripts that script requires, and devise some way to ensure that the script was never called from a page that itself included any HTML or JS over a non-HTTPS connection, because any of those document loads could also MITM the script. Isn't Javascript crypto fun!

Yes, I will install ssl cert in future (at least self signed), understand the risk. Standalone bookmark is great idea, but I am not sure if I can fit script to 2048 bytes. Maybe, I'll make html5 cache manifest to avoid network access.

Even if you could somehow minify all of AES into a bookmarklet, you'd still lose any time any page this ran from requested HTML or JS from a non-HTTPS link, since any of those requests could poison the runtime.

Would using SPDY help?

Not in and of itself. Google runs SPDY over SSL, just as they also run HTTP over SSL (HTTPS). It's the SSL that makes it secure. Once you're running one protocol over SSL, you might as well run all of them over SSL.

The basic problem here is that JS is too dynamic to ensure this type of security. Any script running on the page can rebind any value, monitor or trigger any event, or a number of other things. Without SSL or similar, an attacker can inject any script they want into the page.

The simplest variant of such an attack would be a script that replaces your AES function with a ROT13 or other useless cipher. There are variations on this theme, and in the end it's impossible to defend against all of them.

Caja / Secure EcmaScript should fix the JS-too-dynamic problem. I haven't tried it out yet.

It doesn't help in this case, since an attacker can just insert plain old JS. Caja (and similar things) only help for code you can actually put through the Cajoler.

It's still a good, if imperfect, solution for other use-cases.

Don't do your self the disservice of self-signed - you can get a free cert from startssl.

The CA landscape has changed.... what used to be expensive and required a lot of paperwork is getting cheap/free, and CAs are pushing "Extended validation" certificates and whatnot (the ones that turn your browser bar green, etc....)

Just hit up startssl and get a real certificate... it's that easy. No strings attached.

(Repeating this because I ignored it for about a year until actually checking it out and realizing I'd been an idiot)


Given the single utility of this - just inline the scripts you need and avoid the request overhead. You can probably strip out all the functions you don't need to minimize the load time. You could offer a minimized version as well....


Very cool! Thanks!

Thank you for advice about cert service! Awesome. Will request SSL cert right now. I consciously left scripts uncompressed, so anybody can look what going on behind the scene. Also, I'll publish source code on github as soon as clean it up. Then I make compressed version.

The "other" reason to avoid a self signed cert is that a self signed cert still leaves your users open to a MITM attack. If your goal is to avoid a MITM, a self signed cert gives you nothing but more configuration lines in your webserver config.

It's only free for one year. It's a bait.

You would be able to get past 2048bytes using mozilla or chromium

See there: https://www.squarefree.com/bookmarklets/limits.html

I just tested a 1Mb bookmarlet on chromium and it works.

Thank you for link, very interesting stats. FF also has reasonable URL limit. At least for some browsers I can do it.

MITM issue fixed, all resources are loading over SSL

While I won't point out the technical reasons why encryption is hard, I will say that I think this project is cool.

I think encryption is something more people might use if it were accessible.

But it's hard enough as it is without making it so easy that Joe Sixpack could use it -- especially since implementations as we know it require Joe Sixpack to understand what he's doing or else the encryption fails.

However, tools like this at least give us prototypes for ideas that could one-day bridge the gap.

Good job, dude. Hope you stick with it and find a way to make it better.

I found your "Joe Sixpack" reference extremely comical.

Note that Gmail automatically saves your draft as you type it. So while this will offer some protection for the message while it's in transit from Google's server to your destination, your unencrypted message draft will still be sent to Google's servers (and given Google Apps' distributed architecture, I'm not sure you can determine where that unencrypted copy could end up or when it'd be erased).

Perhaps a way around that could be to enhance a text input field so that only the final encrypted message is written to it, so Google's app does not see the plain text.

Firegpg used to support disabled drafts

I feel like this would be better as a browser extension instead of a bookmarklet... I get a bit queasy about the potential for MITM with this implementation. An extension that could bring GPG to the mix, would be VERY awesome (if that doesn't exist, I actually haven't tried searching for that...).

Cool project though :)

Who are you protecting the message from when you do this? Gmail? But they can just send the cleartext to the server before you click "encrypt it", and in fact they do (drafts).

Don't type stuff into a program you didn't write if you don't want the author to see it.


Typing The Letters A-E-S Into Your Code? You’re Doing It Wrong

This is great, I was just thinking the other day that it should be possible to encrypt gmail messages. Now you should make it possible to encrypt GChat messages automatically when I hit Send, and then decrypt them when they are received, that way they are encrypted end to end, instead of just between my browser and the server :-)

If you use Pidgin, you can do just that with the Pidgin-Encryption plugin. Both parties need the plugin installed, though.


OTR supports this for pidgin, and has a proxy for other clients: http://www.cypherpunks.ca/otr/

>Weekend project


Choose one.

Also: "Browser-based." "Secure." Choose one.

Thats pretty neat since you have of the encryption done client side. Which mode of AES do you use?

I use counter mode with 256 bit key Key is generated as sha256 hash of the user password

That's also not a secure way of generating an AES key; those crypto keys can be cracked quickly. The problem you're trying to solve is the entire reason for PBKDF2.

You should also use SJCL's AES.

You should also use SJCL's AES.

Here's the link: http://bitwiseshiftleft.github.com/sjcl/

Obligatory link to Nate Lawson's article on in-page crypto: http://rdist.root.org/2010/11/29/final-post-on-javascript-cr...

This implementation is broken. It concatenates a hash of the plaintext to a CTR-mode ciphertext. That's weakly authenticated and leaks information about the plaintext.

It would be better to HMAC the ciphertext with a second key value.

Fixed. Thank you for advice about HMAC, now I am use it.

Very cool. Something like that for GPG encrypted emails would be great.

This is interesting, but s/mime is the proper way to encrypt and/or sign emails.

I am not sure though, if it is possible to create a multipart message using JavaScript in gmail.

I'm pretty amateur on cryptography, and this is cool and everything for basic security, but for those more in the know does the fact that the algorithm knows a password is "wrong" weaken the cryptography (I realise it's a cool feature of this app, I'm talking generally)? Presumably you would have to test each decrypted result for language words etc. otherwise to know if you had decrypted it correctly.

Or prepend a known header to the plaintext you're encrypting..

This is neat. Would it be possible to extend it such that you could drop a key file into the password box to do the encryption/decryption?

Sure, but on modern browsers only (utilizing html5 file API). I am thinking about implementing RSA private key generation and online public key registry in future.

Hmm, testing it out it constantly confuses weather it should be encrypting or decrypting. I've tried to enter a message and had it request a decryption password.

That combined with the poor crypto practices makes it rather unusable, but it's a fantastic concept! Just needs a bit of work.

This is an awesome way of doing things. I'm going to be doing a slightly different implementation of this for my WIRE project on the advice of a bunch of people (more intense key differentiation, for a start), but it's good to know people are starting to do this :)

Edit: Just finished implementing this using the Stanford library - check it out (non-SSL test site) http://wire.0xf.nl

Nicely done. Roundcubemail has been struggling with email encryption for a while now. I would love to see you solution in a plugin: http://trac.roundcube.net/wiki/Plugin_Repository

This tool is interesting and the page has a nice design.

I also created recently a weekend project based on client-side encryption: https://whisperpassword.com , I need to learn about design though ;-)

Check this out and see if it can help in any way (at least for Chrome):


Very nice. I've been thinking of something like this for my project as well. The problem I face is how do you securely exchange the key.

You might also want to fix the typo:

"Firefox or Goole Chrome:" (missing _g_ in Google)

Gotta say, awesome work so far! Encryption aside, this is a great concept.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact