couchdb-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Patrick Barnes <mrtr...@gmail.com>
Subject Re: Question about validator functions and replication
Date Tue, 29 Mar 2011 23:24:20 GMT
On 29/03/2011 11:54 PM, Robert Newson wrote:
> You can get read access control by separating each users documents
> into a separate database.

That's true, although it complicates whole-system replication and 
deployment. It's probably worth looking at doing, though at the moment 
the encryption method works well enough. (And the volume of 
user-specific data is quite low)

> I'm curious to know where you store the encryption keys such that no
> user can access the key of another user. Whatever you did to solve
> that would seem to be sufficient to prevent the access you were
> concerned about in the first place. Presumably there's also a
> different key per user?

Each application that uses the db uses a common API, defined by a PHP 
library. Encryption/descryption keys are stored within the application's 
configuration, in the same place as application username:password. As I 
said, the db isn't being used directly by users.

I suppose if you wanted to handle the encryption/decryption *inside* 
couchdb itself, you could use update and show functions with the key 
being passed as a parameter.
* As long as https is used, those keys won't be sniffable.
* To get the keys to the user's client, you could store them in 
encrypted form within the user document, with the password as key. (That 
way if the password changes, you only have to re-encrypt one document.)

-Patrick


>
> B.
>
> On 29 March 2011 00:41, Patrick Barnes<mrtrick@gmail.com>  wrote:
>> On 29/03/2011 2:38 AM, Nebu Pookins wrote:
>>>>
>>>> If you have some secure data floating around in your db, encryption can
>>>>>   still be a good idea. Parts of one of my databases are encrypted,
>>>>> because
>>>>>   users need to be able to see some documents in the db but not others.
>>>
>>> I'm curious as how you've implemented encryption in your DB. Was it
>>> pure JavaScript, or did you use native libraries? Elsewhere in this
>>> thread, I've started a new "branch" where I've started outlining my
>>> concerns with a pure JavaScript solution and wondered if cryptography
>>> could be included as a core feature of CouchDB.
>>
>> I'm using couchdb as a database, not to serve up pages directly to users. As
>> a consequence, a 'user' is a web application, and multiple applications have
>> differing levels of access to the database.
>>
>> Each application is allowed to store it's own 'application data' documents
>> and I override two methods in my document class to allow transparent
>> decryption/encryption of those docs when read/written. (see below)
>>
>> The reason I implemented encryption is that there's no per-doc read access
>> control in couchdb, so without encryption, I'm not able to prevent
>> applications from accessing another application's document. It's not as good
>> a solution as proper access control.
>>
>> -Patrick
>>
>>
>>         /**
>>          * Given an object - load all the attributes from it into the
>> document - displacing existing attributes.
>>      * If the data field is encrypted, attempts to decrypt it.
>>          * @param stdClass $obj : An object with the desired attributes.
>>          **/
>>         public function loadFromObject(stdClass $obj) {
>>         parent::loadFromObject($obj);
>>         if ($this->doc_type != 'appdata') throw new
>> InvalidArgumentException("Wrong object type - Cgm_Appdata is for appdata
>> only");
>>
>>         //Does the data section need to be decrypted?
>>         if (isset($this->encrypted) and $this->encrypted == true) {
>>             // Check that decryption info is stored
>>             $conf = Cgm_Document_Gateway::getAppConfig($this->source);
>>             if (!$conf->decrypt) throw new LogicException("Cannot load
>> document - no decryption is configured, and the document is encrypted.");
>>
>>             // Decrypt and decode the data
>>             $decryptor = new Zend_Filter_Decrypt($conf->decrypt);
>>
>>             $raw = base64_decode($this->data);
>>             $plain_json = trim($decryptor->filter($raw));
>>             $plain = json_decode($plain_json);
>>
>>             if ($plain === NULL) throw new LogicException("Cannot load
>> document - decryption configuration is incorrect.");
>>
>>             // Store the plain data within the object, in the same way as a
>> non-encrypted object.
>>             $this->data = $plain;
>>             unset($this->encrypted);
>>         }
>>         }
>>
>>     /**
>>      * Export to an object.
>>      * If encryption is configured, attempts to encrypt the data field.
>>      * @return stdClass $obj
>>      */
>>     public function exportToObject() {
>>         $obj = parent::exportToObject();
>>
>>         //Should the data section be encrypted?
>>         $conf = Cgm_Document_Gateway::getAppConfig($this->source);
>>         if ($conf->encrypt) {
>>             $encryptor = new Zend_Filter_Encrypt($conf->encrypt);
>>             $cryptdata = base64_encode( $encryptor->filter(
>> Zend_Json::encode($obj->data) ) );
>>             $obj->data = $cryptdata;
>>             $obj->encrypted = true;
>>         }
>>         //Was it encrypted before? - ensure that the flag is cleared
>>         elseif (isset($obj->encrypted)) {
>>             $obj->encrypted = false;
>>         }
>>
>>         return $obj;
>>     }
>>
>

Mime
View raw message