summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/leap/soledad/__init__.py34
-rw-r--r--src/leap/soledad/backends/leap_backend.py27
-rw-r--r--src/leap/soledad/tests/test_crypto.py17
-rw-r--r--src/leap/soledad/tests/test_sqlcipher.py15
4 files changed, 59 insertions, 34 deletions
diff --git a/src/leap/soledad/__init__.py b/src/leap/soledad/__init__.py
index 3b7aadea..6ae82b4d 100644
--- a/src/leap/soledad/__init__.py
+++ b/src/leap/soledad/__init__.py
@@ -28,9 +28,6 @@ remote storage in the server side.
import os
import string
-import hashlib
-import configparser
-import re
import binascii
import logging
try:
@@ -43,6 +40,7 @@ from hashlib import sha256
from leap.common import events
+from leap.common.check import leap_assert
from leap.soledad.config import SoledadConfig
from leap.soledad.backends import sqlcipher
from leap.soledad.backends.leap_backend import (
@@ -121,6 +119,12 @@ class Soledad(object):
The length of the secret used for symmetric encryption.
"""
+ SYMKEY_KEY = '_symkey'
+ ADDRESS_KEY = '_address'
+ """
+ Key used to access symmetric keys in recovery documents.
+ """
+
def __init__(self, address, passphrase, config_path=None,
secret_path=None, local_db_path=None,
shared_db_url=None, auth_token=None, bootstrap=True):
@@ -208,7 +212,7 @@ class Soledad(object):
else:
self._set_symkey(
self._crypto.decrypt_sym(
- doc.content['_symkey'],
+ doc.content[self.KEY_SYMKEY],
passphrase=self._address_hash()))
# Stage 2 - Keys synchronization
self._assert_server_keys()
@@ -416,20 +420,26 @@ class Soledad(object):
"""
Assert our key copies are the same as server's ones.
"""
- assert self._has_keys()
+ leap_assert(
+ self._has_keys(),
+ 'Tried to send keys to server but they don\'t exist in local '
+ 'storage.')
if not self._shared_db:
return
doc = self._fetch_keys_from_shared_db()
if doc:
remote_symkey = self.decrypt_sym(
- doc.content['_symkey'],
+ doc.content[self.SYMKEY_KEY],
passphrase=self._address_hash())
- assert remote_symkey == self._symkey
+ leap_assert(
+ remote_symkey == self._symkey,
+ 'Local and remote symmetric secrets differ!')
else:
events.signal(
events.events_pb2.SOLEDAD_UPLOADING_KEYS, self._address)
content = {
- '_symkey': self.encrypt_sym(self._symkey, self._passphrase),
+ self.SYMKEY_KEY: self.encrypt_sym(
+ self._symkey, self._passphrase),
}
doc = LeapDocument(doc_id=self._address_hash())
doc.content = content
@@ -744,8 +754,8 @@ class Soledad(object):
@rtype: str
"""
data = json.dumps({
- 'address': self._address,
- 'symkey': self._symkey,
+ self.ADDRESS_KEY: self._address,
+ self.SYMKEY_KEY: self._symkey,
})
if passphrase:
data = self._crypto.encrypt_sym(data, passphrase)
@@ -770,8 +780,8 @@ class Soledad(object):
if passphrase:
data = self._crypto.decrypt_sym(data, passphrase=passphrase)
data = json.loads(data)
- self._address = data['address']
- self._symkey = data['symkey']
+ self._address = data[self.ADDRESS_KEY]
+ self._symkey = data[self.SYMKEY_KEY]
self._crypto.symkey = self._symkey
self._store_symkey()
# TODO: make this work well with bootstrap.
diff --git a/src/leap/soledad/backends/leap_backend.py b/src/leap/soledad/backends/leap_backend.py
index 51c471eb..9750ffad 100644
--- a/src/leap/soledad/backends/leap_backend.py
+++ b/src/leap/soledad/backends/leap_backend.py
@@ -39,6 +39,10 @@ from leap.common.keymanager import KeyManager
from leap.common.check import leap_assert
+#
+# Exceptions
+#
+
class NoDefaultKey(Exception):
"""
Exception to signal that there's no default OpenPGP key configured.
@@ -84,6 +88,11 @@ class EncryptionSchemes(object):
# Crypto utilities for a LeapDocument.
#
+ENC_JSON_KEY = '_enc_json'
+ENC_SCHEME_KEY = '_enc_scheme'
+MAC_KEY = '_mac'
+
+
def encrypt_doc_json(crypto, doc_id, doc_json):
"""
Return a valid JSON string containing the C{doc} content encrypted to
@@ -92,7 +101,7 @@ def encrypt_doc_json(crypto, doc_id, doc_json):
The returned JSON string is the serialization of the following dictionary:
{
- '_encrypted_json': encrypt_sym(doc_content),
+ ENC_JSON_KEY: encrypt_sym(doc_content),
'_encryption_scheme: 'symkey',
}
@@ -112,8 +121,8 @@ def encrypt_doc_json(crypto, doc_id, doc_json):
if not crypto.is_encrypted_sym(ciphertext):
raise DocumentNotEncrypted('Failed encrypting document.')
return json.dumps({
- '_encrypted_json': ciphertext,
- '_encryption_scheme': EncryptionSchemes.SYMKEY,
+ ENC_JSON_KEY: ciphertext,
+ ENC_SCHEME_KEY: EncryptionSchemes.SYMKEY,
})
@@ -126,8 +135,8 @@ def decrypt_doc_json(crypto, doc_id, doc_json):
following dictionary:
{
- '_encrypted_json': enc_blob,
- '_encryption_scheme': enc_scheme,
+ ENC_JSON_KEY: enc_blob,
+ ENC_SCHEME_KEY: enc_scheme,
}
C{enc_blob} is the encryption of the JSON serialization of the document's
@@ -150,8 +159,8 @@ def decrypt_doc_json(crypto, doc_id, doc_json):
leap_assert(isinstance(doc_json, str))
leap_assert(doc_json != '')
content = json.loads(doc_json)
- ciphertext = content['_encrypted_json']
- enc_scheme = content['_encryption_scheme']
+ ciphertext = content[ENC_JSON_KEY]
+ enc_scheme = content[ENC_SCHEME_KEY]
plainjson = None
if enc_scheme == EncryptionSchemes.SYMKEY:
if not crypto.is_encrypted_sym(ciphertext):
@@ -315,8 +324,8 @@ class LeapSyncTarget(HTTPSyncTarget):
# if arriving content was symmetrically encrypted, we decrypt
# it.
doc = LeapDocument(entry['id'], entry['rev'], entry['content'])
- if doc.content and '_encryption_scheme' in doc.content:
- if doc.content['_encryption_scheme'] == \
+ if doc.content and ENC_SCHEME_KEY in doc.content:
+ if doc.content[ENC_SCHEME_KEY] == \
EncryptionSchemes.SYMKEY:
doc.set_json(
decrypt_doc_json(
diff --git a/src/leap/soledad/tests/test_crypto.py b/src/leap/soledad/tests/test_crypto.py
index 5d494818..101b5d83 100644
--- a/src/leap/soledad/tests/test_crypto.py
+++ b/src/leap/soledad/tests/test_crypto.py
@@ -35,6 +35,9 @@ from leap.soledad.backends.leap_backend import (
decrypt_doc_json,
EncryptionSchemes,
LeapSyncTarget,
+ ENC_JSON_KEY,
+ ENC_SCHEME_KEY,
+ MAC_KEY,
)
from leap.soledad.backends.couch import CouchDatabase
from leap.soledad import KeyAlreadyExists, Soledad
@@ -79,7 +82,7 @@ class EncryptedSyncTestCase(BaseSoledadTest):
enc_json = json.loads(
encrypt_doc_json(
self._soledad._crypto,
- doc1.doc_id, doc1.get_json()))['_encrypted_json']
+ doc1.doc_id, doc1.get_json()))[ENC_JSON_KEY]
self.assertEqual(
True,
self._soledad._crypto.is_encrypted_sym(enc_json),
@@ -182,8 +185,8 @@ class RecoveryDocumentTestCase(BaseSoledadTest):
rd = self._soledad.export_recovery_document(None)
self.assertEqual(
{
- 'address': self._soledad._address,
- 'symkey': self._soledad._symkey
+ self._soledad.ADDRESS_KEY: self._soledad._address,
+ self._soledad.SYMKEY_KEY: self._soledad._symkey
},
json.loads(rd),
"Could not export raw recovery document."
@@ -194,12 +197,12 @@ class RecoveryDocumentTestCase(BaseSoledadTest):
self.assertEqual(True,
self._soledad._crypto.is_encrypted_sym(rd))
data = {
- 'address': self._soledad._address,
- 'symkey': self._soledad._symkey,
+ self._soledad.ADDRESS_KEY: self._soledad._address,
+ self._soledad.SYMKEY_KEY: self._soledad._symkey,
}
- raw_data = json.loads(str(self._soledad._crypto.decrypt_sym(
+ raw_data = json.loads(self._soledad._crypto.decrypt_sym(
rd,
- passphrase='123456')))
+ passphrase='123456'))
self.assertEqual(
raw_data,
data,
diff --git a/src/leap/soledad/tests/test_sqlcipher.py b/src/leap/soledad/tests/test_sqlcipher.py
index 73388202..6b2889d6 100644
--- a/src/leap/soledad/tests/test_sqlcipher.py
+++ b/src/leap/soledad/tests/test_sqlcipher.py
@@ -31,6 +31,9 @@ from leap.soledad.backends.leap_backend import (
EncryptionSchemes,
decrypt_doc_json,
encrypt_doc_json,
+ ENC_JSON_KEY,
+ ENC_SCHEME_KEY,
+ MAC_KEY,
)
# u1db tests stuff.
@@ -518,7 +521,7 @@ class SQLCipherDatabaseSyncTests(
# make sure db2 now has the exact same thing
doc1 = self.db1.get_doc('doc')
doc2 = self.db1.get_doc('doc')
- if '_encryption_scheme' in doc2.content:
+ if ENC_SCHEME_KEY in doc2.content:
doc2.set_json(
decrypt_doc_json(
self._soledad._crypto, doc2, doc2.get_json()))
@@ -579,7 +582,7 @@ class SQLCipherDatabaseSyncTests(
self.assertFalse(doc2.has_conflicts)
self.sync(self.db2, db3)
doc3 = db3.get_doc('the-doc')
- if '_encryption_scheme' in doc3.content:
+ if ENC_SCHEME_KEY in doc3.content:
doc3.set_json(
decrypt_doc_json(
self._soledad._crypto, doc3.doc_id, doc3.get_json()))
@@ -595,7 +598,7 @@ class SQLCipherDatabaseSyncTests(
doc.doc_id, doc.rev, tests.simple_doc, False)
doc2 = self.db2.get_doc(doc.doc_id)
# decrypt to compare it it is the case
- if '_encryption_scheme' in doc2.content:
+ if ENC_SCHEME_KEY in doc2.content:
doc2 = self.db2.get_doc(doc.doc_id)
doc2.set_json(
decrypt_doc_json(
@@ -652,7 +655,7 @@ class SQLCipherSyncTargetTests(
last_known_trans_id=None, return_doc_cb=self.receive_doc)
# decrypt doc1 for comparison if needed
tmpdoc = self.db.get_doc('doc-id')
- if '_encryption_scheme' in tmpdoc.content:
+ if ENC_SCHEME_KEY in tmpdoc.content:
tmpdoc.set_json(
decrypt_doc_json(
self._soledad._crypto, tmpdoc.doc_id,
@@ -681,7 +684,7 @@ class SQLCipherSyncTargetTests(
last_known_trans_id=None, return_doc_cb=self.receive_doc)
# decrypt doc1 for comparison if needed
tmpdoc1 = self.db.get_doc('doc-id')
- if '_encryption_scheme' in tmpdoc1.content:
+ if ENC_SCHEME_KEY in tmpdoc1.content:
tmpdoc1.set_json(
decrypt_doc_json(
self._soledad._crypto, tmpdoc1.doc_id,
@@ -691,7 +694,7 @@ class SQLCipherSyncTargetTests(
self.assertFalse(tmpdoc1.has_conflicts)
# decrypt doc2 for comparison if needed
tmpdoc2 = self.db.get_doc('doc-id2')
- if '_encryption_scheme' in tmpdoc2.content:
+ if ENC_SCHEME_KEY in tmpdoc2.content:
tmpdoc2.set_json(
decrypt_doc_json(
self._soledad._crypto, tmpdoc2.doc_id,