summaryrefslogtreecommitdiff
path: root/src/leap/soledad
diff options
context:
space:
mode:
authordrebs <drebs@leap.se>2013-05-21 21:41:11 -0300
committerdrebs <drebs@leap.se>2013-05-21 21:44:14 -0300
commit3214e542c7e5ebaadd704c17f2a34858b7b8e92e (patch)
tree16ac207b7e8c813a7f1dbcfd541a2507ca4ca691 /src/leap/soledad
parent6c1b204938109de29fa53cc4e445b822f622826d (diff)
Improve export/import_recovery_document()
* Fix docstrings.
Diffstat (limited to 'src/leap/soledad')
-rw-r--r--src/leap/soledad/__init__.py80
-rw-r--r--src/leap/soledad/tests/test_crypto.py6
2 files changed, 40 insertions, 46 deletions
diff --git a/src/leap/soledad/__init__.py b/src/leap/soledad/__init__.py
index b0acb91a..6bb88094 100644
--- a/src/leap/soledad/__init__.py
+++ b/src/leap/soledad/__init__.py
@@ -199,7 +199,7 @@ class Soledad(object):
@param uuid: User's uuid.
@type uuid: str
@param passphrase: The passphrase for locking and unlocking encryption
- secrets for disk storage.
+ secrets for local and remote storage.
@type passphrase: str
@param secrets_path: Path for storing encrypted key used for
symmetric encryption.
@@ -294,7 +294,7 @@ class Soledad(object):
logger.info(
'Found cryptographic secrets in shared recovery '
'database.')
- self.import_recovery_document(doc.content[self.SECRET_KEY])
+ self.import_recovery_document(doc.content)
else:
# there are no secrets in server also, so generate a secret.
logger.info(
@@ -572,9 +572,7 @@ class Soledad(object):
if doc is None:
doc = LeapDocument(doc_id=self._uuid_hash())
# fill doc with encrypted secrets
- doc.content = {
- self.SECRET_KEY: self.export_recovery_document()
- }
+ doc.content = self.export_recovery_document(include_uuid=False)
# upload secrets to server
events.signal(
events.events_pb2.SOLEDAD_UPLOADING_KEYS, self._uuid)
@@ -590,9 +588,6 @@ class Soledad(object):
# Document storage, retrieval and sync.
#
- # TODO: refactor the following methods to somewhere out of here
- # (SoledadLocalDatabase, maybe?)
-
def put_doc(self, doc):
"""
Update a document in the local encrypted database.
@@ -893,57 +888,56 @@ class Soledad(object):
token = property(_get_token, _set_token, doc='The authentication Token.')
#
- # Recovery document export and import methodsecret
- def export_recovery_document(self, passphrase=None):
+ # Recovery document export and import methods
+ #
+ def export_recovery_document(self, include_uuid=True):
"""
- Exports username, provider, private key and key for symmetric
- encryption, optionally encrypted with a password.
-
- The LEAP client gives the user the option to export a text file with a
- complete copy of their private keys and authorization information,
- either password protected or not. This "recovery document" can be
- printed or saved electronically as the user sees fit. If the user
- needs to recover their data, they can load this recover document into
- any LEAP client. The user can also type the recovery document in
- manually, although it will be long and very painful to copy manually.
+ Export the storage secrets and (optionally) the uuid.
- Contents of recovery document:
+ A recovery document has the following structure:
- - username
- - provider
- - private key.
- - key for symmetric encryption
+ {
+ self.STORAGE_SECRET_KEY: <secrets dict>,
+ self.UUID_KEY: '<uuid>', # (optional)
+ }
- @param passphrase: an optional passphrase for encrypting the document
- @type passphrase: str
+ @param include_uuid: Should the uuid be included?
+ @type include_uuid: bool
- @return: the recovery document json serialization
- @rtype: str
+ @return: The recovery document.
+ @rtype: dict
"""
- data = json.dumps({
- self.UUID_KEY: self._uuid,
- self.STORAGE_SECRETS_KEY: self._secrets,
- })
+ data = {self.STORAGE_SECRETS_KEY: self._secrets}
+ if include_uuid:
+ data[self.UUID_KEY] = self._uuid
return data
def import_recovery_document(self, data):
"""
- Import username, provider, private key and key for symmetric
- encryption from a recovery document.
+ Import storage secrets for symmetric encryption and uuid (if present)
+ from a recovery document.
+
+ A recovery document has the following structure:
- @param data: the recovery document json serialization
- @type data: str
+ {
+ self.STORAGE_SECRET_KEY: <secrets dict>,
+ self.UUID_KEY: '<uuid>', # (optional)
+ }
+
+ @param data: The recovery document.
+ @type data: dict
"""
- data = json.loads(data)
# include new secrets in our secret pool.
for secret_id, secret_data in data[self.STORAGE_SECRETS_KEY].items():
if secret_id not in self._secrets:
self._secrets[secret_id] = secret_data
- self._store_secrets()
- # set uuid
- self._uuid = data[self.UUID_KEY]
- # choose first secret to use
- self._set_secret_id(data[self.STORAGE_SECRETS_KEY].items()[0][0])
+ self._store_secrets() # save new secrets in local file
+ # set uuid if present
+ if self.UUID_KEY in data:
+ self._uuid = data[self.UUID_KEY]
+ # choose first secret to use is none is assigned
+ if self._secret_id is None:
+ self._set_secret_id(data[self.STORAGE_SECRETS_KEY].items()[0][0])
#
# Setters/getters
diff --git a/src/leap/soledad/tests/test_crypto.py b/src/leap/soledad/tests/test_crypto.py
index 7b8f756a..a61b931c 100644
--- a/src/leap/soledad/tests/test_crypto.py
+++ b/src/leap/soledad/tests/test_crypto.py
@@ -180,7 +180,7 @@ class EncryptedSyncTestCase(BaseSoledadTest):
class RecoveryDocumentTestCase(BaseSoledadTest):
def test_export_recovery_document_raw(self):
- rd = json.loads(self._soledad.export_recovery_document())
+ rd = self._soledad.export_recovery_document()
secret_id = rd[self._soledad.STORAGE_SECRETS_KEY].items()[0][0]
secret = rd[self._soledad.STORAGE_SECRETS_KEY][secret_id]
self.assertEqual(secret_id, self._soledad._secret_id)
@@ -191,7 +191,7 @@ class RecoveryDocumentTestCase(BaseSoledadTest):
self.assertTrue(self._soledad.SECRET_KEY in secret)
def test_import_recovery_document(self):
- rd = self._soledad.export_recovery_document(None)
+ rd = self._soledad.export_recovery_document()
s = self._soledad_instance(user='anotheruser@leap.se', prefix='/2')
s.import_recovery_document(rd)
s._set_secret_id(self._soledad._secret_id)
@@ -238,7 +238,7 @@ class CryptoMethodsTestCase(BaseSoledadTest):
def test__has_secret(self):
- sol = self._soledad_instance(user='user@leap.se', prefix='/3')
+ sol = self._soledad_instance(user='user@leap.se', prefix='/4')
self.assertTrue(sol._has_secret(), "Should have a secret at "
"this point")
# setting secret id to None should not interfere in the fact we have a