summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNavaL <ayoyo@thoughtworks.com>2016-11-25 20:51:45 +0100
committerRuben Pollan <meskio@sindominio.net>2017-12-03 20:43:31 +0100
commitbf9fa332e270ce0775e62517da457c8fc54f77ba (patch)
tree1311b80a089f26a70befc0b761f0a994b502e062
parent95f8a39c2185d9cc3af4e6ed600aea98c13d1949 (diff)
[feat] decryption interoperability, when the current key pair
is renewed - there is only one private inactive key that is the key expiring last among all inactive keys - if there is an inactive key, decryption with it, is tried if it fails with the current active key.
-rw-r--r--bench/keymanager/common.py65
-rw-r--r--src/leap/bitmask/keymanager/__init__.py65
-rw-r--r--src/leap/bitmask/keymanager/keys.py2
-rw-r--r--tests/integration/keymanager/common.py64
-rw-r--r--tests/integration/keymanager/test_keymanager.py63
5 files changed, 253 insertions, 6 deletions
diff --git a/bench/keymanager/common.py b/bench/keymanager/common.py
index a7713944..aa907dab 100644
--- a/bench/keymanager/common.py
+++ b/bench/keymanager/common.py
@@ -205,6 +205,71 @@ RZXoH+FTg9UAW87eqU610npOkT6cRaBxaMK/mDtGNdc=
-----END PGP PRIVATE KEY BLOCK-----
"""
+
+# different private key to the same address
+# A4337956D27DC89C Leap Test Key <leap@leap.se>
+# no expiry date
+DIFFERENT_KEY_FPR = "EFA5842560D6462AD9CCE7A2A4337956D27DC89C"
+DIFFERENT_PRIVATE_KEY = """
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v1
+
+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
+=3mjv
+-----END PGP PRIVATE KEY BLOCK-----
+"""
+
# key 7FEE575A: public key "anotheruser <anotheruser@leap.se>"
KEY_FINGERPRINT_2 = "F6E2B572ADB84EA58BD2E9A57F9DFA687FEE575A"
PUBLIC_KEY_2 = """
diff --git a/src/leap/bitmask/keymanager/__init__.py b/src/leap/bitmask/keymanager/__init__.py
index a273b87d..87f411e7 100644
--- a/src/leap/bitmask/keymanager/__init__.py
+++ b/src/leap/bitmask/keymanager/__init__.py
@@ -207,7 +207,47 @@ class KeyManager(object):
yield self.put_raw_key(
raw_key, address=address, validation=validation_level)
- def get_key(self, address, private=False, fetch_remote=True):
+ @defer.inlineCallbacks
+ def get_key(self, address, private=False, active=True, fetch_remote=True):
+ """
+ Return a key bound to address.
+
+ For an active key: first, search for the key in local storage.
+ If it is not available, then try to fetch from nickserver.
+ The inactive key is fetched locally, for the case of multiple keys
+ for the same address. This can be used to attempt decryption
+ from multiple keys.
+
+ :param address: The address bound to the key.
+ :type address: str
+ :param private: Look for a private key instead of a public one?
+ :type private: bool
+ :param active: Look for the current active key
+ :type private: bool
+ :param fetch_remote: If key not found in local storage try to fetch
+ from nickserver
+ :type fetch_remote: bool
+
+ :return: A Deferred which fires with an EncryptionKey bound to address,
+ or which fails with KeyNotFound if no key was found neither
+ locally or in keyserver or fail with KeyVersionError if the
+ key has a format not supported by this version of KeyManager
+ :rtype: Deferred
+
+ :raise UnsupportedKeyTypeError: if invalid key type
+ """
+
+ if active:
+ key = yield self._get_key(address, private, fetch_remote)
+ defer.returnValue(key)
+ all_keys = yield self.get_all_keys(private)
+ inactive_keys = filter(lambda _key: not _key.is_active(), all_keys)
+ if inactive_keys:
+ inactive_keys = sorted(inactive_keys,
+ key=lambda _key: _key.expiry_date)
+ defer.returnValue(inactive_keys[-1])
+
+ def _get_key(self, address, private=False, fetch_remote=True):
"""
Return a key bound to address.
@@ -462,7 +502,8 @@ class KeyManager(object):
fetch_remote=True):
"""
Decrypt data using private key from address and verify with public key
- bound to verify address.
+ bound to verify address. If the decryption using the active private
+ key fails, then decription using the inactive key, if any, is tried.
:param data: The data to be decrypted.
:type data: str
@@ -489,7 +530,7 @@ class KeyManager(object):
"""
@defer.inlineCallbacks
- def decrypt(keys):
+ def _decrypt(keys):
pubkey, privkey = keys
decrypted, signed = yield self._openpgp.decrypt(
data, privkey, passphrase=passphrase, verify=pubkey)
@@ -507,6 +548,24 @@ class KeyManager(object):
(pubkey.fingerprint,))
defer.returnValue((decrypted, signature))
+ @defer.inlineCallbacks
+ def decrypt_with_inactive_key(keys, original_decrypt_error):
+ verify_key, active_key = keys
+ inactive_key = yield self.get_key(address, private=True,
+ active=False)
+ if inactive_key:
+ result = yield _decrypt([verify_key, inactive_key])
+ defer.returnValue(result)
+ raise original_decrypt_error
+
+ @defer.inlineCallbacks
+ def decrypt(keys):
+ try:
+ result = yield _decrypt(keys)
+ except keymanager_errors.DecryptError as e:
+ result = yield decrypt_with_inactive_key(keys, e)
+ defer.returnValue(result)
+
dpriv = self.get_key(address, private=True)
dpub = defer.succeed(None)
if verify is not None:
diff --git a/src/leap/bitmask/keymanager/keys.py b/src/leap/bitmask/keymanager/keys.py
index 6aca0320..d26f8b31 100644
--- a/src/leap/bitmask/keymanager/keys.py
+++ b/src/leap/bitmask/keymanager/keys.py
@@ -289,7 +289,7 @@ class OpenPGPKey(object):
return key, value
def has_expired(self):
- return self.expiry_date < datetime.now()
+ return self.expiry_date and self.expiry_date < datetime.now()
def __iter__(self):
return self
diff --git a/tests/integration/keymanager/common.py b/tests/integration/keymanager/common.py
index 9e4b9ee1..c2fd77be 100644
--- a/tests/integration/keymanager/common.py
+++ b/tests/integration/keymanager/common.py
@@ -195,6 +195,70 @@ RZXoH+FTg9UAW87eqU610npOkT6cRaBxaMK/mDtGNdc=
-----END PGP PRIVATE KEY BLOCK-----
"""
+# different private key to the same address
+# A4337956D27DC89C Leap Test Key <leap@leap.se>
+# no expiry date
+DIFFERENT_KEY_FPR = "EFA5842560D6462AD9CCE7A2A4337956D27DC89C"
+DIFFERENT_PRIVATE_KEY = """
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v1
+
+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
+=3mjv
+-----END PGP PRIVATE KEY BLOCK-----
+"""
+
# key 7FEE575A: public key "anotheruser <anotheruser@leap.se>"
KEY_FINGERPRINT_2 = "F6E2B572ADB84EA58BD2E9A57F9DFA687FEE575A"
PUBLIC_KEY_2 = """
diff --git a/tests/integration/keymanager/test_keymanager.py b/tests/integration/keymanager/test_keymanager.py
index e11e19b8..7bacd050 100644
--- a/tests/integration/keymanager/test_keymanager.py
+++ b/tests/integration/keymanager/test_keymanager.py
@@ -52,8 +52,8 @@ from common import (
KEY_EXPIRING_CREATION_DATE,
PRIVATE_EXPIRING_KEY,
NEW_PUB_KEY,
- OLD_AND_NEW_KEY_ADDRESS
-)
+ OLD_AND_NEW_KEY_ADDRESS,
+ DIFFERENT_PRIVATE_KEY, DIFFERENT_KEY_FPR)
NICKSERVER_URI = "http://leap.se/"
REMOTE_KEY_URL = "http://site.domain/key"
@@ -195,6 +195,25 @@ class KeyManagerKeyManagementTestCase(KeyManagerWithSoledadTestCase):
self.assertTrue(key.private)
@defer.inlineCallbacks
+ def test_create_and_get_two_private_keys_sets_first_key_inactive(self):
+ km = self._key_manager()
+ yield km._openpgp.put_raw_key(PRIVATE_KEY, ADDRESS)
+ yield km._openpgp.put_raw_key(DIFFERENT_PRIVATE_KEY, ADDRESS)
+ # get the key
+ inactive_key = yield km.get_key(ADDRESS, private=True,
+ active=False, fetch_remote=False)
+ active_key = yield km.get_key(ADDRESS, private=True,
+ active=True, fetch_remote=False)
+ self.assertEqual(
+ inactive_key.fingerprint.lower(), KEY_FINGERPRINT.lower())
+ self.assertEqual(
+ active_key.fingerprint.lower(), DIFFERENT_KEY_FPR.lower())
+ self.assertTrue(inactive_key.private)
+ self.assertTrue(active_key.private)
+ self.assertFalse(inactive_key.is_active())
+ self.assertTrue(active_key.is_active())
+
+ @defer.inlineCallbacks
def test_send_key(self):
"""
Test that request is well formed when sending keys to server.
@@ -577,6 +596,25 @@ class KeyManagerKeyManagementTestCase(KeyManagerWithSoledadTestCase):
self.assertIn(old_key.fingerprint[-16:], renewed_public_key.signatures)
@defer.inlineCallbacks
+ def test_key_regenerate_deactivate_the_old_private_key(self):
+ km = self._key_manager(user=ADDRESS_EXPIRING)
+
+ yield km._openpgp.put_raw_key(PRIVATE_EXPIRING_KEY, ADDRESS_EXPIRING)
+ old_key = yield km.get_key(ADDRESS_EXPIRING)
+
+ new_key = yield km.regenerate_key()
+ retrieved_old_key = yield km.get_key(ADDRESS_EXPIRING,
+ private=True, active=False)
+ renewed_public_key = yield km.get_key(ADDRESS_EXPIRING, private=False)
+
+ self.assertEqual(old_key.fingerprint,
+ retrieved_old_key.fingerprint)
+ self.assertNotEqual(old_key.fingerprint,
+ new_key.fingerprint)
+ self.assertEqual(new_key.fingerprint, renewed_public_key.fingerprint)
+ self.assertIn(old_key.fingerprint[-16:], renewed_public_key.signatures)
+
+ @defer.inlineCallbacks
def test_key_regenerate_resets_all_public_key_sign_used(self):
km = self._key_manager(user=ADDRESS_EXPIRING)
@@ -630,6 +668,27 @@ class KeyManagerCryptoTestCase(KeyManagerWithSoledadTestCase):
self.assertEqual(signingkey.fingerprint, key.fingerprint)
@defer.inlineCallbacks
+ def test_keymanager_openpgp_decryption_tries_inactive_valid_key(self):
+ km = self._key_manager()
+ # put raw private key
+ yield km._openpgp.put_raw_key(PRIVATE_KEY, ADDRESS)
+ yield km._openpgp.put_raw_key(PRIVATE_KEY_2, ADDRESS_2)
+ # encrypt
+ encdata = yield km.encrypt(self.RAW_DATA, ADDRESS, sign=ADDRESS_2,
+ fetch_remote=False)
+ self.assertNotEqual(self.RAW_DATA, encdata)
+
+ # renew key
+ new_key = yield km.regenerate_key()
+
+ # decrypt
+ rawdata, signingkey = yield km.decrypt(
+ encdata, ADDRESS, verify=ADDRESS_2, fetch_remote=False)
+ self.assertEqual(self.RAW_DATA, rawdata)
+ key = yield km.get_key(ADDRESS_2, private=False, fetch_remote=False)
+ self.assertEqual(signingkey.fingerprint, key.fingerprint)
+
+ @defer.inlineCallbacks
def test_keymanager_openpgp_encrypt_decrypt_wrong_sign(self):
km = self._key_manager()
# put raw keys