From 15a5b15cf1a03cc3fbb68bfccf4cd32af8479f2a Mon Sep 17 00:00:00 2001 From: drebs Date: Mon, 24 Dec 2012 12:39:35 -0200 Subject: Load local u1db encrypted database. --- src/leap/soledad/__init__.py | 84 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 3 deletions(-) (limited to 'src/leap/soledad/__init__.py') diff --git a/src/leap/soledad/__init__.py b/src/leap/soledad/__init__.py index 6a3707ea..f0d1cbb9 100644 --- a/src/leap/soledad/__init__.py +++ b/src/leap/soledad/__init__.py @@ -7,13 +7,18 @@ import string import random import cStringIO import hmac +from backends import sqlcipher from soledad.util import GPGWrapper class Soledad(object): - PREFIX = os.environ['HOME'] + '/.config/leap/soledad' - SECRET_PATH = PREFIX + '/secret.gpg' - GNUPG_HOME = PREFIX + '/gnupg' + # paths + PREFIX = os.environ['HOME'] + '/.config/leap/soledad' + SECRET_PATH = PREFIX + '/secret.gpg' + GNUPG_HOME = PREFIX + '/gnupg' + U1DB_PATH = PREFIX + '/soledad.u1db' + + # other configs SECRET_LENGTH = 50 def __init__(self, user_email, gpghome=None): @@ -31,13 +36,29 @@ class Soledad(object): if not self._has_secret(): self._gen_secret() self._load_secret() + # instantiate u1db + # TODO: verify if secret for sqlcipher should be the same as the one + # for symmetric encryption. + self._db = sqlcipher.open(self.U1DB_PATH, True, self._secret) + + #------------------------------------------------------------------------- + # Symmetric secret management + #------------------------------------------------------------------------- def _has_secret(self): + """ + Verify if secret for symmetric encryption exists on local encrypted file. + """ + # TODO: verify if file is a GPG-encrypted file and if we have the + # corresponding private key for decryption. if os.path.isfile(self.SECRET_PATH): return True return False def _load_secret(self): + """ + Load secret for symmetric encryption from local encrypted file. + """ try: with open(self.SECRET_PATH) as f: self._secret = str(self._gpg.decrypt(f.read())) @@ -45,14 +66,24 @@ class Soledad(object): raise IOError('Failed to open secret file %s.' % self.SECRET_PATH) def _gen_secret(self): + """ + Generate a secret for symmetric encryption and store in a local encrypted file. + """ self._secret = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(self.SECRET_LENGTH)) ciphertext = self._gpg.encrypt(self._secret, self._fingerprint, self._fingerprint) f = open(self.SECRET_PATH, 'w') f.write(str(ciphertext)) f.close() + #------------------------------------------------------------------------- + # OpenPGP keypair management + #------------------------------------------------------------------------- def _has_openpgp_keypair(self): + """ + Verify if there exists an OpenPGP keypair for this user. + """ + # TODO: verify if we have the corresponding private key. try: self._gpg.find_key(self._user_email) return True @@ -60,6 +91,9 @@ class Soledad(object): return False def _gen_openpgp_keypair(self): + """ + Generate and OpenPGP keypair for this user. + """ params = self._gpg.gen_key_input( key_type='RSA', key_length=4096, @@ -69,19 +103,63 @@ class Soledad(object): self._gpg.gen_key(params) def _load_openpgp_keypair(self): + """ + Find fingerprint for this user's OpenPGP keypair. + """ self._fingerprint = self._gpg.find_key(self._user_email)['fingerprint'] + def publish_pubkey(self, keyserver): + pass + + #------------------------------------------------------------------------- + # Data encryption/decryption + #------------------------------------------------------------------------- + def encrypt(self, data, sign=None, passphrase=None, symmetric=False): + """ + Encrypt data. + """ return str(self._gpg.encrypt(data, self._fingerprint, sign=sign, passphrase=passphrase, symmetric=symmetric)) def encrypt_symmetric(self, doc_id, data, sign=None): + """ + Encrypt data using symmetric secret. + """ h = hmac.new(self._secret, doc_id).hexdigest() return self.encrypt(data, sign=sign, passphrase=h, symmetric=True) def decrypt(self, data, passphrase=None, symmetric=False): + """ + Decrypt data. + """ return str(self._gpg.decrypt(data, passphrase=passphrase)) def decrypt_symmetric(self, doc_id, data): + """ + Decrypt data using symmetric secret. + """ h = hmac.new(self._secret, doc_id).hexdigest() return self.decrypt(data, passphrase=h) + + #------------------------------------------------------------------------- + # Document storage/retrieval and sync + #------------------------------------------------------------------------- + + def put(self, doc_id, data): + """ + Store a document in the local encrypted database. + """ + pass + + def get(self, doc_id): + """ + Retrieve a document from the local encrypted database. + """ + pass + + def sync(self): + """ + Synchronize the local encrypted database with LEAP server. + """ + pass -- cgit v1.2.3 From bc83c4e3ce0bed00604fa876eff4c77da7531aa8 Mon Sep 17 00:00:00 2001 From: drebs Date: Mon, 24 Dec 2012 13:02:47 -0200 Subject: Add basic doc methods mapping for local encrypted storage. --- src/leap/soledad/__init__.py | 48 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 7 deletions(-) (limited to 'src/leap/soledad/__init__.py') diff --git a/src/leap/soledad/__init__.py b/src/leap/soledad/__init__.py index f0d1cbb9..3ed82ca7 100644 --- a/src/leap/soledad/__init__.py +++ b/src/leap/soledad/__init__.py @@ -146,20 +146,54 @@ class Soledad(object): # Document storage/retrieval and sync #------------------------------------------------------------------------- - def put(self, doc_id, data): + def put_doc(self, doc): """ - Store a document in the local encrypted database. + Update a document in the local encrypted database. """ - pass + return self._db.put_doc(doc) - def get(self, doc_id): + def delete_doc(self, doc): + """ + Delete a document from the local encrypted database. + """ + return self._db.delete_doc(doc) + + def get_doc(self, doc_id, include_deleted=False): """ Retrieve a document from the local encrypted database. """ - pass + return self._db.get_doc(doc_id, include_deleted=include_deleted) + + def get_docs(self, doc_ids, check_for_conflicts=True, + include_deleted=False): + """ + Get the content for many documents. + """ + return self._db.get_docs(doc_ids, + check_for_conflicts=check_for_conflicts, + include_deleted=include_deleted) + + def create_doc(self, content, doc_id=None): + """ + Create a new document in the local encrypted database. + """ + return self._db.create_doc(content, doc_id=doc_id) + + def get_doc_conflicts(self, doc_id): + """ + Get the list of conflicts for the given document. + """ + return self._db.get_doc_conflicts(doc_id) - def sync(self): + def resolve_doc(self, doc, conflicted_doc_revs): + """ + Mark a document as no longer conflicted. + """ + return self._db.resolve_doc(doc, conflicted_doc_revs) + + def sync(self, url): """ Synchronize the local encrypted database with LEAP server. """ - pass + # TODO: create authentication scheme for sync with server. + return self._db.sync(url, creds=None, autocreate=True) -- cgit v1.2.3 From 7aee1e34baeafcc12d44c304bac7fb6fcf3be562 Mon Sep 17 00:00:00 2001 From: drebs Date: Thu, 27 Dec 2012 11:09:39 -0200 Subject: Fix imports and namespaces --- src/leap/soledad/__init__.py | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'src/leap/soledad/__init__.py') diff --git a/src/leap/soledad/__init__.py b/src/leap/soledad/__init__.py index 3ed82ca7..6c313f77 100644 --- a/src/leap/soledad/__init__.py +++ b/src/leap/soledad/__init__.py @@ -5,10 +5,10 @@ import os import string import random -import cStringIO import hmac -from backends import sqlcipher -from soledad.util import GPGWrapper +from leap.soledad.backends import sqlcipher +from leap.soledad.util import GPGWrapper +import util class Soledad(object): @@ -27,12 +27,12 @@ class Soledad(object): os.makedirs(self.PREFIX) if not gpghome: gpghome = self.GNUPG_HOME - self._gpg = GPGWrapper(gpghome=gpghome) - # load OpenPGP keypair + self._gpg = util.GPGWrapper(gpghome=gpghome) + # loaa/generate OpenPGP keypair if not self._has_openpgp_keypair(): self._gen_openpgp_keypair() self._load_openpgp_keypair() - # load secret + # load/generate secret if not self._has_secret(): self._gen_secret() self._load_secret() @@ -42,7 +42,7 @@ class Soledad(object): self._db = sqlcipher.open(self.U1DB_PATH, True, self._secret) #------------------------------------------------------------------------- - # Symmetric secret management + # Management of secret for symmetric encryption #------------------------------------------------------------------------- def _has_secret(self): @@ -76,7 +76,7 @@ class Soledad(object): f.close() #------------------------------------------------------------------------- - # OpenPGP keypair management + # Management of OpenPGP keypair #------------------------------------------------------------------------- def _has_openpgp_keypair(self): @@ -92,7 +92,7 @@ class Soledad(object): def _gen_openpgp_keypair(self): """ - Generate and OpenPGP keypair for this user. + Generate an OpenPGP keypair for this user. """ params = self._gpg.gen_key_input( key_type='RSA', @@ -109,10 +109,13 @@ class Soledad(object): self._fingerprint = self._gpg.find_key(self._user_email)['fingerprint'] def publish_pubkey(self, keyserver): + """ + Publish OpenPGP public key to a keyserver. + """ pass #------------------------------------------------------------------------- - # Data encryption/decryption + # Data encryption and decryption #------------------------------------------------------------------------- def encrypt(self, data, sign=None, passphrase=None, symmetric=False): @@ -143,7 +146,7 @@ class Soledad(object): return self.decrypt(data, passphrase=h) #------------------------------------------------------------------------- - # Document storage/retrieval and sync + # Document storage, retrieval and sync #------------------------------------------------------------------------- def put_doc(self, doc): @@ -197,3 +200,5 @@ class Soledad(object): """ # TODO: create authentication scheme for sync with server. return self._db.sync(url, creds=None, autocreate=True) + +__all__ = ['util'] -- cgit v1.2.3 From eae9fd4b5d93845fc708abb722714ebf9d003418 Mon Sep 17 00:00:00 2001 From: drebs Date: Sun, 20 Jan 2013 16:29:53 -0200 Subject: SQLCipher backend syncs using a LeapSyncTarget. --- src/leap/soledad/__init__.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'src/leap/soledad/__init__.py') diff --git a/src/leap/soledad/__init__.py b/src/leap/soledad/__init__.py index 6c313f77..26e982ba 100644 --- a/src/leap/soledad/__init__.py +++ b/src/leap/soledad/__init__.py @@ -13,10 +13,10 @@ import util class Soledad(object): # paths - PREFIX = os.environ['HOME'] + '/.config/leap/soledad' - SECRET_PATH = PREFIX + '/secret.gpg' - GNUPG_HOME = PREFIX + '/gnupg' - U1DB_PATH = PREFIX + '/soledad.u1db' + PREFIX = os.environ['HOME'] + '/.config/leap/soledad' + SECRET_PATH = PREFIX + '/secret.gpg' + GNUPG_HOME = PREFIX + '/gnupg' + LOCAL_DB_PATH = PREFIX + '/soledad.u1db' # other configs SECRET_LENGTH = 50 @@ -28,7 +28,7 @@ class Soledad(object): if not gpghome: gpghome = self.GNUPG_HOME self._gpg = util.GPGWrapper(gpghome=gpghome) - # loaa/generate OpenPGP keypair + # load/generate OpenPGP keypair if not self._has_openpgp_keypair(): self._gen_openpgp_keypair() self._load_openpgp_keypair() @@ -39,7 +39,7 @@ class Soledad(object): # instantiate u1db # TODO: verify if secret for sqlcipher should be the same as the one # for symmetric encryption. - self._db = sqlcipher.open(self.U1DB_PATH, True, self._secret) + self._db = sqlcipher.open(self.LOCAL_DB_PATH, True, self._secret) #------------------------------------------------------------------------- # Management of secret for symmetric encryption @@ -112,6 +112,7 @@ class Soledad(object): """ Publish OpenPGP public key to a keyserver. """ + # TODO: this has to talk to LEAP's Nickserver. pass #------------------------------------------------------------------------- @@ -199,6 +200,7 @@ class Soledad(object): Synchronize the local encrypted database with LEAP server. """ # TODO: create authentication scheme for sync with server. - return self._db.sync(url, creds=None, autocreate=True) + return self._db.sync(url, creds=None, autocreate=True, soledad=self) __all__ = ['util'] + -- cgit v1.2.3