summaryrefslogtreecommitdiff
path: root/src/leap/soledad/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/leap/soledad/common')
-rw-r--r--src/leap/soledad/common/preamble.py88
1 files changed, 88 insertions, 0 deletions
diff --git a/src/leap/soledad/common/preamble.py b/src/leap/soledad/common/preamble.py
new file mode 100644
index 00000000..724923c5
--- /dev/null
+++ b/src/leap/soledad/common/preamble.py
@@ -0,0 +1,88 @@
+# -*- coding: utf-8 -*-
+# preamble.py
+# Copyright (C) 2017 LEAP Encryption Access Project
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+Preamble is a metadata payload present on encrypted documents. It holds data
+about encryption scheme, iv, document id and sync related data.
+ BLOB_SIGNATURE_MAGIC, -> used to differentiate from other data formats
+ ENC_SCHEME, -> cryptographic scheme (symmetric or asymmetric)
+ ENC_METHOD, -> cipher used, such as AES-GCM or AES-CTR or GPG
+ current_time, -> time.time()
+ self.iv, -> initialization vector if any, or 0 when not applicable
+ str(self.doc_id), -> document id
+ str(self.rev), -> current revision
+ self._content_size) -> size, rounded to ceiling
+"""
+import warnings
+import struct
+import time
+from collections import namedtuple
+PACMAN = struct.Struct('2sbbQ16s255p255pQ')
+LEGACY_PACMAN = struct.Struct('2sbbQ16s255p255p') # DEPRECATED
+BLOB_SIGNATURE_MAGIC = '\x13\x37'
+ENC_SCHEME = namedtuple('SCHEME', 'symkey')(1)
+ENC_METHOD = namedtuple('METHOD', 'aes_256_ctr aes_256_gcm')(1, 2)
+
+
+class InvalidPreambleException(Exception):
+ pass
+
+
+class Preamble:
+
+ def __init__(self, doc_id, rev, scheme, method,
+ timestamp=0, iv='', magic=None, content_size=0):
+ self.doc_id = doc_id
+ self.rev = rev
+ self.scheme = scheme
+ self.method = method
+ self.iv = iv
+ self.timestamp = int(timestamp) or int(time.time())
+ self.magic = magic or BLOB_SIGNATURE_MAGIC
+ self.content_size = int(content_size)
+
+ def encode(self):
+ preamble = PACMAN.pack(
+ self.magic,
+ self.scheme,
+ self.method,
+ self.timestamp,
+ self.iv,
+ str(self.doc_id),
+ str(self.rev),
+ self.content_size)
+ return preamble
+
+
+def decode_preamble(encoded_preamble):
+ preamble_size = len(encoded_preamble)
+ try:
+ if preamble_size == LEGACY_PACMAN.size:
+ unpacked_data = LEGACY_PACMAN.unpack(encoded_preamble)
+ magic, sch, meth, ts, iv, doc_id, rev = unpacked_data
+ warnings.warn("Decoding a legacy preamble without size. " +
+ "This will be deprecated in 0.12. Doc was: " +
+ "doc_id: %s rev: %s" % (doc_id, rev), Warning)
+ return Preamble(doc_id, rev, sch, meth, ts, iv, magic)
+ elif preamble_size == PACMAN.size:
+ unpacked_data = PACMAN.unpack(encoded_preamble)
+ magic, sch, meth, ts, iv, doc_id, rev, size = unpacked_data
+ return Preamble(doc_id, rev, sch, meth, ts, iv, magic, int(size))
+ else:
+ raise InvalidPreambleException("Unexpected preamble size %d",
+ preamble_size)
+ except struct.error as e:
+ raise InvalidPreambleException(e)