diff options
-rw-r--r-- | src/leap/soledad/__init__.py | 80 | ||||
-rw-r--r-- | src/leap/soledad/tests/test_crypto.py | 6 |
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 |