import os
+from deltatar import crypto
from deltatar.tarfile import TarFile, GNU_FORMAT
import filesplit
from . import BaseTest
-from . import new_volume_handler
+from . import new_volume_handler, make_new_encryption_volume_handler
+DELTATAR_HEADER_VERSION = 1
+DELTATAR_PARAMETER_VERSION = 1
class EncryptionTest(BaseTest):
"""
Test encryption after compression in tarfiles
"""
- def test_openssl_decrypt(self):
+ def test_cli_decrypt(self):
"""
Create a tar file with only one file inside, using concat
- compression and encryption mode. Then decrypt with openssl,
+ compression and encryption mode. Then decrypt with crypto.py,
decompress it with zcat and untar it with gnu tar.
+
+ Note that in an earlier implementation of the Deltatar crypto
+ layer, files could be decrypted directly using OpenSSL command
+ line tools. With the version 1 parameters this is no longer
+ possible since OpenSSL does not ship with a command line tool
+ that understands GCM and even if it did, it would be very
+ unlikely that it could be made with the raw pdtcrypt format.
+
+ Thus, we rely on the functionality of our encryption library
+ ``crypto.py`` to decrypt on the command line; the rest of the
+ data pipeline (→ gzip → tar → files) remains the same.
"""
# create the content of the file to compress and hash it
hash = self.create_file("big", 50000)
+ # create the encryption handler
+ encryptor = crypto.Encrypt (password="key",
+ version=DELTATAR_HEADER_VERSION,
+ paramversion=DELTATAR_PARAMETER_VERSION)
+
# create the tar file with volumes
- tarobj = TarFile.open("sample.tar.gz.aes128",
- mode="w#gz.aes128",
+ tarobj = TarFile.open("sample.tar.gz.pdtcrypt",
+ mode="w#gz",
format=GNU_FORMAT,
concat_compression=True,
- password='key')
+ encryption=encryptor)
tarobj.add("big")
tarobj.close()
os.unlink("big")
- # extract with normal tar and check output
- filesplit.split_file(b'Salted__', "sample.tar.gz.aes.", "sample.tar.gz.aes128")
+ #filesplit.split_file(b'Salted__', "sample.tar.gz.aes.", "sample.tar.gz.aes128")
- assert os.path.exists("sample.tar.gz.aes.0") # beginning of the tar file
- assert os.path.exists("sample.tar.gz.aes.1") # first file
+ # decrypt outer archive layer with crypto.py
+ assert os.path.exists("sample.tar.gz.pdtcrypt")
+ ret = os.system("python3 -s ./deltatar/crypto.py key <sample.tar.gz.pdtcrypt >sample.tar.gz")
+ assert ret == 0
+ assert os.path.exists("sample.tar.gz")
- os.system("openssl aes-128-cbc -nopad -k 'key' -d -in sample.tar.gz.aes.1 -out sample.tar.gz")
+ # extract with normal tar and check output
os.system("zcat sample.tar.gz 2>/dev/null > sample.tar")
os.system("tar xf sample.tar")
assert os.path.exists("big")
assert hash == self.md5sum("big")
- def test_openssl_multiple_files_decrypt(self):
+ def test_cli_multiple_files_decrypt(self):
"""
Create a tar file with multiple files inside, using concat
- compression and encryption mode. Then decrypt with openssl,
+ compression and encryption mode. Then decrypt with ``crypto.py``,
decompress it with zcat and untar it with gnu tar.
"""
hash["small"] = self.create_file("small", 100)
hash["small2"] = self.create_file("small2", 354)
+ # create the encryption handler
+ encryptor = crypto.Encrypt (password="key",
+ version=DELTATAR_HEADER_VERSION,
+ paramversion=DELTATAR_PARAMETER_VERSION)
+
# create the tar file with volumes
- tarobj = TarFile.open("sample.tar.gz.aes128",
- mode="w#gz.aes128",
+ tarobj = TarFile.open("sample.tar.gz.pdtcrypt",
+ mode="w#gz",
format=GNU_FORMAT,
concat_compression=True,
- password='key')
+ encryption=encryptor)
for k in hash:
tarobj.add(k)
for k in hash:
os.unlink(k)
- # extract with normal tar and check output
- filesplit.split_file(b'Salted__', "sample.tar.gz.aes.", "sample.tar.gz.aes128")
-
- assert os.path.exists("sample.tar.gz.aes.0") # beginning of the tar file
- assert os.path.exists("sample.tar.gz.aes.1") # first file
- assert os.path.exists("sample.tar.gz.aes.2") # second file
- assert os.path.exists("sample.tar.gz.aes.3") # third file
- assert not os.path.exists("sample.tar.gz.aes.4") # nothing else
-
- # extract and check output
- for i in range(1, 4):
- fname = "sample.tar.gz.aes.%d" % i
- os.system("openssl aes-128-cbc -nopad -k 'key' -d -in %s -out sample.tar.gz" % fname)
- os.system("zcat sample.tar.gz 2>/dev/null > sample.tar")
- os.system("tar xf sample.tar")
+ assert os.path.exists("sample.tar.gz.pdtcrypt")
+ ret = os.system("python3 -s ./deltatar/crypto.py key <sample.tar.gz.pdtcrypt >sample.tar.gz")
+ assert ret == 0
+ assert os.path.exists("sample.tar.gz")
+ os.system("zcat sample.tar.gz 2>/dev/null > sample.tar")
+ os.system("tar xf sample.tar")
for key, value in hash.items():
assert os.path.exists(key)
assert value == self.md5sum(key)
+
def test_decrypt(self):
"""
Create a tar file with only one file inside, using concat
# create the content of the file to compress and hash it
hash = self.create_file("big", 50000)
+ # encryption handling
+ encryptor = crypto.Encrypt (password="key",
+ version=DELTATAR_HEADER_VERSION,
+ paramversion=DELTATAR_PARAMETER_VERSION)
+ decryptor = crypto.Decrypt (password="key")
+
# create the tar file with volumes
- tarobj = TarFile.open("sample.tar.gz.aes128",
- mode="w#gz.aes128",
+ tarobj = TarFile.open("sample.tar.gz.pdtcrypt",
+ mode="w#gz",
format=GNU_FORMAT,
concat_compression=True,
- password='key')
+ encryption=encryptor)
tarobj.add("big")
tarobj.close()
os.unlink("big")
- tarobj = TarFile.open("sample.tar.gz.aes128",
- mode="r#gz.aes128",
+ tarobj = TarFile.open("sample.tar.gz.pdtcrypt",
+ mode="r#gz",
format=GNU_FORMAT,
- password='key')
+ encryption = decryptor)
tarobj.extractall()
tarobj.close()
assert os.path.exists("big")
hash["small"] = self.create_file("small", 100)
hash["small2"] = self.create_file("small2", 354)
+ encryptor = crypto.Encrypt (password="key",
+ version=DELTATAR_HEADER_VERSION,
+ paramversion=DELTATAR_PARAMETER_VERSION)
+
# create the tar file with volumes
- tarobj = TarFile.open("sample.tar.gz.aes128",
- mode="w#gz.aes128",
+ tarobj = TarFile.open("sample.tar.gz.pdtcrypt",
+ mode="w#gz",
format=GNU_FORMAT,
concat_compression=True,
- password='key')
+ encryption=encryptor)
for k in hash:
tarobj.add(k)
for k in hash:
os.unlink(k)
- tarobj = TarFile.open("sample.tar.gz.aes128",
- mode="r#gz.aes128",
+ decryptor = crypto.Decrypt (password="key")
+ tarobj = TarFile.open("sample.tar.gz.pdtcrypt",
+ mode="r#gz",
format=GNU_FORMAT,
- password='key')
+ encryption=decryptor)
+
tarobj.extractall()
tarobj.close()
assert os.path.exists(key)
assert value == self.md5sum(key)
+
def test_multivol_file_decrypt(self):
'''
Test multivol tarball with encryption.
hash["small"] = self.create_file("small", 100)
hash["small2"] = self.create_file("small2", 354)
- # create the tar file with volumes
- tarobj = TarFile.open("sample.tar.gz.aes128",
- mode="w#gz.aes128",
- password='key',
- concat_compression=True,
- max_volume_size=20000,
- new_volume_handler=new_volume_handler)
-
- for k in hash:
- tarobj.add(k)
- tarobj.close()
-
- assert os.path.exists("sample.tar.gz.aes128")
- for k in hash:
- os.unlink(k)
-
- # extract
- tarobj = TarFile.open("sample.tar.gz.aes128",
- mode="r#gz.aes128",
- password="key",
- new_volume_handler=new_volume_handler)
- tarobj.extractall()
- tarobj.close()
-
- # check output
- for key, value in hash.items():
- assert os.path.exists(key)
- assert value == self.md5sum(key)
-
- def test_multivol_file_decrypt_aes256(self):
- '''
- Test multivol tarball with encryption aes256
- '''
+ # encryption handler
+ encryptor = crypto.Encrypt (password="key",
+ version=DELTATAR_HEADER_VERSION,
+ paramversion=DELTATAR_PARAMETER_VERSION)
- # create sample data
- hash = dict()
- hash["big"] = self.create_file("big", 50000)
- hash["big2"] = self.create_file("big2", 10200)
- hash["small"] = self.create_file("small", 100)
- hash["small2"] = self.create_file("small2", 354)
+ # plug the encryption context into the volume handler
+ encrypt_volume = make_new_encryption_volume_handler (encryptor)
- # create the tar file with volumes
- tarobj = TarFile.open("sample.tar.gz.aes256",
- mode="w#gz.aes256",
- password='key',
+ # create the tar file with volumes; we need to use a low compression
+ # level to force volume split because the test data has too little
+ # entropy
+ tarobj = TarFile.open("sample.tar.gz.pdtcrypt",
+ mode="w#gz",
concat_compression=True,
max_volume_size=20000,
- new_volume_handler=new_volume_handler)
+ compresslevel=0,
+ new_volume_handler=encrypt_volume,
+ encryption=encryptor)
for k in hash:
tarobj.add(k)
tarobj.close()
- assert os.path.exists("sample.tar.gz.aes256")
+ assert os.path.exists("sample.tar.gz.pdtcrypt")
for k in hash:
os.unlink(k)
+ # decrypt
+ decryptor = crypto.Decrypt (password="key")
+
+ # plug the encryption context into the volume handler
+ decrypt_volume = make_new_encryption_volume_handler (decryptor)
+
# extract
- tarobj = TarFile.open("sample.tar.gz.aes256",
- mode="r#gz.aes256",
- password="key",
- new_volume_handler=new_volume_handler)
+ tarobj = TarFile.open("sample.tar.gz.pdtcrypt",
+ mode="r#gz",
+ new_volume_handler=decrypt_volume,
+ encryption=decryptor)
tarobj.extractall()
tarobj.close()
assert os.path.exists(key)
assert value == self.md5sum(key)
- def test_openssl_decrypt_256(self):
- """
- Create a tar file with only one file inside, using concat
- compression and encryption mode. Then decrypt with openssl,
- decompress it with zcat and untar it with gnu tar.
-
- Using aes 256.
- """
-
- # create the content of the file to compress and hash it
- hash = self.create_file("big", 50000)
-
- # create the tar file with volumes
- tarobj = TarFile.open("sample.tar.gz.aes256",
- mode="w#gz.aes256",
- format=GNU_FORMAT,
- concat_compression=True,
- password='key')
- tarobj.add("big")
- tarobj.close()
- os.unlink("big")
-
- # extract with normal tar and check output
- filesplit.split_file(b'Salted__', "sample.tar.gz.aes.", "sample.tar.gz.aes256")
-
- assert os.path.exists("sample.tar.gz.aes.0") # beginning of the tar file
- assert os.path.exists("sample.tar.gz.aes.1") # first file
-
- os.system("openssl aes-256-cbc -nopad -k 'key' -d -in sample.tar.gz.aes.1 -out sample.tar.gz")
- os.system("zcat sample.tar.gz 2>/dev/null > sample.tar")
- os.system("tar xf sample.tar")
- assert os.path.exists("big")
- assert hash == self.md5sum("big")