summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/leap/bitmask/keymanager/__init__.py10
-rw-r--r--src/leap/bitmask/keymanager/keys.py5
-rw-r--r--src/leap/bitmask/keymanager/openpgp.py32
-rw-r--r--tests/integration/keymanager/test_keymanager.py12
-rw-r--r--tests/integration/keymanager/test_openpgp.py27
5 files changed, 77 insertions, 9 deletions
diff --git a/src/leap/bitmask/keymanager/__init__.py b/src/leap/bitmask/keymanager/__init__.py
index 483c7e51..a273b87d 100644
--- a/src/leap/bitmask/keymanager/__init__.py
+++ b/src/leap/bitmask/keymanager/__init__.py
@@ -330,6 +330,7 @@ class KeyManager(object):
d.addCallback(signal_finished)
return d
+ @defer.inlineCallbacks
def regenerate_key(self):
"""
Regenerate a key bound to the user's address.
@@ -345,9 +346,12 @@ class KeyManager(object):
self.log.info('Regenerating key for %s.' % self._address)
emit_async(catalog.KEYMANAGER_STARTED_KEY_GENERATION, self._address)
- d = self._openpgp.regenerate_key(self._address)
- d.addCallback(signal_finished)
- return d
+ new_key = yield self._openpgp.regenerate_key(self._address)
+ yield self._openpgp.reset_all_keys_sign_used()
+ emit_async(
+ catalog.KEYMANAGER_FINISHED_KEY_GENERATION, self._address)
+
+ defer.returnValue(new_key)
#
# Setters/getters
diff --git a/src/leap/bitmask/keymanager/keys.py b/src/leap/bitmask/keymanager/keys.py
index d37c6d21..7e8d8ead 100644
--- a/src/leap/bitmask/keymanager/keys.py
+++ b/src/leap/bitmask/keymanager/keys.py
@@ -184,7 +184,7 @@ class OpenPGPKey(object):
return False
- def merge(self, newkey):
+ def merge(self, newkey, key_renewal=False):
if newkey.fingerprint != self.fingerprint:
self.log.critical(
"Can't put a key whith the same key_id and different "
@@ -216,7 +216,8 @@ class OpenPGPKey(object):
if newkey.last_audited_at > self.last_audited_at:
self.validation = newkey.last_audited_at
self.encr_used = newkey.encr_used or self.encr_used
- self.sign_used = newkey.sign_used or self.sign_used
+ if not key_renewal:
+ self.sign_used = newkey.sign_used or self.sign_used
self.refreshed_at = datetime.now()
def get_json(self):
diff --git a/src/leap/bitmask/keymanager/openpgp.py b/src/leap/bitmask/keymanager/openpgp.py
index d0acca54..593536eb 100644
--- a/src/leap/bitmask/keymanager/openpgp.py
+++ b/src/leap/bitmask/keymanager/openpgp.py
@@ -30,6 +30,7 @@ from twisted.internet import defer
from twisted.internet.threads import deferToThread
from twisted.logger import Logger
+from leap.bitmask.keymanager.migrator import KeyDocumentsMigrator
from leap.common.check import leap_assert, leap_assert_type, leap_check
from leap.bitmask.keymanager import errors
from leap.bitmask.keymanager.wrapper import TempGPGWrapper
@@ -120,7 +121,6 @@ class OpenPGPScheme(object):
self._wait_indexes("get_key", "put_key", "get_all_keys")
def _migrate_documents_schema(self, _):
- from leap.bitmask.keymanager.migrator import KeyDocumentsMigrator
migrator = KeyDocumentsMigrator(self._soledad)
return migrator.migrate()
@@ -149,6 +149,7 @@ class OpenPGPScheme(object):
d.addCallback(lambda _: self.stored[method](*args, **kw))
self.waiting.append(d)
return d
+
return wrapper
for method in methods:
@@ -175,12 +176,14 @@ class OpenPGPScheme(object):
"""
leap_assert(is_address(address), 'Not an user address: %s' % address)
current_sec_key = yield self.get_key(address, private=True)
+ current_pub_key = yield self.get_key(address, private=False)
with TempGPGWrapper([current_sec_key], self._gpgbinary) as gpg:
if current_sec_key.has_expired():
temporary_extension_period = '1' # extend for 1 extra day
gpg.extend_key(current_sec_key.fingerprint,
validity=temporary_extension_period)
- yield self.unactivate_key(address)
+ yield self.unactivate_key(address) # only one priv key allowed
+ yield self.delete_key(current_pub_key)
new_key = yield self.gen_key(address)
gpg.import_keys(new_key.key_data)
key_signing = yield from_thread(gpg.sign_key, new_key.fingerprint)
@@ -405,7 +408,7 @@ class OpenPGPScheme(object):
d.addCallback(put_key, openpgp_privkey)
return d
- def put_key(self, key):
+ def put_key(self, key, key_renewal=False):
"""
Put C{key} in local storage.
@@ -425,7 +428,7 @@ class OpenPGPScheme(object):
active_content = activedoc.content
oldkey = build_key_from_dict(keydoc.content, active_content)
- key.merge(oldkey)
+ key.merge(oldkey, key_renewal)
keydoc.set_json(key.get_json())
d = self._soledad.put_doc(keydoc)
d.addCallback(put_active, activedoc)
@@ -578,6 +581,27 @@ class OpenPGPScheme(object):
active_doc = yield self._get_active_doc_from_address(address, False)
yield self._soledad.delete_doc(active_doc)
+ @defer.inlineCallbacks
+ def reset_all_keys_sign_used(self):
+ """
+ Reset sign_used flag for all keys in storage, to False...
+ to indicate that the key pair has not interacted with all
+ keys in the key ring yet.
+ This should only be used when regenerating the key pair.
+
+ """
+ all_keys = yield self.get_all_keys(private=False)
+ deferreds = []
+
+ @defer.inlineCallbacks
+ def reset_sign_used(key):
+ key.sign_used = False
+ yield self.put_key(key, key_renewal=True)
+
+ for open_pgp_key in all_keys:
+ deferreds.append(reset_sign_used(open_pgp_key))
+ yield defer.gatherResults(deferreds)
+
#
# Data encryption, decryption, signing and verifying
#
diff --git a/tests/integration/keymanager/test_keymanager.py b/tests/integration/keymanager/test_keymanager.py
index 4e6d62c8..e11e19b8 100644
--- a/tests/integration/keymanager/test_keymanager.py
+++ b/tests/integration/keymanager/test_keymanager.py
@@ -577,6 +577,18 @@ class KeyManagerKeyManagementTestCase(KeyManagerWithSoledadTestCase):
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)
+
+ yield km._openpgp.put_raw_key(PRIVATE_EXPIRING_KEY, ADDRESS_EXPIRING)
+ yield km._openpgp.put_raw_key(PUBLIC_KEY_2, ADDRESS_2)
+ km._openpgp.reset_all_keys_sign_used = mock.Mock()
+
+ yield km.regenerate_key()
+
+ km._openpgp.reset_all_keys_sign_used.assert_called_once()
+
+ @defer.inlineCallbacks
def test_key_extension_with_invalid_period_throws_exception(self):
km = self._key_manager(user=ADDRESS_EXPIRING)
diff --git a/tests/integration/keymanager/test_openpgp.py b/tests/integration/keymanager/test_openpgp.py
index d04f5d01..d994f801 100644
--- a/tests/integration/keymanager/test_openpgp.py
+++ b/tests/integration/keymanager/test_openpgp.py
@@ -100,6 +100,33 @@ class OpenPGPCryptoTestCase(KeyManagerWithSoledadTestCase):
yield self._assert_key_not_found(pgp, ADDRESS)
@inlineCallbacks
+ def test_reset_sign_used_for_all_keys(self):
+ pgp = openpgp.OpenPGPScheme(
+ self._soledad, gpgbinary=self.gpg_binary_path)
+
+ yield pgp.put_raw_key(PRIVATE_KEY, ADDRESS)
+ yield pgp.put_raw_key(PUBLIC_KEY, ADDRESS)
+ yield pgp.put_raw_key(PUBLIC_KEY_2, ADDRESS_2)
+ pubkey = yield pgp.get_key(ADDRESS)
+ pubkey.sign_used = True
+ yield pgp.put_key(pubkey)
+ pubkey2 = yield pgp.get_key(ADDRESS_2)
+ pubkey2.sign_used = True
+ yield pgp.put_key(pubkey2)
+
+ yield pgp.reset_all_keys_sign_used()
+
+ pubkey_refetched = yield pgp.get_key(ADDRESS)
+ pubkey2_refetched = yield pgp.get_key(ADDRESS_2)
+
+ self.assertEqual(False, pubkey_refetched.sign_used)
+ self.assertEqual(False, pubkey2_refetched.sign_used)
+ self.assertEqual(pubkey.fingerprint, pubkey_refetched.fingerprint)
+ self.assertEqual(pubkey.key_data, pubkey_refetched.key_data)
+ self.assertEqual(pubkey2.fingerprint, pubkey2_refetched.fingerprint)
+ self.assertEqual(pubkey2.key_data, pubkey2_refetched.key_data)
+
+ @inlineCallbacks
def test_openpgp_encrypt_decrypt(self):
data = 'data'
pgp = openpgp.OpenPGPScheme(