summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordrebs <drebs@leap.se>2012-12-24 12:13:30 -0200
committerdrebs <drebs@leap.se>2012-12-24 12:13:30 -0200
commit3cada93fd723a99f07adab201c1fa9f8cda3f243 (patch)
tree442daae3efabad9fe81b0c80785525fcbf16bf76
parent319e279b59ac080779d0a3375ae4d6582f5ee6a3 (diff)
parent8a36fceb830d46cb53fbdcc47a9fb63d3b47c9f0 (diff)
Merge branch 'feature/soledad-publish-pubkey' into develop
-rw-r--r--src/leap/soledad/__init__.py77
-rw-r--r--src/leap/soledad/util.py44
2 files changed, 101 insertions, 20 deletions
diff --git a/src/leap/soledad/__init__.py b/src/leap/soledad/__init__.py
index 6a3707ea..2caee108 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):
@@ -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,19 +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)
+
+ #-------------------------------------------------------------------------
+ # 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
diff --git a/src/leap/soledad/util.py b/src/leap/soledad/util.py
index 41fd4548..67d950a5 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,31 @@ 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
-
- def import_keys(self, data):
- return self.gpg.import_keys(data)
-
- def gen_key_input(self, **kwargs):
- return self.gpg.gen_key_input(**kwargs)
+ # 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 gen_key(self, input):
- return self.gpg.gen_key(input)
+ def send_keys(self, keyserver, *keyids):
+ """
+ Send keys to a keyserver.
+ """
+ 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
#----------------------------------------------------------------------------