Secure browser-based communications
Introduction
I’ve often wanted to securely send a message to someone who didn’t have a serious software package like GPG installed. Rather than ask them to install software they might not use ever again, I employed the scheme described below – it only requires a web browser with Javascript support.
Our friends Alice and Bob have agreed to help me illustrate this scheme for secure browser-based communications. Eve declined my invitation. She’s busy decrypting debian-vulnerable SSH sessions off the wire.
Contents
The scheme
Alice wants to send Bob a secret message. Bob doesn’t want to fiddle around with any stand-alone crypto software in order to read the secret message. Bob is, however, saavy with his web browser.
- Alice points her browser to an SSL-secured web page (“https://foo.com/aes.html”) which contains a bit of HTML and an inline Javascript implementation of the AES encryption standard.
- Alice uses the form on the web page to encrypt the secret message (“linux rulz”) with the password she chose (“thelegendofdrunkenmaster”). The encryption is performed locally – the secret message does not enter the network nor interact with any software besides the browser’s Javascript engine.
- Alice sends the message encrypted message (“MGfrSbm5ubmqsnbYtoa9cgeYfA==”) to Bob via a second channel – e.g. by reading it to him over the telephone. Alice also gives Bob a hint about the password (“it’s the name of the movie we watched last week – without any spaces”).
- Bob visits the same secured page with ”his” web browser. He types the encrypted message and the password into the form.
- The decrypted message appears on his screen and he compliments Alice on her astute observation.
Potential pitfalls
- The password “hint” should be chosen carefully. If it isn’t, a passive attacker (Eve, when she’s done submitting Valgrind “uninitialized data” warning reports to the Debian project1 ) has a chance at brute-forcing the password. Substituting an ad-hoc “hint” system for well-designed key-exchange mechanisms should be done with caution!
- Alice and Bob should devote an entire browser instance to this task and ”only” to this task. They should close the browser and reboot after handling the decrypted message. If they don’t, malicious browser components, malicious websites, or OS paging could subvert their efforts by revealing the decrypted message to an attacker. I recommend that they use a browser that was ”designed” with security in mind.
- The webserver that serves the encryption/decryption page should be managed by a trusted party. If it isn’t, an active attacker could obtain the decrypted message. Barring port-forwarding and self-signed SSL key hassles, Alice herself could run a small webserver devoted to the purpose.
- Chris Veness’ Javascript emits Base64 encoded ciphertext. Base64’s default alphabet may lend itself to transcription errors if the telephone is chosen as a second channel e.g. “3″ is heard as “E”. In rare cases, this could go undetected by the decoding scheme’s error detection and result in the generation of incorrect plaintext e.g. “linux drulz”. For ”one” clever (ref: genetic algorithms!) solution to the transcription problem, see The PGP word list.
Conclusion
I’ve presented a scheme for secure communications between two parties where the only application software required is a Javascript-capable web browser and a SSL-capable web server.
Using a second channel and carefully-chosen password “hint”, this scheme allows access to high-grade cryptography with minimal “new software” requirements.
An aside: “Damn! I shouldn’t have killed that Emacs buffer!”
I began writing some code for this article in an Emacs scratch buffer. I then proceeded to accidentally kill the buffer before cutting its contents to my kill-ring.
I figured that maybe I could find the “lost” source code in Emacs’ heap so I forced a core dump with `killall –signal ABRT emacs`23.
Next I tried to search for a snippet of the source code (the word “alice”) in the core dump with the `strings(1)` utility. The values for `CUR_ENC` are from the `strings(1)` manpage.
$ for CUR_ENC in s S b l B L; do strings --encoding \
${CUR_ENC} core | grep --ignore-case alice; done
$
No dice! If I had to guess, I’d say that Emacs uses some funky elisp mechanism for allocating memory for the contents of buffers, hence the failure of this naive `strings | grep` search. Suggestions welcome `;]`.
Update 5/12/09 – I should have tried hachoir-grep – it’s UNICODE-aware.
See also
- Ooooooh. Twice in one blog post? I only do it because I love ya, Debian `:]` [↩]
- I’d started emacs in a shell where I’d previously run `ulimit -c unlimited`, thus enabling core dumps. Dog help you if you haven’t done so and need a core dump. [↩]
- Ubuntu disables `/dev/mem` (booooo hissss) IIRC so I didn’t try that route. [↩]



