While not specifically CouchDB related, currently there just is not a good way to deal with this natively in the browser, unless you're using x509 certificates that can be stored in the local device keystore. You should NEVER transmit a private key across the internet. Exposing any kind of private key material into the web client is just not a good idea. I'd suggest using the <keygen> tag to generate a client certificate which the public portion could be countersigned by the remote certificate.  If there is a way for the local client app to verify the counter-signature. You could then operate only with this client cert when disconnected.  There's an example of this sort of workflow here for generating and installing a ert like this here: http://goo.gl/PrxTr 

If you can generate the keys locally and distribute the public key to the remote service... which countersigns and and sends the certificate back to be installed on the client.  You should theoretically be able to store everything encrypted locally with the same private key which never left the client.  The trick is going to be using the private key to decrypt the local data when disconnected, AFAIK this is typically handled by the browser not by the web app.

I'd also advise against using any JS-crypto solution, as the algorithms can be compromised via a XSS scripting attack unless your client can sandbox and secure the algorithms somehow.

There is actually a W3C Web Cryptography working group that is in the process of being chartered this month to work out this very issue: http://www.w3.org/wiki/IdentityCharter

Jim Klo
Senior Software Engineer
Center for Software Engineering
SRI International

On Nov 9, 2011, at 1:13 PM, Jens Alfke wrote:

On Nov 9, 2011, at 9:58 AM, Jay Zamboni wrote:

we want the client application to be able to decrypt data
even when it cannot connect to the server.  This seems to force us to store
the decryption key on the client with the encrypted data.  Storing the key
locally seriously weakens our security so we would want to at least encrypt
the stored key with the users password(+salt).

Is this a pure web-app or will it have native components? iOS has APIs for storing secrets like keys in a secure encrypted “keychain”. I’m sure Android has a similar feature. (Even if you’re going to use a wrapper like PhoneGap to package your app for mobile devices, then that’s likely to have JavaScript bindings for those APIs.)

          Encrypt key using session id and store in couch
As the user goes from page to page we would use the session id to load the
encryption key.  When the user logs out or the session times out, the
session id should not exist anywhere.

I don’t know the implementation details of how CouchDB tracks sessions, but if it stores the currently active session IDs on disk, then this won’t be secure, as an attacker can look at the server’s files and locate both the session key and the server key that was encrypted with it.