summaryrefslogtreecommitdiff
path: root/src/leap/soledad/backends
diff options
context:
space:
mode:
authordrebs <drebs@leap.se>2013-04-23 10:22:05 -0300
committerdrebs <drebs@leap.se>2013-04-23 10:22:05 -0300
commitb48f000e311daf543a8b8f776c5438725485bffd (patch)
tree6872e00de2e9ae749cec285569d497c0739e32cb /src/leap/soledad/backends
parent23e1a6404d31070364654b8138cfe21f07239974 (diff)
Separate crypto-related stuff from Soledad class.
This creates a SoledadCrypto object that should encapsulate everything related to crypto in Soledad. Also, replace hmac for sha256 when creating hashes.
Diffstat (limited to 'src/leap/soledad/backends')
-rw-r--r--src/leap/soledad/backends/leap_backend.py41
-rw-r--r--src/leap/soledad/backends/sqlcipher.py35
2 files changed, 40 insertions, 36 deletions
diff --git a/src/leap/soledad/backends/leap_backend.py b/src/leap/soledad/backends/leap_backend.py
index 4ea131c0..687b59ef 100644
--- a/src/leap/soledad/backends/leap_backend.py
+++ b/src/leap/soledad/backends/leap_backend.py
@@ -42,7 +42,7 @@ class NoDefaultKey(Exception):
pass
-class NoSoledadInstance(Exception):
+class NoSoledadCryptoInstance(Exception):
"""
Exception to signal that no Soledad instance was found.
"""
@@ -69,7 +69,7 @@ class LeapDocument(Document):
"""
def __init__(self, doc_id=None, rev=None, json='{}', has_conflicts=False,
- encrypted_json=None, soledad=None, syncable=True):
+ encrypted_json=None, crypto=None, syncable=True):
"""
Container for handling an encryptable document.
@@ -84,14 +84,14 @@ class LeapDocument(Document):
@param encrypted_json: The encrypted JSON string for this document. If
given, the decrypted value supersedes any raw json string given.
@type encrypted_json: str
- @param soledad: An instance of Soledad so we can encrypt/decrypt
+ @param crypto: An instance of SoledadCrypto so we can encrypt/decrypt
document contents when syncing.
- @type soledad: soledad.Soledad
+ @type crypto: soledad.Soledad
@param syncable: Should this document be synced with remote replicas?
@type syncable: bool
"""
Document.__init__(self, doc_id, rev, json, has_conflicts)
- self._soledad = soledad
+ self._crypto = crypto
self._syncable = syncable
if encrypted_json:
self.set_encrypted_json(encrypted_json)
@@ -103,17 +103,20 @@ class LeapDocument(Document):
@return: The encrypted JSON serialization of document's contents.
@rtype: str
"""
- if not self._soledad:
- raise NoSoledadInstance()
- return self._soledad.encrypt_symmetric(self.doc_id,
- self.get_json())
+ if not self._crypto:
+ raise NoSoledadCryptoInstance()
+ return self._crypto.encrypt_symmetric(
+ self.get_json(),
+ self._crypto._hash_passphrase(self.doc_id))
def set_encrypted_content(self, cyphertext):
"""
Decrypt C{cyphertext} and set document's content.
contents.
"""
- plaintext = self._soledad.decrypt_symmetric(self.doc_id, cyphertext)
+ plaintext = self._crypto.decrypt_symmetric(
+ cyphertext,
+ self._crypto._hash_passphrase(self.doc_id))
self.set_json(plaintext)
def get_encrypted_json(self):
@@ -131,8 +134,8 @@ class LeapDocument(Document):
Set document's content based on a valid JSON string containing the
encrypted document's contents.
"""
- if not self._soledad:
- raise NoSoledadInstance()
+ if not self._crypto:
+ raise NoSoledadCryptoInstance()
cyphertext = json.loads(encrypted_json)['_encrypted_json']
self.set_encrypted_content(cyphertext)
@@ -196,7 +199,7 @@ class LeapSyncTarget(HTTPSyncTarget):
receiving.
"""
- def __init__(self, url, creds=None, soledad=None):
+ def __init__(self, url, creds=None, crypto=None):
"""
Initialize the LeapSyncTarget.
@@ -210,7 +213,7 @@ class LeapSyncTarget(HTTPSyncTarget):
@type soledad: soledad.Soledad
"""
HTTPSyncTarget.__init__(self, url, creds)
- self._soledad = soledad
+ self._crypto = crypto
def _parse_sync_stream(self, data, return_doc_cb, ensure_callback=None):
"""
@@ -244,15 +247,15 @@ class LeapSyncTarget(HTTPSyncTarget):
line, comma = utils.check_and_strip_comma(entry)
entry = json.loads(line)
# decrypt after receiving from server.
- if not self._soledad:
- raise NoSoledadInstance()
+ if not self._crypto:
+ raise NoSoledadCryptoInstance()
enc_json = json.loads(entry['content'])['_encrypted_json']
- if not self._soledad.is_encrypted_sym(enc_json):
+ if not self._crypto.is_encrypted_sym(enc_json):
raise DocumentNotEncrypted(
"Incoming document from sync is not encrypted.")
doc = LeapDocument(entry['id'], entry['rev'],
encrypted_json=entry['content'],
- soledad=self._soledad)
+ crypto=self._crypto)
return_doc_cb(doc, entry['gen'], entry['trans_id'])
if parts[-1] != ']':
try:
@@ -300,7 +303,7 @@ class LeapSyncTarget(HTTPSyncTarget):
# encrypt and verify before sending to server.
enc_json = json.loads(
doc.get_encrypted_json())['_encrypted_json']
- if not self._soledad.is_encrypted_sym(enc_json):
+ if not self._crypto.is_encrypted_sym(enc_json):
raise DocumentNotEncrypted(
"Could not encrypt document before sync.")
size += prepare(id=doc.doc_id, rev=doc.rev,
diff --git a/src/leap/soledad/backends/sqlcipher.py b/src/leap/soledad/backends/sqlcipher.py
index a4d53fa8..288680d4 100644
--- a/src/leap/soledad/backends/sqlcipher.py
+++ b/src/leap/soledad/backends/sqlcipher.py
@@ -38,7 +38,7 @@ from u1db import (
from leap.soledad.backends.leap_backend import LeapDocument
-def open(path, password, create=True, document_factory=None, soledad=None):
+def open(path, password, create=True, document_factory=None, crypto=None):
"""Open a database at the given location.
Will raise u1db.errors.DatabaseDoesNotExist if create=False and the
@@ -58,7 +58,7 @@ def open(path, password, create=True, document_factory=None, soledad=None):
"""
return SQLCipherDatabase.open_database(
path, password, create=create, document_factory=document_factory,
- soledad=soledad)
+ crypto=crypto)
class DatabaseIsNotEncrypted(Exception):
@@ -78,7 +78,7 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
db_handle.cursor().execute("PRAGMA key = '%s'" % key)
def __init__(self, sqlcipher_file, password, document_factory=None,
- soledad=None):
+ crypto=None):
"""
Create a new sqlcipher file.
@@ -89,23 +89,24 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
@param document_factory: A function that will be called with the same
parameters as Document.__init__.
@type document_factory: callable
- @param soledad: An instance of Soledad so we can encrypt/decrypt
+ @param crypto: An instance of SoledadCrypto so we can encrypt/decrypt
document contents when syncing.
- @type soledad: soledad.Soledad
+ @type crypto: soledad.crypto.SoledadCrypto
"""
self._check_if_db_is_encrypted(sqlcipher_file)
self._db_handle = dbapi2.connect(sqlcipher_file)
SQLCipherDatabase.set_pragma_key(self._db_handle, password)
self._real_replica_uid = None
self._ensure_schema()
- self._soledad = soledad
+ self._crypto = crypto
def factory(doc_id=None, rev=None, json='{}', has_conflicts=False,
encrypted_json=None, syncable=True):
return LeapDocument(doc_id=doc_id, rev=rev, json=json,
has_conflicts=has_conflicts,
encrypted_json=encrypted_json,
- syncable=syncable, soledad=self._soledad)
+ syncable=syncable,
+ crypto=self._crypto)
self.set_document_factory(factory)
def _check_if_db_is_encrypted(self, sqlcipher_file):
@@ -131,7 +132,7 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
@classmethod
def _open_database(cls, sqlcipher_file, password, document_factory=None,
- soledad=None):
+ crypto=None):
"""
Open a SQLCipher database.
@@ -142,9 +143,9 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
@param document_factory: A function that will be called with the same
parameters as Document.__init__.
@type document_factory: callable
- @param soledad: An instance of Soledad so we can encrypt/decrypt
+ @param crypto: An instance of SoledadCrypto so we can encrypt/decrypt
document contents when syncing.
- @type soledad: soledad.Soledad
+ @type crypto: soledad.crypto.SoledadCrypto
@return: The database object.
@rtype: SQLCipherDatabase
@@ -171,11 +172,11 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
time.sleep(cls.WAIT_FOR_PARALLEL_INIT_HALF_INTERVAL)
return SQLCipherDatabase._sqlite_registry[v](
sqlcipher_file, password, document_factory=document_factory,
- soledad=soledad)
+ crypto=crypto)
@classmethod
def open_database(cls, sqlcipher_file, password, create, backend_cls=None,
- document_factory=None, soledad=None):
+ document_factory=None, crypto=None):
"""
Open a SQLCipher database.
@@ -191,9 +192,9 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
@param document_factory: A function that will be called with the same
parameters as Document.__init__.
@type document_factory: callable
- @param soledad: An instance of Soledad so we can encrypt/decrypt
+ @param crypto: An instance of SoledadCrypto so we can encrypt/decrypt
document contents when syncing.
- @type soledad: soledad.Soledad
+ @type crypto: soledad.crypto.SoledadCrypto
@return: The database object.
@rtype: SQLCipherDatabase
@@ -201,7 +202,7 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
try:
return cls._open_database(sqlcipher_file, password,
document_factory=document_factory,
- soledad=soledad)
+ crypto=crypto)
except errors.DatabaseDoesNotExist:
if not create:
raise
@@ -211,7 +212,7 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
backend_cls = SQLCipherDatabase
return backend_cls(sqlcipher_file, password,
document_factory=document_factory,
- soledad=soledad)
+ crypto=crypto)
def sync(self, url, creds=None, autocreate=True):
"""
@@ -234,7 +235,7 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
self,
LeapSyncTarget(url,
creds=creds,
- soledad=self._soledad)).sync(autocreate=autocreate)
+ crypto=self._crypto)).sync(autocreate=autocreate)
def _extra_schema_init(self, c):
"""