diff --git a/README.md b/README.md index b444412..5cc0365 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ Plain text notes search/edit tool that supports encrypted files, formats: * AES-256-CTR PBKDF2 (iterations 1000) * [ccrypt](https://ccrypt.sourceforge.net/) - Rijndael-256 (no authentication) * [GnuPG (OpenPGP, gpg)](https://www.gnupg.org/) - [symmetric](https://www.gnupg.org/gph/en/manual/r656.html) see https://tutonics.com/articles/gpg-encryption-guide-part-4-symmetric-encryption/#:~:text=Another%20type%20of%20cryptographic%20solution,also%20called%20a%20shared%20secret. + * [OpenSSL 1.1.1 aes-256-cbc](https://github.com/openssl/openssl) - [symmetric](https://www.openssl.org/docs/manmaster/man1/openssl.html) AES-256-CBC encryption with pbkdf2. * [Tombo (chi)](https://github.com/clach04/chi_io?tab=readme-ov-file) - blowfish-ECB * [vim VimCrypt](https://vimdoc.sourceforge.net/htmldoc/editing.html#encryption) encrypted files READ ONLY - VimCrypt (1-3) zip, blowfish, and blowfish2 @@ -180,6 +181,7 @@ Also see https://github.com/clach04/puren_tonbo/wiki/tool-ptig aes256.zip - ZipAES - AES-256 ZIP AE-1 DEFLATED (regular compression) aeszip - ZipAES - AES-256 ZIP AE-1 DEFLATED (regular compression) old.zip - ZipAES - AES-256 ZIP AE-1 DEFLATED (regular compression) + openssl_aes256cbc_pbkdf2_10k - OpenSslEnc10k - OpenSSL 1.1.1 pbkdf2 iterations 10000 aes-256-cbc aes256stored.zip - ZipNoCompressionAES - AES-256 ZIP AE-1 STORED (uncompressed) oldstored.zip - ZipNoCompressionAES - AES-256 ZIP AE-1 STORED (uncompressed) aes256lzma.zip - ZipLzmaAES - AES-256 ZIP AE-1 LZMA @@ -342,6 +344,25 @@ Requires a gpg binary, download from https://gnupg.org/download/ Also see `encryptcli` from https://github.com/evpo/EncryptPad/ +#### OpenSSL 1.1.1 AES + +OpenSSL 1.1.1 compatible (with a very small subset of options). + + ptcat --note-root=. puren_tonbo/tests/data/aesop_win.openssl_aes256cbc_pbkdf2_10k + +Intended to allow decryption of files generated with OpenSSL 1.1.1 and vice-versa. Supported OpenSSL flags/formats: + + openssl enc -e aes-256-cbc -salt -pbkdf2 -iter 10000 -in in_file -base64 -out out_file + openssl dec -d aes-256-cbc -salt -pbkdf2 -iter 10000 -in in_file -base64 -out out_file + + echo hello| openssl enc -e aes-256-cbc -salt -pbkdf2 -iter 10000 -in - -base64 -out - -pass pass:password + echo hello| openssl enc -e -aes-256-cbc -in - -out - -salt -pbkdf2 -iter 10000 -pass pass:password + +NOTE PBKDF2 iteration count of 10,000 is the default in OpenSSL 1.1.1 and is considered too few in 2023. +Older versions of OpenSSL did not support; PBKDF2 (and ergo iterations) and salt and used a much weaker KDF. + +Supports binary/raw and base64 encoded/ASCII armored files. +ONLY supports aes-256-cbc with salt and pbkdf2 KDF with 10,000 interations. #### AES-256 zip diff --git a/puren_tonbo/__init__.py b/puren_tonbo/__init__.py index 7b6ad86..ac34576 100644 --- a/puren_tonbo/__init__.py +++ b/puren_tonbo/__init__.py @@ -66,6 +66,11 @@ def __bool__(self): except ImportError: keyring = fake_module('keyring') +try: + from openssl_enc_compat.cipher import OpenSslEncDecCompat # https://github.com/clach04/openssl_enc_compat/ +except ImportError: + OpenSslEncDecCompat = fake_module('openssl_enc_compat') + try: import pyzipper # https://github.com/danifus/pyzipper NOTE py3 only except ImportError: @@ -419,6 +424,23 @@ def write_to(self, file_object, byte_data): file_object.write(enc_data.data) +class OpenSslEnc10k(EncryptedFile): + description = 'OpenSSL 1.1.1 pbkdf2 iterations 10000 aes-256-cbc' + extensions = [ + '.openssl_aes256cbc_pbkdf2_10k', # generated via openssl enc -e -aes-256-cbc -in plain_in -out crypted_out.openssl_aes256cbc_pbkdf2_10k -salt -pbkdf2 -iter 10000 + ] + # TODO KeepOut .kpt files - https://antofthy.gitlab.io/software/keepout.sh.txt + + def read_from(self, file_object): + # TODO catch exceptions and raise PurenTonboException() + data = file_object.read() + password = self.key + if not isinstance(password, bytes): + password = password.decode("utf-8") + cipher = OpenSslEncDecCompat(password) + plaintext = cipher.decrypt(data) # guesses if base64 encoded or note + return plaintext + class TomboBlowfish(EncryptedFile): """Read/write Tombo (modified) Blowfish encrypted files Compatible with files in: @@ -596,6 +618,10 @@ class ZipBzip2AES(ZipAES): for enc_class in (PurePyZipAES, ZipNoCompressionPurePyZipAES): for file_extension in enc_class.extensions: file_type_handlers[file_extension] = enc_class +if OpenSslEncDecCompat: + for enc_class in (OpenSslEnc10k, ): + for file_extension in enc_class.extensions: + file_type_handlers[file_extension] = enc_class if pyzipper: # potentially overwrite PurePyZipAES and ZipNoCompressionPurePyZipAES as default zip support for enc_class in (ZipAES, ZipNoCompressionAES, ZipLzmaAES, ZipBzip2AES): for file_extension in enc_class.extensions: diff --git a/puren_tonbo/tests/data/README.md b/puren_tonbo/tests/data/README.md index a2227b5..b416b6a 100644 --- a/puren_tonbo/tests/data/README.md +++ b/puren_tonbo/tests/data/README.md @@ -20,6 +20,11 @@ Ideally generated with external tools that Puren Tonbo can validate against. * Approx 1.5Kb. * Command: type aesop.txt | ccrypt -e > aesop_win_ccrypt.cpt + * aesop_win.openssl_aes256cbc_pbkdf2_10k - OpenSSL aes-256-cbc pbkdf2 encrypted from `aesop.txt` + Created with Windows win64 with windows-git openssl.exe - `"C:\Program Files\Git\mingw64\bin\openssl.exe" enc -e -aes-256-cbc -in aesop.txt -out aesop_win.openssl_aes256cbc_pbkdf2_10k -salt -pbkdf2 -iter 10000 -pass pass:password` + * password is `password` + * Approx 1.1Kb. + * aesop_win_encryptpad.asc - gpg (GnuPG) encrypted from `aesop.txt` Created with Windows win32 encryptpad 0.5.0.2 beta https://github.com/evpo/EncryptPad/ * password is `password` diff --git a/puren_tonbo/tests/data/aesop_win.openssl_aes256cbc_pbkdf2_10k b/puren_tonbo/tests/data/aesop_win.openssl_aes256cbc_pbkdf2_10k new file mode 100644 index 0000000..afd68dd Binary files /dev/null and b/puren_tonbo/tests/data/aesop_win.openssl_aes256cbc_pbkdf2_10k differ diff --git a/puren_tonbo/tests/testsuite.py b/puren_tonbo/tests/testsuite.py index 2ffa8c9..a33de76 100644 --- a/puren_tonbo/tests/testsuite.py +++ b/puren_tonbo/tests/testsuite.py @@ -547,6 +547,7 @@ def test_aesop_linux_vimcrypt1(self): data = note_root.note_contents(test_note_filename, password) self.assertEqual(self.plain_text_data_linux_newlines, data) +# TODO test openssl_aes256cbc_pbkdf2_10k # Tests write/encryption to disk diff --git a/requirements.txt b/requirements.txt index 4deaa82..cdb52b9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,3 +4,4 @@ keyring==18.0.1 # last py2.7 and Py3 compat version pycryptodome # for performance - actually used by pyzipper so not explictly needed pyzipper; python_version > "2.7" python-gnupg +openssl_enc_compat # https://github.com/clach04/openssl_enc_compat/ diff --git a/setup.py b/setup.py index ad571b8..55fd119 100644 --- a/setup.py +++ b/setup.py @@ -38,7 +38,7 @@ # TODO/FIXME dupe of requirements.txt - also chi_io missing here (as not on pypi) -install_requires = ['colorama', 'pycryptodome', 'python-gnupg'] +install_requires = ['colorama', 'pycryptodome', 'python-gnupg', 'openssl_enc_compat'] if is_py3: install_requires += ['pyzipper'] # pyzipperis python 3.x+ # TODO consider extras_require, for things like; pyvim, python-gnupg, chi_io