From 6306a61d8c6c840a09ea9aa26e439a40dc9b5a9a Mon Sep 17 00:00:00 2001 From: drebs Date: Tue, 18 Dec 2012 18:51:01 -0200 Subject: Refactor and symmetric encryption --- backends/leap.py | 53 ++++++++++++++++++++++++++++++++----------------- backends/objectstore.py | 7 +++---- 2 files changed, 38 insertions(+), 22 deletions(-) (limited to 'backends') diff --git a/backends/leap.py b/backends/leap.py index ce00c8f3..4a496d3e 100644 --- a/backends/leap.py +++ b/backends/leap.py @@ -7,12 +7,15 @@ from u1db import Document from u1db.remote.http_target import HTTPSyncTarget from u1db.remote.http_database import HTTPDatabase import base64 -from soledad import GPGWrapper +from soledad.util import GPGWrapper class NoDefaultKey(Exception): pass +class NoSoledadInstance(Exception): + pass + class LeapDocument(Document): """ @@ -22,41 +25,40 @@ class LeapDocument(Document): """ def __init__(self, doc_id=None, rev=None, json='{}', has_conflicts=False, - encrypted_json=None, default_key=None, gpg_wrapper=None): + encrypted_json=None, soledad=None): super(LeapDocument, self).__init__(doc_id, rev, json, has_conflicts) - # we might want to get already initialized wrappers for testing. - if gpg_wrapper is None: - self._gpg = GPGWrapper() - else: - self._gpg = gpg_wrapper + self._soledad = soledad if encrypted_json: self.set_encrypted_json(encrypted_json) - self._default_key = default_key def get_encrypted_json(self): """ Returns document's json serialization encrypted with user's public key. """ - if self._default_key is None: - raise NoDefaultKey() - cyphertext = self._gpg.encrypt(self.get_json(), - self._default_key, - always_trust = True) - # TODO: always trust? - return json.dumps({'cyphertext' : str(cyphertext)}) + if not self._soledad: + raise NoSoledadInstance() + cyphertext = self._soledad.encrypt_symmetric(self.get_json()) + return json.dumps({'_encrypted_json' : cyphertext}) def set_encrypted_json(self, encrypted_json): """ Set document's content based on encrypted version of json string. """ - cyphertext = json.loads(encrypted_json)['cyphertext'] - plaintext = str(self._gpg.decrypt(cyphertext)) + if not self._soledad: + raise NoSoledadInstance() + cyphertext = json.loads(encrypted_json)['_encrypted_json'] + plaintext = self._soledad.decrypt_symmetric(cyphertext) return self.set_json(plaintext) class LeapDatabase(HTTPDatabase): """Implement the HTTP remote database API to a Leap server.""" + def __init__(self, url, document_factory=None, creds=None, soledad=None): + super(LeapDatabase, self).__init__(url, creds=creds) + self._soledad = soledad + self._factory = LeapDocument + @staticmethod def open_database(url, create): db = LeapDatabase(url) @@ -74,9 +76,21 @@ class LeapDatabase(HTTPDatabase): st._creds = self._creds return st + def create_doc_from_json(self, content, doc_id=None): + if doc_id is None: + doc_id = self._allocate_doc_id() + res, headers = self._request_json('PUT', ['doc', doc_id], {}, + content, 'application/json') + new_doc = self._factory(doc_id, res['rev'], content, soledad=self._soledad) + return new_doc + class LeapSyncTarget(HTTPSyncTarget): + def __init__(self, url, creds=None, soledad=None): + super(LeapSyncTarget, self).__init__(url, creds) + self._soledad = soledad + def _parse_sync_stream(self, data, return_doc_cb, ensure_callback=None): """ Does the same as parent's method but ensures incoming content will be @@ -97,8 +111,10 @@ class LeapSyncTarget(HTTPSyncTarget): raise BrokenSyncStream line, comma = utils.check_and_strip_comma(entry) entry = json.loads(line) + # decrypt after receiving from server. doc = LeapDocument(entry['id'], entry['rev'], - encrypted_json=entry['content']) + encrypted_json=entry['content'], + soledad=self._soledad) return_doc_cb(doc, entry['gen'], entry['trans_id']) if parts[-1] != ']': try: @@ -142,6 +158,7 @@ class LeapSyncTarget(HTTPSyncTarget): ensure=ensure_callback is not None) comma = ',' for doc, gen, trans_id in docs_by_generations: + # encrypt before sending to server. size += prepare(id=doc.doc_id, rev=doc.rev, content=doc.get_encrypted_json(), gen=gen, trans_id=trans_id) diff --git a/backends/objectstore.py b/backends/objectstore.py index 298bdda3..a8e139f7 100644 --- a/backends/objectstore.py +++ b/backends/objectstore.py @@ -1,8 +1,7 @@ import uuid from u1db.backends import CommonBackend -from u1db import errors -from soledad import SyncLog, TransactionLog -from soledad.backends.leap import LeapDocument +from u1db import errors, Document +from soledad.util import SyncLog, TransactionLog class ObjectStore(CommonBackend): @@ -11,7 +10,7 @@ class ObjectStore(CommonBackend): # This initialization method should be called after the connection # with the database is established, so it can ensure that u1db data is # configured and up-to-date. - self.set_document_factory(LeapDocument) + self.set_document_factory(Document) self._sync_log = SyncLog() self._transaction_log = TransactionLog() self._ensure_u1db_data() -- cgit v1.2.3