specify salt and version in ctor when encrypting
authorPhilipp Gesang <philipp.gesang@intra2net.com>
Fri, 7 Apr 2017 07:29:27 +0000 (09:29 +0200)
committerPhilipp Gesang <philipp.gesang@intra2net.com>
Mon, 7 Aug 2017 12:02:45 +0000 (14:02 +0200)
Simplify the signature of Encrypt.next() by removing the salt and
version arguments: This will make the encryptor reuse the values
it already has which was either passed to or randomly generated
by the ctor. Currently there is no case where we’d need to change
the salt or version during encryption. When decrypting, the
values from the headers are used anyways so nothing changes over
there.

deltatar/crypto.py
deltatar/deltatar.py
deltatar/tarfile.py

index 56b7a66..5bfefe7 100755 (executable)
@@ -368,14 +368,14 @@ class Crypto (object):
     cnt  = None # file counter (uint32_t != 0)
     iv   = None # current IV
     pfx  = None # accu for 64 bit fixed parts of IV
-    password = None
+    password     = None
+    paramversion = None
     stats = { "in"  : 0
             , "out" : 0
             , "obj" : 0 }
 
     ctsize  = -1
     ptsize  = -1
-    paramversion = None
     info_counter_used = False
 
     def __init__ (self, *al, **akv):
@@ -419,7 +419,6 @@ class Crypto (object):
         kdf = kdf_by_version (paramversion)
         if kdf is not None:
             self.key, self.nacl = kdf (password, nacl)
-
         self.paramversion = paramversion
 
 
@@ -448,19 +447,17 @@ class Crypto (object):
 
 class Encrypt (Crypto):
 
-    curobj = None
-    hdrdum = None
-    paramversion = None
+    lastinfo     = None
+    version      = None
     paramenc     = None
 
-    def __init__ (self, password, paramversion, nacl=None,
+    def __init__ (self, password, version, paramversion, nacl=None,
                   counter=AES_GCM_IV_CNT_DATA):
         if len (password) == 0:
             raise Exception ("XXX refusing to encrypt with empty password")
-        self.pfx = [ ]
-        self.paramversion = paramversion
-        defs = ENCRYPTION_PARAMETERS.get(self.paramversion)
-        self.paramenc = defs ["enc"]
+        self.pfx          = [ ]
+        self.version      = version
+        self.paramenc     = ENCRYPTION_PARAMETERS.get (paramversion) ["enc"]
 
         super().__init__ (password, paramversion, nacl, counter=counter,
                           nextpfx=lambda: self.pfx.append (os.urandom(8)))
@@ -470,8 +467,7 @@ class Encrypt (Crypto):
         return struct.pack(FMT_I2N_IV, self.pfx [-1], self.cnt)
 
 
-    def next (self, filename, version, nacl, counter=None):
-        self.curobj = (filename, version, nacl or self.nacl)
+    def next (self, filename, counter=None):
         self.iv = self.iv_make ()
         if self.paramenc == "aes-gcm":
             self.enc = Cipher \
@@ -484,22 +480,23 @@ class Encrypt (Crypto):
         else:
             raise Exception ("XXX garbage encryption parameter %d → %r"
                              % (self.paramversion, enc))
-        self.hdrdum = hdr_make_dummy (filename)
-        super().next (self.password, self.paramversion, nacl)
+        hdrdum = hdr_make_dummy (filename)
+        self.lastinfo = (filename, hdrdum)
+        super().next (self.password, self.paramversion, self.nacl)
 
         self.set_object_counter (counter if counter is not None else self.cnt + 1)
-        return self.hdrdum
+        return hdrdum
 
 
     def done (self, cmpdata):
-        if cmpdata != self.hdrdum:
+        filename, hdrdum = self.lastinfo
+        if cmpdata != hdrdum:
             raise Exception ("XXX bad sync for writing header") ## we need to converge on a sensible error handling strategy
         data = self.enc.finalize ()
         self.stats ["out"] += len (data)
         self.ctsize += len (data)
-        (filename, version, nacl) = self.curobj
-        ok, hdr = hdr_from_params (version, self.paramversion, nacl, self.iv,
-                                   self.ctsize, self.enc.tag)
+        ok, hdr = hdr_from_params (self.version, self.paramversion, self.nacl,
+                                   self.iv, self.ctsize, self.enc.tag)
         if ok is False:
             raise Exception ("XXX error constructing header: %r" % hdr) ## we need to converge on a sensible error handling strategy
         return data, hdr, self.pfx
index 0fa8e48..bd0dc67 100644 (file)
@@ -601,8 +601,10 @@ class DeltaTar(object):
 
         # setup for encrypting payload
         if self.password is not None:
-            self.crypto_ctx = crypto.Encrypt (self.password,
-                                              paramversion=DELTATAR_PARAMETER_VERSION)
+            self.crypto_ctx = \
+                    crypto.Encrypt (self.password,
+                                    version=DELTATAR_HEADER_VERSION,
+                                    paramversion=DELTATAR_PARAMETER_VERSION)
 
         # some initialization
         self.vol_no = 0
@@ -689,8 +691,7 @@ class DeltaTar(object):
         index_sink = self.open_auxiliary_file(index_path, 'w') # **NOT** an fd
         if index_sink.encryption is not None:
             self.nacl = index_sink.encryption.nacl
-            dummyhdr = index_sink.encryption.next \
-                        (path, version=DELTATAR_HEADER_VERSION, nacl=self.nacl)
+            dummyhdr = index_sink.encryption.next (path)
             index_sink.write (dummyhdr)
         index_sink.write (index_accu.getvalue ())
         index_sink.close ()
@@ -771,8 +772,10 @@ class DeltaTar(object):
 
         # setup for encrypting payload
         if self.password is not None:
-            self.crypto_ctx = crypto.Encrypt (self.password,
-                                              paramversion=DELTATAR_PARAMETER_VERSION)
+            self.crypto_ctx = \
+                    crypto.Encrypt (self.password,
+                                    version=DELTATAR_HEADER_VERSION,
+                                    paramversion=DELTATAR_PARAMETER_VERSION)
         # some initialization
         self.vol_no = 0
 
index 4143821..62b76f6 100644 (file)
@@ -115,9 +115,6 @@ GNU_FORMAT = 1                  # GNU tar format
 PAX_FORMAT = 2                  # POSIX.1-2001 (pax) format
 DEFAULT_FORMAT = GNU_FORMAT
 
-DELTATAR_HEADER_VERSION    = 1
-DELTATAR_PARAMETER_VERSION = 1
-
 GZ_FMT_HEADER        = b"<BBBBLBB"
 GZ_MAGIC             = (0x1f, 0x8b) # 0o37, 0o213
 GZ_METHOD_DEFLATE    = 0x08 # 0o10
@@ -531,9 +528,7 @@ class _Stream:
             # secondly, assemble the header with the updated parameters
             # and commit it directly to the underlying stream, bypassing the
             # encryption layer in .__write().
-            dummyhdr = self.encryption.next (entry,
-                                             version=DELTATAR_HEADER_VERSION,
-                                             nacl=self.encryption.nacl)
+            dummyhdr = self.encryption.next (entry)
             if dummyhdr is None:
                 raise EncryptionError ("Crypto.next(): bad dummy header") # XXX