summaryrefslogtreecommitdiff
path: root/src/leap/bitmask/keymanager
diff options
context:
space:
mode:
authorNavaL <ayoyo@thoughtworks.com>2016-11-16 16:53:48 +0100
committerRuben Pollan <meskio@sindominio.net>2017-12-03 20:43:24 +0100
commit3eab1813bfb9efeea65ab3ad9798b8e8dba6d163 (patch)
treeaf519eaf21e15edeb0211e0e1ad1b4b6c3301e18 /src/leap/bitmask/keymanager
parent10a8b732576aa6a21ca01f265967f9e09560c2cf (diff)
[feat] add key expiry date extension in keymanager
- extends key pair (unlocked from soledad) - extension period is counted from key creation date
Diffstat (limited to 'src/leap/bitmask/keymanager')
-rw-r--r--src/leap/bitmask/keymanager/__init__.py23
-rw-r--r--src/leap/bitmask/keymanager/errors.py6
-rw-r--r--src/leap/bitmask/keymanager/openpgp.py41
-rw-r--r--src/leap/bitmask/keymanager/testing/__init__.py65
4 files changed, 133 insertions, 2 deletions
diff --git a/src/leap/bitmask/keymanager/__init__.py b/src/leap/bitmask/keymanager/__init__.py
index e3ff3b87..03ade634 100644
--- a/src/leap/bitmask/keymanager/__init__.py
+++ b/src/leap/bitmask/keymanager/__init__.py
@@ -38,7 +38,6 @@ from leap.bitmask.keymanager.openpgp import OpenPGPScheme
class KeyManager(object):
-
#
# server's key storage constants
#
@@ -110,7 +109,7 @@ class KeyManager(object):
leap_ca_bundle = ca_bundle.where()
if self._ca_cert_path == leap_ca_bundle:
- return self._ca_cert_path # don't merge file with itself
+ return self._ca_cert_path # don't merge file with itself
elif not self._ca_cert_path:
return leap_ca_bundle
@@ -711,6 +710,26 @@ class KeyManager(object):
pubkey.validation = validation
yield self.put_key(pubkey)
+ @defer.inlineCallbacks
+ def extend_key(self, validity='1y', passphrase=None):
+ """
+ extend the expiration date of the key pair bound to the user's address
+ by the validity period, from the key's creation date.
+
+ :param validity: new validity from creation date 'n','nw','nm' or 'ny'
+ where n is a number
+ :type validity: str
+
+ :return: The updated secret key, with new expiry date
+ :rtype: OpenPGPKey
+
+ :raise KeyExpiryExtensionError: if invalid validity period
+ """
+ my_secret_key = yield self.get_key(self._address, private=True)
+ renewed_key = yield self._openpgp.extend_key(my_secret_key, validity,
+ passphrase)
+ defer.returnValue(renewed_key)
+
def _split_email(address):
"""
diff --git a/src/leap/bitmask/keymanager/errors.py b/src/leap/bitmask/keymanager/errors.py
index dfff3936..1ca234de 100644
--- a/src/leap/bitmask/keymanager/errors.py
+++ b/src/leap/bitmask/keymanager/errors.py
@@ -88,6 +88,12 @@ class GPGError(Exception):
pass
+class KeyExpiryExtensionError(Exception):
+ """
+ Error during key expiry date extension
+ """
+
+
class SignFailed(Exception):
"""
Raised when failed to sign.
diff --git a/src/leap/bitmask/keymanager/openpgp.py b/src/leap/bitmask/keymanager/openpgp.py
index a27eb3de..99e5bc72 100644
--- a/src/leap/bitmask/keymanager/openpgp.py
+++ b/src/leap/bitmask/keymanager/openpgp.py
@@ -617,6 +617,47 @@ class OpenPGPScheme(object):
raise errors.EncryptError()
@defer.inlineCallbacks
+ def extend_key(self, seckey, validity='1y', passphrase=None):
+ """
+ Extend C{key} key pair, expiration date for C{validity} period,
+ from its creation date.
+
+ :param seckey: The secret key of the key pair to be extended.
+ :type seckey: OpenPGPKey
+ :param validity: new validity from creation date 'n','nw','nm' or 'ny'
+ where n is a number
+ :type validity: str
+
+ :return: The updated secret key, with new expiry date
+ :rtype: OpenPGPKey
+
+ :raise KeyExpiryExtensionError: Raised if failed to extend key
+ for some reason.
+ """
+ leap_assert_type(seckey, OpenPGPKey)
+ leap_assert(seckey.private is True, 'Key is not private.')
+ keys = [seckey]
+ try:
+ with TempGPGWrapper(keys, self._gpgbinary) as gpg:
+ result = yield from_thread(gpg.extend_key, seckey.address,
+ validity=validity,
+ passphrase=passphrase)
+ if result.status == 'ok':
+ for secret in [False, True]:
+ fetched_key = gpg.list_keys(secret=secret).pop()
+ key_data = gpg.export_keys(seckey.fingerprint,
+ secret=secret)
+ renewed_key = self._build_key_from_gpg(
+ fetched_key,
+ key_data,
+ seckey.address)
+ yield self.put_key(renewed_key)
+ defer.returnValue(renewed_key)
+ except Exception as e:
+ logger.warn('Failed to Extend Key: %s expiration date.' % str(e))
+ raise errors.KeyExpiryExtensionError(str(e))
+
+ @defer.inlineCallbacks
def decrypt(self, data, privkey, passphrase=None, verify=None):
"""
Decrypt C{data} using private @{privkey} and verify with C{verify} key.
diff --git a/src/leap/bitmask/keymanager/testing/__init__.py b/src/leap/bitmask/keymanager/testing/__init__.py
index 63ccf50a..192c7d9b 100644
--- a/src/leap/bitmask/keymanager/testing/__init__.py
+++ b/src/leap/bitmask/keymanager/testing/__init__.py
@@ -237,6 +237,71 @@ THx7N776fcYHGumbqUMYrxrcZSbNveE6SaK8fphRam1dewM0
-----END PGP PRIVATE KEY BLOCK-----
"""
+# key with expiry date, change if key below is changed
+ADDRESS_EXPIRING = 'leap.expiring@leap.se'
+KEY_EXPIRING_CREATION_DATE = '2016-11-06'
+
+PRIVATE_EXPIRING_KEY = """
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v1
+
+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
+=2Zjl
+-----END PGP PRIVATE KEY BLOCK-----
+"""
+
class KeyManagerWithSoledadTestCase(unittest.TestCase, BaseLeapTest):