ORIGINAL POST 03.19.2022
Here is one way to accomplish your use case using pyzipper
import fs
import pyzipper
# create in-memory file system
mem_fs = fs.open_fs('mem://')
mem_fs.makedir('hidden_dir')
# generate data
data = b'ab' * 10
secret_password = b'super secret password'
# Create encrypted password protected ZIP file in-memory
with pyzipper.AESZipFile(mem_fs.open('/hidden_dir/password_protected.zip', 'wb'),
'w',
compression=pyzipper.ZIP_LZMA,
encryption=pyzipper.WZ_AES) as zf:
zf.setpassword(secret_password)
zf.writestr('data.txt', data)
# Read encrypted password protected ZIP file from memory
with pyzipper.AESZipFile(mem_fs.open('/hidden_dir/password_protected.zip', 'rb')) as zf:
zf.setpassword(secret_password)
my_secrets = zf.read('data.txt')
print(my_secrets)
# output
b'abababababababababab'
UPDATED 03.21.2022
Reading through our comments you continue to raise concerns about the cryptography components of modules, such as pyzipper, but not 7Z LIB/SDK. Here is an academic paper on 7Z LIB/SDK version 19 cryptography.
Based on your concerns have you considered encrypting your data in memory prior to writing it to a zipfile?
Here is an example for doing this and writing the encrypted data to a file in memory:
import os
import fs
import base64
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
mem_fs = fs.open_fs('mem://')
mem_fs.makedir('hidden_dir')
password = b"password"
salt = os.urandom(16)
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=390000,
)
key = base64.urlsafe_b64encode(kdf.derive(password))
f = Fernet(key)
data = b'ab' * 10
encrypted_message = f.encrypt(data)
with mem_fs.open('hidden_dir/encrypted.text', 'wb') as in_file_in_memory:
in_file_in_memory.write(encrypted_message)
in_file_in_memory.close()
with mem_fs.open('hidden_dir/encrypted.text', 'rb') as out_file_in_memory:
raw_data = out_file_in_memory.read()
decrypted_data = f.decrypt(raw_data)
print(decrypted_data)
# output
b'abababababababababab'
Previously in the comments I mentioned key management, which is similar to maintaining a list of passwords for your zip archives.
I don't know your setup, but you could pregenerate keys in advance and stored them in a secure way for use in your code.
I don't have 7z installed on my Mac, so I could only give you pseudocode. The examples below aren't using 7z.
import os
import fs
import base64
import pyzipper
from zipfile import ZipFile
from cryptography.fernet import Fernet
mem_fs = fs.open_fs('mem://')
mem_fs.makedir('hidden_dir')
# pregenerate key
f = Fernet(b'-6_WO-GLrlXexdSbon_fKJoVOVBh66LdYrEM0Kvcwf0=')
data = b'ab' * 10
encrypted_message = f.encrypt(data)
with mem_fs.open('hidden_dir/encrypted.text', 'wb') as in_file_in_memory:
in_file_in_memory.write(encrypted_message)
in_file_in_memory.close()
# This uses standard ZIP with no password, but the data
# is encrypted
with mem_fs.open('hidden_dir/encrypted.text', 'rb') as out_file_in_memory:
raw_data = out_file_in_memory.read()
with ZipFile('archive.zip', mode='w') as zip_file:
zip_file.writestr('file.txt', raw_data)
# This uses pyzipper to create a password word protected
# encrypted file, which stores the encrypted.text.
# overkill, because the data is already encrypted prior
with mem_fs.open('hidden_dir/encrypted.text', 'rb') as out_file_in_memory:
raw_data = out_file_in_memory.read()
secret_password = b'super secret password'
# Create encrypted password protected ZIP file in-memory
with pyzipper.AESZipFile('password_protected.zip',
'w',
compression=pyzipper.ZIP_LZMA,
encryption=pyzipper.WZ_AES) as zf:
zf.setpassword(secret_password)
zf.writestr('data.txt', raw_data)
I'm still looking into how to pipe this encrypted.text to subprocess 7-zip.
pyminizip
, orpyzipper
? Alternately, did you try to check if any of the tools you mightsubprocess.call
, take the input data from standard input? If they do, do you see how to use pipes to solve the problem?7z.exe
if we can pipe binary data to it without writing to a temp file)pyminizip
works from a file, not from in-memory data.