diff options
-rw-r--r-- | client/pkg/requirements.pip | 1 | ||||
-rw-r--r-- | client/src/leap/soledad/client/_crypto.py | 36 | ||||
-rw-r--r-- | client/src/leap/soledad/client/http_target/fetch.py | 2 | ||||
-rw-r--r-- | testing/tests/client/test_crypto.py | 6 | ||||
-rw-r--r-- | testing/tests/server/test_server.py | 3 |
5 files changed, 19 insertions, 29 deletions
diff --git a/client/pkg/requirements.pip b/client/pkg/requirements.pip index a18fe124..24b168b4 100644 --- a/client/pkg/requirements.pip +++ b/client/pkg/requirements.pip @@ -2,5 +2,4 @@ pysqlcipher>2.6.3 scrypt zope.proxy twisted -six cryptography diff --git a/client/src/leap/soledad/client/_crypto.py b/client/src/leap/soledad/client/_crypto.py index 574e2b6e..b1c6b059 100644 --- a/client/src/leap/soledad/client/_crypto.py +++ b/client/src/leap/soledad/client/_crypto.py @@ -32,8 +32,6 @@ from io import BytesIO from itertools import imap from collections import namedtuple -import six - from twisted.internet import defer from twisted.internet import interfaces from twisted.web.client import FileBodyProducer @@ -50,7 +48,8 @@ MAC_KEY_LENGTH = 64 CRYPTO_BACKEND = MultiBackend([OpenSSLBackend()]) -PACMAN = struct.Struct('cQbb16s255p255p') +PACMAN = struct.Struct('2sbbQ16s255p255p') +BLOB_SIGNATURE_MAGIC = '\x13\x37' ENC_SCHEME = namedtuple('SCHEME', 'symkey')(1) @@ -226,10 +225,10 @@ class BlobEncryptor(object): current_time = int(time.time()) write(PACMAN.pack( - '\x80', - current_time, + BLOB_SIGNATURE_MAGIC, ENC_SCHEME.symkey, ENC_METHOD.aes_256_ctr, + current_time, self.iv, str(self.doc_id), str(self.rev))) @@ -292,11 +291,11 @@ class BlobDecryptor(object): try: unpacked_data = PACMAN.unpack(preamble) - magic, ts, sch, meth, iv, doc_id, rev = unpacked_data + magic, sch, meth, ts, iv, doc_id, rev = unpacked_data except struct.error: raise InvalidBlob - if magic != '\x80': + if magic != BLOB_SIGNATURE_MAGIC: raise InvalidBlob # TODO check timestamp if sch != ENC_SCHEME.symkey: @@ -405,27 +404,18 @@ class VerifiedAESWriter(object): return self.aes_writer.end(), self.hmac_writer.end() -def is_symmetrically_encrypted(doc): +def is_symmetrically_encrypted(content): """ - Return True if the document was symmetrically encrypted. + Returns True if the document was symmetrically encrypted. + 'EzcB' is the base64 encoding of \x13\x37 magic number and 1 (symmetrically + encrypted value for enc_scheme flag). - :param doc: The document to check. - :type doc: SoledadDocument + :param doc: The document content as string + :type doc: str :rtype: bool """ - payload = doc.content - if not payload or 'raw' not in payload: - return False - payload = str(payload['raw']) - if len(payload) < PACMAN.size: - return False - payload = _split(payload).next() - if six.indexbytes(payload, 0) != 0x80: - return False - unpacked = PACMAN.unpack(payload) - ts, sch, meth = unpacked[1:4] - return sch == ENC_SCHEME.symkey and meth == ENC_METHOD.aes_256_ctr + return content and content[:13] == '{"raw": "EzcB' # utils diff --git a/client/src/leap/soledad/client/http_target/fetch.py b/client/src/leap/soledad/client/http_target/fetch.py index df07a96a..8676ceed 100644 --- a/client/src/leap/soledad/client/http_target/fetch.py +++ b/client/src/leap/soledad/client/http_target/fetch.py @@ -114,7 +114,7 @@ class HTTPDocFetcher(object): @defer.inlineCallbacks def __atomic_doc_parse(self, doc_info, content, total): doc = SoledadDocument(doc_info['id'], doc_info['rev'], content) - if is_symmetrically_encrypted(doc): + if is_symmetrically_encrypted(content): content = yield self._crypto.decrypt_doc(doc) elif old_crypto.is_symmetrically_encrypted(doc): content = self._deprecated_crypto.decrypt_doc(doc) diff --git a/testing/tests/client/test_crypto.py b/testing/tests/client/test_crypto.py index aad588c0..33a660c9 100644 --- a/testing/tests/client/test_crypto.py +++ b/testing/tests/client/test_crypto.py @@ -110,8 +110,8 @@ class BlobTestCase(unittest.TestCase): assert len(preamble) == _crypto.PACMAN.size unpacked_data = _crypto.PACMAN.unpack(preamble) - pad, ts, sch, meth, iv, doc_id, rev = unpacked_data - assert pad == '\x80' + magic, sch, meth, ts, iv, doc_id, rev = unpacked_data + assert magic == _crypto.BLOB_SIGNATURE_MAGIC assert sch == 1 assert meth == 1 assert iv == blob.iv @@ -155,7 +155,7 @@ class BlobTestCase(unittest.TestCase): assert 'raw' in encrypted doc2 = SoledadDocument('id1', '1') doc2.set_json(encrypted) - assert _crypto.is_symmetrically_encrypted(doc2) + assert _crypto.is_symmetrically_encrypted(encrypted) decrypted = yield crypto.decrypt_doc(doc2) assert len(decrypted) != 0 assert json.loads(decrypted) == payload diff --git a/testing/tests/server/test_server.py b/testing/tests/server/test_server.py index 2f958b29..6710caaf 100644 --- a/testing/tests/server/test_server.py +++ b/testing/tests/server/test_server.py @@ -413,7 +413,8 @@ class EncryptedSyncTestCase( self.assertEqual(soldoc.rev, couchdoc.rev) couch_content = couchdoc.content.keys() self.assertEqual(['raw'], couch_content) - self.assertTrue(_crypto.is_symmetrically_encrypted(couchdoc)) + content = couchdoc.get_json() + self.assertTrue(_crypto.is_symmetrically_encrypted(content)) d = sol1.get_all_docs() d.addCallback(_db1AssertEmptyDocList) |