From 30d55520792a8166872910b56017fce9b49a73a0 Mon Sep 17 00:00:00 2001 From: clach04 Date: Mon, 25 Nov 2024 20:48:50 -0800 Subject: [PATCH] Initial age Actual Good Encryption support, passphrase ONLY - decrypt only --- puren_tonbo/__init__.py | 42 +++++++++++++++++++++++++++++++++++++++++ requirements.txt | 1 + setup.py | 4 +++- 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/puren_tonbo/__init__.py b/puren_tonbo/__init__.py index 5978b4b..1047e26 100644 --- a/puren_tonbo/__init__.py +++ b/puren_tonbo/__init__.py @@ -98,6 +98,14 @@ def __bool__(self): except ImportError: vimdecrypt = fake_module('vimdecrypt') +try: + #import ssage # https://github.com/esoadamo/ssage/ # does not (yet?) support passphrases + import age # https://github.com/jojonas/pyage + import age.file + import age.keys.password +except ImportError: + #ssage = fake_module('ssage') + age = fake_module('age') try: import puren_tonbo.mzipaes as mzipaes @@ -636,6 +644,35 @@ def read_from(self, file_object): def write_to(self, file_object, byte_data): chi_io.write_encrypted_file(file_object, self.key, byte_data) +class Age(EncryptedFile): + description = 'AGE - Actually Good Encryption (passphrase ONLY)' + extensions = [ + '.age', + ] + + def read_from(self, file_object): + # TODO catch exceptions and raise PurenTonboException() + # TODO AsciiArmoredInput() + #encrypted_bytes = file_object.read() + password = self.key + if not isinstance(password, bytes): + password = password.decode("utf-8") + + identities = [age.keys.password.PasswordKey(password)] + with age.file.Decryptor(identities, file_object) as decryptor: + plaintext = decryptor.read() + + return plaintext + + def write_to(self, file_object, byte_data): + password = self.key + if not isinstance(password, bytes): + password = password.decode("utf-8") + + raise NotImplementedError + crypted_bytes = b'TODO' + file_object.write(crypted_bytes) + # TODO AE-2 (no CRC), otherwise the same as AE-1 - see https://github.com/clach04/puren_tonbo/wiki/zip-format class ZipEncryptedFileBase(EncryptedFile): _filename = 'encrypted.md' # filename inside of (encrypted) zip file @@ -777,6 +814,11 @@ class ZipBzip2AES(ZipAES): for file_extension in enc_class.extensions: file_type_handlers[file_extension] = enc_class +if age: + for enc_class in (Age, ): + for file_extension in enc_class.extensions: + file_type_handlers[file_extension] = enc_class + if jenc: # FIXME, handle this via introspection, see code above for RawFile # https://github.com/clach04/jenc-py/issues/7 diff --git a/requirements.txt b/requirements.txt index 2247527..c5b2c79 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,6 +6,7 @@ pyzipper; python_version > "2.7" python-gnupg openssl_enc_compat # https://github.com/clach04/openssl_enc_compat/ jenc>=0.0.3 +age # 0.5.1 # pywin32 # Windows only - for GUI password prompt percolator diff --git a/setup.py b/setup.py index d9dd84b..39be438 100644 --- a/setup.py +++ b/setup.py @@ -130,11 +130,13 @@ platforms='any', # or distutils.util.get_platform() install_requires=install_requires, extras_require={ + 'age': ['age', ], # 0.5.1 'chi_io': ['chi_io', ], 'jenc': ['jenc>=0.0.3', ], + #'ssage': ['ssage', ], # ssage-1.4.0 # TODO pyvim # TODO python-gnupg (consider replacements before implementing https://github.com/clach04/puren_tonbo/issues/118) - 'all': ['chi_io', 'jenc>=0.0.3', ], # convience, all of the above. NOTE duplicate of above + 'all': ['age', 'chi_io', 'jenc>=0.0.3',], # convenience, all of the above. NOTE duplicate of above }, zip_safe=True, )