summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Shyba <victor1984@riseup.net>2016-11-30 00:07:24 -0300
committerVictor Shyba <victor1984@riseup.net>2016-11-30 01:55:33 -0300
commitefb37c37bda119d3f73cc4d79f3b663585219c23 (patch)
tree4cfa559cd7875635ac899e1023b89ce0e933b407
parent388e2b2916e49b0992ff7ffbf3fe4e212386b7b0 (diff)
[refactor] improve blob signature magic usage
Our magic value wasn't being used and were represented as a string. Refactored it to a constant, increased it's size to 2 bytes and optimzed is_symmetrically_encrypted to look for the magic and symmetrically encrypted flag under base64 encoding. Most file types will use this feature to help identifying themselves, so it got refactored to serve the purpose it was created.
-rw-r--r--client/pkg/requirements.pip1
-rw-r--r--client/src/leap/soledad/client/_crypto.py36
-rw-r--r--client/src/leap/soledad/client/http_target/fetch.py2
-rw-r--r--testing/tests/client/test_crypto.py6
-rw-r--r--testing/tests/server/test_server.py3
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)