Browse Source

UNENCRYPTED (and unauthenticated) "ciphersuite"

it can be used to integrate the plaintext mode with the AEAD modes, both use same api now.
Thomas Waldmann 8 years ago
parent
commit
310b4b7775
2 changed files with 47 additions and 1 deletions
  1. 36 0
      src/borg/crypto/low_level.pyx
  2. 11 1
      src/borg/testsuite/crypto.py

+ 36 - 0
src/borg/crypto/low_level.pyx

@@ -189,6 +189,42 @@ cdef Py_buffer ro_buffer(object data) except *:
     return view
     return view
 
 
 
 
+class UNENCRYPTED:
+    # Layout: HEADER + PlainText
+
+    def __init__(self, mac_key, enc_key, iv=None):
+        assert mac_key is None
+        assert enc_key is None
+        self.set_iv(iv)
+
+    def encrypt(self, data, header=b'', aad_offset=0, iv=None):
+        """
+        IMPORTANT: it is called encrypt to satisfy the crypto api naming convention,
+        but this does NOT encrypt and it does NOT compute and store a MAC either.
+        """
+        if iv is not None:
+            self.set_iv(iv)
+        assert self.iv is not None, 'iv needs to be set before encrypt is called'
+        return header + data
+
+    def decrypt(self, envelope, header_len=0, aad_offset=0):
+        """
+        IMPORTANT: it is called decrypt to satisfy the crypto api naming convention,
+        but this does NOT decrypt and it does NOT verify a MAC either, because data
+        is not encrypted and there is no MAC.
+        """
+        return memoryview(envelope)[header_len:]
+
+    def block_count(self, length):
+        return 0
+
+    def set_iv(self, iv):
+        self.iv = iv
+
+    def next_iv(self):
+        return self.iv
+
+
 cdef class AES256_CTR_HMAC_SHA256:
 cdef class AES256_CTR_HMAC_SHA256:
     # Layout: HEADER + HMAC 32 + IV 8 + CT (same as attic / borg < 1.2 IF HEADER = TYPE_BYTE, no AAD)
     # Layout: HEADER + HMAC 32 + IV 8 + CT (same as attic / borg < 1.2 IF HEADER = TYPE_BYTE, no AAD)
 
 

+ 11 - 1
src/borg/testsuite/crypto.py

@@ -1,6 +1,6 @@
 from binascii import hexlify, unhexlify
 from binascii import hexlify, unhexlify
 
 
-from ..crypto.low_level import AES256_CTR_HMAC_SHA256, AES256_GCM, AES256_OCB, CHACHA20_POLY1305, \
+from ..crypto.low_level import AES256_CTR_HMAC_SHA256, AES256_GCM, AES256_OCB, CHACHA20_POLY1305, UNENCRYPTED, \
                      IntegrityError, hmac_sha256, blake2b_256, openssl10
                      IntegrityError, hmac_sha256, blake2b_256, openssl10
 from ..crypto.low_level import bytes_to_long, bytes_to_int, long_to_bytes, bytes16_to_int, int_to_bytes16, increment_iv
 from ..crypto.low_level import bytes_to_long, bytes_to_int, long_to_bytes, bytes16_to_int, int_to_bytes16, increment_iv
 from ..crypto.low_level import hkdf_hmac_sha512
 from ..crypto.low_level import hkdf_hmac_sha512
@@ -41,6 +41,16 @@ class CryptoTestCase(BaseTestCase):
         self.assert_equal(increment_iv(iva, 2), ivc)
         self.assert_equal(increment_iv(iva, 2), ivc)
         self.assert_equal(increment_iv(iv0, 2**64), ivb)
         self.assert_equal(increment_iv(iv0, 2**64), ivb)
 
 
+    def test_UNENCRYPTED(self):
+        iv = b''  # any IV is ok, it just must be set and not None
+        data = b'data'
+        header = b'header'
+        cs = UNENCRYPTED(None, None, iv)
+        envelope = cs.encrypt(data, header=header)
+        self.assert_equal(envelope, header + data)
+        got_data = cs.decrypt(envelope, header_len=len(header))
+        self.assert_equal(got_data, data)
+
     def test_AES256_CTR_HMAC_SHA256(self):
     def test_AES256_CTR_HMAC_SHA256(self):
         # this tests the layout as in attic / borg < 1.2 (1 type byte, no aad)
         # this tests the layout as in attic / borg < 1.2 (1 type byte, no aad)
         mac_key = b'Y' * 32
         mac_key = b'Y' * 32