Matched Client & Server Cryptography
I've been putting together a portal site - partly because I want a portal that does what I want, partly because its one way to learn ruby/rails. I'm very happy with my host (dreamhost ), but one thing I don't get with my plan is SSL. Well, as you might imagine, I store a significant number of passwords and I want to be able to edit them straight from my portal. Not to mention that I would like to be able to log in without sending my password in cleartext across the wire. So, what to do?
First I trawled for an encryption/decryption function written in JavaScript. It took a while but eventually I found this implementation of BlockTEA . I also eventually found this page which has a fairly complete list of JavaScript encryption functions, but by then it was too late.
After I found the BlockTEA JavaScript code I converted it to ruby so that I could encrypt and decrypt on both the client and the server. One small wrinkle was that the encoded string is binary, so I base64 encoded/decoded it on both sides. Something that proved to be pretty easy in Ruby but required another search for code in JavaScript.
So the end result is that I now have matched code on both the client (web browser) and the server that allows me to encrypt and decrypt data while it is in transit between the two. As a side-effect I also have something that allows me to encrypt the passwords as they are saved to the database, and with a slight modification to the ruby YAML code, something that encrypts confidential data as it is serialized to temporary store. So now my confidential data never appears in plain text anywhere.
Sounds great eh? Well, one weakness of this is that you have to use a key to both encrypt and de-crypt the data. How does this key get to the client from the server? Well, over an unencrypted HTTP connection of course. So someone could get a hold of the key if they were determined enough and decrypt whatever they liked. You could reduce the usefulness of such an attack by using a different key for each user, generating the key algorithmically etc. If you do both, you make it harder to get the key and you limit the scope of an attack to just one user.
The standard way around this is to use public-key encryption. In this case anyone can encrypt using the public key, but only I can decrypt (using the private key). The problem here is that it works great if I only need to encrypt in one direction (i.e. the client encrypts form data using a public key that the server gave it before posting it to the server which then decrypts using the private key). But if I also need to encrypt in the other direction (i.e. the server populates form data using encypted values) then I would have to send a private key to the client so that it could decrypt what I've encrypted.
Well. You know what? You can get around that too using a little sprinkling of AJAX. But first you need to add yet another encyption mechanism into the mix called a symetric key algorithm. This is just a regular algorithm like BlockTEA that uses the same key to both encrypt and decrypt. Here's what you do:
- The server sends a public key (and the JavaScript code to use it) to the browser.
- The browser generates a random key, encodes it using the server's public key and sends it to the server using AJAX.
- The server uses its private key to decode the random key and uses a symetric encryption algorithm (such as BlockTEA) to encode the form data using the random key and send it to the web browser as a response to the AJAX call.
- Still with me? The web browser decrypts the form data using the random key that it just generated and populates the form.
- The user edits the form data and posts it back to the server - except the browser intercepts the post and…
- …the browser encrypts the form data using the key it generated earlier and posts it back to the server.
- Which then decrypts it using the random key it was given earlier.
Strangely enough, that's just how SSL works, so we've implemented SSL. using AJAX and JavaScript.
Well. I hope you're not expecting some wonderful JavaScript/AJAX library that implements SSL from me. All I've got to offer ATM is BlockTEA in both JavaScript and Ruby, which, as they say where I come from, is better than a poke in the eye with sharp stick. However this page has a JavaScript implementation of RSA (a public key algorithm) so if you get around to implementing it before I do, let me know. Or I could just pony-up for an SSL enabled account.
Here's a link to the matched BlockTEA JavaScript/Ruby code .






