CakePHP plugin providing highly secured user-level multi-tiered public-key database encryption.

Installs: 37

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 7

Forks: 0

Open Issues: 3

Type:cakephp-plugin

dev-master 2017-04-18 03:30 UTC

This package is not auto-updated.

Last update: 2024-11-09 20:57:27 UTC


README

Build Status License

CakePHP 2.x plugin providing highly-secured public-key encryption to database I/O.

This is a work-in-progress. The implementation, documentation and sample code are not only incomplete, they may also change without notice.

3.x plugin will follow soon.

Lapis is named after Kue lapis, a layered cake from Southeast Asia. Similar to the cake, Lapis plugin incorporates a multi-layered encryption scheme to keep your data safe.

Motivation

TODO: why Lapis

Set up

  1. Install Lapis plugin to your local CakePHP app.

  2. Create the necessary tables by running:

    Console/cake schema create --plugin Lapis
  3. Generate the root key pair(s) by following the guided key generator. You would need at least 1 root key pair to use Lapis.

    Console/cake Lapis.keys generate    # follow the guided prompts

    It is highly recommended to not store private keys unencrypted at the database. If you provide a password to the private key, take note that the password is not stored anywhere in the system. You would have to store the password safely and separately outside of the system.

Sample model

  1. To prepare a model for Lapis secured document, add a text field named document to the associated table.

    ALTER TABLE `table_name` ADD `document` TEXT NULL DEFAULT NULL;

    On top of document field, you are free to still include other conventional fields such as id, created, or custom fields such as title, etc. Take note that data in conventional fields will not be encrypted, but being native, they would continue to enjoy database-level privilege such as indexing, etc.

  2. Update your Model to include Lapis.SecDoc behavior and define document schema. Lapis supports the following JSON data types: string, number, or boolean. If you prefer to not enforce data type, you can either specify a document field as inherit or use a non-associated array.

    For illustration, a Book model with Lapis secured document.

    class Book extends AppModel {
    	public $name = 'Book';
    	public $actsAs = array('Lapis.SecDoc');
    
    	/**
    	 * Either number, string or boolean
    	 */
    	public $documentSchema = array(
    		'author' => 'string',
    		'pages' => 'number',
    		'available' => 'boolean'
    	);
    
    	// or if you prefer to not enforce JSON data types, you can list the schema as such
    	// public $documentSchema = array('author', 'pages', 'available');
    }
  3. To save to a secured document model, you would specify the lowest key(s) you would want to provide access privilege to. Lapis would sign the document for all the specified public keys and their respective ancestors all the way to root key(s).

    $data = array(
    	// Conventional database fields
    	'title' => 'Book Title',
    
    	// Secured document
    	'author' => 'John Doe',
    	'pages' => 488,
    	'available' => true
    );
    
    $this->Book->saveFor = 2;
    $this->Book->saveFor = array(2, 5); // for multiple lowest keys
    
    $this->Book->create();
    $this->Book->save($data);

    Assuming the key hierarchy is as illustrated:

    /*
     * 1 (root) => 2 => 9
     * 3 (root) => 4 => 5
     **/
    
    $this->Book->saveFor = 2;
    // would provide access to keys with IDs: 2 and 1 (its ancestors), but not 3 (even though it is a root key)
    
    $this->Book->saveFor = array(2, 5);
    // would provide access to keys with IDs: 2, 1; and 5, 4, 3.
  4. To query a secured document model, you would have to provide either the unencrypted private key that has privileged access to the document, or the password to the encrypted private key that has privileged access to the document.

    // Specifying unencrypted private key in PEM encoded format, including header and footer.
    $this->Book->requestAs = array('id' => 2, 'unencrypted_key' => 'PEM_ENCODED_UNENCRYPTED_PRIVATE_KEY';
    
    // or, the password to an encrypted private key in `keys` table
    $this->Book->requestAs = array('id' => 23, 'password' => 'PASSWORD_TO_DECRYPT_PVT_KEY');
    
    // if private key is stored unencrypted in database (not recommended), id is all that is required.
    $this->Book->requestAs = array('id' => 23);
    
    $this->Book->find('first', array(
    	'conditons' => array('Book.id' => 2)
    ));
    
    // If the supplied private key has privileged access to the document, unencrypted document fields would be returned normally just like a normal database fields.
    // Otherwise, only database fields would be returned encrypted.

Notes

  1. It is highly recommended to not store private keys unencrypted at the database.