diaspora/diaspora — pull request #3267 by justindthomas (2012-05-17 05:01:03+00:00)
Title: Implement Client Encryption

This request is absolutely not ready to actually pull into the master repository; I'm issuing it now to solicit feedback.

I've implemented a new model (KeyRing) associated with the existing Person model to store encryption keys for browser-based encryption of various elements within Diaspora. To get things kicked off, I've coded hooks in to the Message functionality to encrypt data immediately before conversations and messages are sent to the server. Likewise, I've added functionality to decrypt messages as they are displayed to the recipient. If these subroutines fail, the messages should just be delivered unencrypted, silently.

The keys are generated via a new section in the "Privacy" settings menu. Entropy is required for this process and is collected through the user's mouse movements within the browser window.

The encryption structure is somewhat complex. Every Person may have a KeyRing that contains 4 asymmetric keys - 2 for encryption/decryption and 2 for signing/verification. The secret keys (encryption and signing) are themselves encrypted using a passphrase supplied by the user. That passphrase is never communicated to the server and is used only in the browser. The 384 bit asymmetric keys are for use with an ECC algorithm and the 128 bit symmetric keys are for use with an AES algorithm. The actual encryption math is performed by the included SJCL library.

Each message is AES encrypted to a random key generated by the sender's browser. That key is encrypted to the public ECC key of each recipient and those encrypted symmetric keys are stored with each message. Each message is a Base64 encoded JSON object.

The Conversations view includes a section that has "Entropy" (for generating keys for new messages) and "Passphrase" fields. When a user opens the Conversations view, they will see the Base64 encoded, AES encrypted messages. Only after entering the passphrase to decrypt their secret key (accessible in window.current_user_attributes.key_ring, incidentally) will they be able to decrypt the conversations.

I feel like I need to draw a diagram of how this all works. I am a new Rails programmer, so I absolutely welcome your guidance. I've tried to keep things pretty modular and to keep my JavaScript (of which there is a ton) unobtrusive, but I'm no expert in Rails, let alone in Backbone.js and other supporting libraries.

I know this all works in Firefox and Safari. I know it does not work in IE8 (but I suspect IE9 should be fine).