From ba97ee77ddeb101834a25cbb8d48aaa5edc26b93 Mon Sep 17 00:00:00 2001 From: drebs Date: Mon, 24 Dec 2012 11:31:58 -0200 Subject: GPGWrapper extends gnupg.GPG --- src/leap/soledad/__init__.py | 5 ++++- src/leap/soledad/util.py | 37 ++++++++++++++++++++----------------- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/leap/soledad/__init__.py b/src/leap/soledad/__init__.py index 6a3707ea..abec6488 100644 --- a/src/leap/soledad/__init__.py +++ b/src/leap/soledad/__init__.py @@ -7,7 +7,7 @@ import string import random import cStringIO import hmac -from soledad.util import GPGWrapper +from util import GPGWrapper class Soledad(object): @@ -85,3 +85,6 @@ class Soledad(object): def decrypt_symmetric(self, doc_id, data): h = hmac.new(self._secret, doc_id).hexdigest() return self.decrypt(data, passphrase=h) + + #def publish_pubkey(self): + # return self._gpg.export_keys( diff --git a/src/leap/soledad/util.py b/src/leap/soledad/util.py index 41fd4548..84ec85f1 100644 --- a/src/leap/soledad/util.py +++ b/src/leap/soledad/util.py @@ -2,7 +2,7 @@ import os import gnupg import re -class GPGWrapper(): +class GPGWrapper(gnupg.GPG): """ This is a temporary class for handling GPG requests, and should be replaced by a more general class used throughout the project. @@ -12,13 +12,15 @@ class GPGWrapper(): GNUPG_BINARY = "/usr/bin/gpg" # this has to be changed based on OS def __init__(self, gpghome=GNUPG_HOME, gpgbinary=GNUPG_BINARY): - self.gpg = gnupg.GPG(gnupghome=gpghome, gpgbinary=gpgbinary) + super(GPGWrapper, self).__init__(gpgbinary=gpgbinary, + gnupghome=gpghome, verbose=False, + use_agent=False, keyring=None, options=None) def find_key(self, email): """ Find user's key based on their email. """ - for key in self.gpg.list_keys(): + for key in self.list_keys(): for uid in key['uids']: if re.search(email, uid): return key @@ -26,23 +28,24 @@ class GPGWrapper(): def encrypt(self, data, recipient, sign=None, always_trust=True, passphrase=None, symmetric=False): - return self.gpg.encrypt(data, recipient, sign=sign, - always_trust=always_trust, - passphrase=passphrase, symmetric=symmetric) + # TODO: manage keys in a way we don't need to "always trust" + return super(GPGWrapper, self).encrypt(data, recipient, sign=sign, + always_trust=always_trust, + passphrase=passphrase, + symmetric=symmetric) def decrypt(self, data, always_trust=True, passphrase=None): - result = self.gpg.decrypt(data, always_trust=always_trust, - passphrase=passphrase) - return result + # TODO: manage keys in a way we don't need to "always trust" + return super(GPGWrapper, self).decrypt(data, + always_trust=always_trust, + passphrase=passphrase) - def import_keys(self, data): - return self.gpg.import_keys(data) - - def gen_key_input(self, **kwargs): - return self.gpg.gen_key_input(**kwargs) - - def gen_key(self, input): - return self.gpg.gen_key(input) + def send_keys(self, keys, keyserver): + """ + Send keys to a keyserver. + """ + pass + #---------------------------------------------------------------------------- -- cgit v1.2.3 From 2889b05a7c540f2370e6a524517dff0994ddbe15 Mon Sep 17 00:00:00 2001 From: drebs Date: Mon, 24 Dec 2012 11:42:13 -0200 Subject: Add send_keys to GPGWrapper --- src/leap/soledad/util.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/leap/soledad/util.py b/src/leap/soledad/util.py index 84ec85f1..67d950a5 100644 --- a/src/leap/soledad/util.py +++ b/src/leap/soledad/util.py @@ -40,12 +40,19 @@ class GPGWrapper(gnupg.GPG): always_trust=always_trust, passphrase=passphrase) - def send_keys(self, keys, keyserver): + def send_keys(self, keyserver, *keyids): """ Send keys to a keyserver. """ - pass - + result = self.result_map['list'](self) + logger.debug('send_keys: %r', keyids) + data = _make_binary_stream("", self.encoding) + args = ['--keyserver', keyserver, '--send-keys'] + args.extend(keyids) + self._handle_io(args, data, result, binary=True) + logger.debug('send_keys result: %r', result.__dict__) + data.close() + return result #---------------------------------------------------------------------------- -- cgit v1.2.3 From 8a36fceb830d46cb53fbdcc47a9fb63d3b47c9f0 Mon Sep 17 00:00:00 2001 From: drebs Date: Mon, 24 Dec 2012 12:12:05 -0200 Subject: Add method signatures for document storage, retrieval and sync --- src/leap/soledad/__init__.py | 76 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 4 deletions(-) diff --git a/src/leap/soledad/__init__.py b/src/leap/soledad/__init__.py index abec6488..2caee108 100644 --- a/src/leap/soledad/__init__.py +++ b/src/leap/soledad/__init__.py @@ -23,21 +23,32 @@ class Soledad(object): if not gpghome: gpghome = self.GNUPG_HOME self._gpg = GPGWrapper(gpghome=gpghome) - # load OpenPGP keypair + # load/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() + + #------------------------------------------------------------------------- + # Management of secret for symmetric encryption + #------------------------------------------------------------------------- + def _has_secret(self): + """ + Verify if secret already exists in a local encrypted file. + """ if os.path.isfile(self.SECRET_PATH): return True return False def _load_secret(self): + """ + Load secret from local encrypted file. + """ try: with open(self.SECRET_PATH) as f: self._secret = str(self._gpg.decrypt(f.read())) @@ -45,14 +56,24 @@ class Soledad(object): raise IOError('Failed to open secret file %s.' % self.SECRET_PATH) def _gen_secret(self): + """ + Generate secret for symmetric encryption and store it 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() + #------------------------------------------------------------------------- + # Management of OpenPGP keypair + #------------------------------------------------------------------------- def _has_openpgp_keypair(self): + """ + Verify if a keypair exists for this user. + """ + # TODO: verify if private key exists. try: self._gpg.find_key(self._user_email) return True @@ -60,6 +81,9 @@ class Soledad(object): return False def _gen_openpgp_keypair(self): + """ + Generate a keypair for this user. + """ params = self._gpg.gen_key_input( key_type='RSA', key_length=4096, @@ -69,22 +93,66 @@ class Soledad(object): self._gpg.gen_key(params) def _load_openpgp_keypair(self): + """ + Load the fingerprint for this user's keypair. + """ 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 and decription + #------------------------------------------------------------------------- + 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): + """ + Symmetrically encrypt data using this user's 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): + """ + Symmetrically decrypt data using this user's secret. + """ h = hmac.new(self._secret, doc_id).hexdigest() return self.decrypt(data, passphrase=h) - #def publish_pubkey(self): - # return self._gpg.export_keys( + #------------------------------------------------------------------------- + # Document storage, retrieval and sync + #------------------------------------------------------------------------- + + def put(self, doc_id, data): + """ + Store a document. + """ + pass + + def get(self, doc_id): + """ + Retrieve a document. + """ + pass + + def sync(self): + """ + Synchronize with LEAP server. + """ + pass -- cgit v1.2.3