Repository: reactive-firewall/PiAP-python-tools

Issue:
Add Encryption
- [ ] need to encrypt data at rest

Discussion:

Patch:
diff --git a/.coveragerc b/.coveragerc
index 7423488..9b946b3 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -9,11 +9,12 @@ exclude_lines =
     pragma: no cover
 
     except Exception
+    except BaseException:
     # Don't complain if tests don't hit defensive assertion code:
     raise AssertionError
     raise NotImplementedError
     raise ImportError
-    except unittest.SkipTest as skiperr
+    except unittest.SkipTest
     except IOError
     except OSError
 
diff --git a/Makefile b/Makefile
index f12ad18..2751eeb 100644
--- a/Makefile
+++ b/Makefile
@@ -133,6 +133,9 @@ cleanup:
 	$(QUIET)rm -f ./the_test_file*.json 2>/dev/null || true
 	$(QUIET)rm -f ./the_test_file*.yml 2>/dev/null || true
 	$(QUIET)rm -f ./the_test_file*.yaml 2>/dev/null || true
+	$(QUIET)rm -f ./the_test_file*.enc 2>/dev/null || true
+	$(QUIET)rm -f ./.weak_test_key_* || true
+	$(QUIET)rm -f ./test.secret || true
 	$(QUIET)rm -f ./the_test_url_file*.txt 2>/dev/null || true
 	$(QUIET)rm -f /tmp/.beta_PiAP_weak_key 2>/dev/null || true
 
diff --git a/piaplib/keyring/clearify.py b/piaplib/keyring/clearify.py
index 22101e0..06e21a8 100644
--- a/piaplib/keyring/clearify.py
+++ b/piaplib/keyring/clearify.py
@@ -52,6 +52,13 @@
 except Exception:
 	import pku.remediation as remediation
 
+try:
+	from remediation import PiAPError as PiAPError
+except Exception:
+	try:
+		from piaplib.pku.remediation import PiAPError as PiAPError
+	except Exception:
+		raise ImportError("Error Importing PiAPError")
 
 try:
 	from ..pku import utils as utils
@@ -242,6 +249,46 @@ def unpackFromRest(ciphertext=None, keyStore=None):
 		raise NotImplementedError("No Implemented Backend - BUG")
 
 
+@remediation.error_handling
+def unpackFromFile(somefile, keyStore=None):
+	"""Reads the raw encrypted file and decrypts it."""
+	read_data = None
+	try:
+		someFilePath = utils.addExtension(somefile, str('enc'))
+		with utils.open_func(someFilePath, mode=u'r', encoding=u'utf-8') as enc_data_file:
+			read_enc_data = enc_data_file.read()
+			read_data = unpackFromRest(read_enc_data, keyStore)
+	except Exception as clearerr:
+		read_data = None
+		baton = PiAPError(clearerr, str("Failed to load or deycrypt file."))
+		clearerr = None
+		del clearerr
+		raise baton
+	return read_data
+
+
+@remediation.error_handling
+def packToFile(somefile, data, keyStore=None):
+	"""Writes the raw encrypted file."""
+	if data is None:
+		return False
+	if somefile is None:
+		return False
+	did_write = False
+	try:
+		someFilePath = utils.literal_code(utils.addExtension(str(somefile), str("enc")))
+		if someFilePath is not None:
+			encData = packForRest(data, keyStore)
+			with utils.open_func(file=someFilePath, mode=u'wb+') as enc_data_file:
+				utils.write_func(enc_data_file, utils.literal_str(encData).encode("utf-8"))
+			del(encData)
+		did_write = True
+	except Exception as clearerr:
+		raise remediation.PiAPError(clearerr, str("Failed to write or encrypt file."))
+		did_write = False
+	return did_write
+
+
 WEAK_ACTIONS = {u'pack': packForRest, u'unpack': unpackFromRest}
 """ The Pocket bag Unit actions.
 	pack - save/pack/pickle functions.
diff --git a/piaplib/pku/config.py b/piaplib/pku/config.py
index 4cf9ccb..886cf7f 100755
--- a/piaplib/pku/config.py
+++ b/piaplib/pku/config.py
@@ -45,27 +45,11 @@
 		raise ImportError("Error Importing remediation")
 
 
-def addExtension(somefile, extension):
-	"""Ensures the given extension is used."""
-	if (somefile is None):
-		return None
-	if (extension is None):
-		return somefile
-	if (len(str(somefile)) > len(extension)):
-		offset = (-1 * len(extension))
-		if (extension in str(somefile)[offset:]) and (str(".") in str(somefile)):
-			return somefile
-		else:
-			return str("{}.{}").format(somefile, extension)
-	else:
-		return str("{}.{}").format(somefile, extension)
-
-
 def hasJsonSupport():
 	support_json = False
 	try:
 		support_json = (json.__name__ is not None)
-	except:
+	except BaseException:
 		support_json = False
 	return support_json
 
@@ -75,7 +59,7 @@ def readJsonFile(somefile):
 	"""Reads the raw json file."""
 	read_data = None
 	try:
-		someFilePath = addExtension(somefile, str('json'))
+		someFilePath = utils.addExtension(somefile, str('json'))
 		with utils.open_func(someFilePath, mode=u'r', encoding=u'utf-8') as json_data_file:
 			read_data = json.load(fp=json_data_file, encoding=u'utf-8')
 	except Exception as jsonerr:
@@ -96,7 +80,7 @@ def writeJsonFile(somefile, data):
 		return False
 	did_write = False
 	try:
-		someFilePath = addExtension(somefile, str('json'))
+		someFilePath = utils.addExtension(somefile, str('json'))
 		with utils.open_func(someFilePath, mode=u'w+', encoding=u'utf-8') as outfile:
 			jsonData = json.dumps(
 				obj=dict(data),
@@ -133,7 +117,7 @@ def hasYamlSupport():
 	support_yaml = False
 	try:
 		support_yaml = (yaml.__name__ is not None)
-	except Exception:
+	except BaseException:
 		support_yaml = False
 	return support_yaml
 
@@ -144,7 +128,7 @@ def readYamlFile(somefile):
 		return None
 	read_data = None
 	try:
-		someFilePath = addExtension(somefile, str('yaml'))
+		someFilePath = utils.addExtension(somefile, str('yaml'))
 		with utils.open_func(file=someFilePath, mode=u'r', encoding=u'utf-8') as ymalfile:
 			if yaml.version_info < (0, 15):
 				read_data = yaml.safe_load(ymalfile)
@@ -168,7 +152,7 @@ def writeYamlFile(somefile, data):
 		return False
 	did_write = False
 	try:
-		someFilePath = addExtension(somefile, str('yaml'))
+		someFilePath = utils.addExtension(somefile, str('yaml'))
 		did_write = utils.writeFile(someFilePath, yaml.dump(data))
 	except Exception as yamlerr:
 		print("")
diff --git a/piaplib/pku/remediation.py b/piaplib/pku/remediation.py
index 7a338c9..c680257 100644
--- a/piaplib/pku/remediation.py
+++ b/piaplib/pku/remediation.py
@@ -105,6 +105,21 @@ def helper_func(*args, **kwargs):
 	return helper_func
 
 
+def error_breakpoint(error, context=None):
+	"""Just logs the error and returns None"""
+	timestamp = getTimeStamp()
+	logs.log(str("An error occured at {}").format(timestamp), "Error")
+	logs.log(str(context), "Debug")
+	logs.log(str(type(error)), "Error")
+	logs.log(str(error), "Error")
+	logs.log(str((error.args)), "Error")
+	if isinstance(error, PiAPError):
+		logs.log(str(error.cause), "Error")
+		logs.log(str(type(error.cause)), "Error")
+		logs.log(str((error.args)), "Error")
+	return None
+
+
 def error_handling(func):
 	"""Runs a function in try-except"""
 	import functools
@@ -116,21 +131,10 @@ def safety_func(*args, **kwargs):
 		try:
 			theOutput = func(*args, **kwargs)
 		except Exception as err:
-			timestamp = getTimeStamp()
-			logs.log(str("An error occured at {}").format(timestamp), "Error")
-			logs.log(str(func), "Debug")
-			logs.log(str(type(err)), "Error")
-			logs.log(str(err), "Error")
-			logs.log(str((err.args)), "Error")
-			if isinstance(err, PiAPError):
-				logs.log(str((err.cause)), "Error")
-				logs.log(str(type(err.cause)), "Error")
-				logs.log(str(type(err.args)), "Error")
-			logs.log(str(""), "Error")
+			theOutput = error_breakpoint(error=err, context=func)
 			# sys.exc_clear()
 			err = None
 			del err
-			theOutput = None
 		return theOutput
 
 	return safety_func
diff --git a/piaplib/pku/utils.py b/piaplib/pku/utils.py
index 57e30e1..54e289b 100644
--- a/piaplib/pku/utils.py
+++ b/piaplib/pku/utils.py
@@ -295,6 +295,23 @@ def xstr(some_str=None):
 """ I/O and Files """
 
 
+@remediation.error_passing
+def addExtension(somefile, extension):
+	"""Ensures the given extension is used."""
+	if (somefile is None):
+		return None
+	if (extension is None):
+		return somefile
+	if (len(str(somefile)) > len(extension)):
+		offset = (-1 * len(extension))
+		if (extension in str(somefile)[offset:]) and (str(".") in str(somefile)):
+			return somefile
+		else:
+			return str("{}.{}").format(somefile, extension)
+	else:
+		return str("{}.{}").format(somefile, extension)
+
+
 @remediation.error_passing
 def open_func(file, mode='r', buffering=-1, encoding=None):
 	""" cross-python open function """
@@ -313,7 +330,7 @@ def open_func(file, mode='r', buffering=-1, encoding=None):
 
 @remediation.error_passing
 def write_func(someFile, the_data=None):
-	""" cross-python open function """
+	""" cross-python write function """
 	try:
 		import six
 		if six.PY2:


Test patch:
diff --git a/tests/test_config.py b/tests/test_config.py
index 2f44b08..2c29351 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -83,135 +83,6 @@ def test_syntax(self):
 			theResult = False
 		assert theResult
 
-	def test_case_config_none_ext(self):
-		"""Tests the addExtension when input is None"""
-		theResult = True
-		try:
-			from .context import piaplib as piaplib
-			if piaplib.__name__ is None:
-				raise ImportError("Failed to import pku")
-			from piaplib import pocket as pocket
-			if pocket.__name__ is None:
-				raise ImportError("Failed to import utils")
-			from piaplib import pku as pku
-			if pku.__name__ is None:
-				raise ImportError("Failed to import pku")
-			from pku import config as config
-			if config.__name__ is None:
-				raise ImportError("Failed to import config")
-			self.assertIsNone(config.addExtension(None, None))
-		except Exception as err:
-			print(str(""))
-			print(str(type(err)))
-			print(str(err))
-			print(str((err.args)))
-			print(str(""))
-			err = None
-			del err
-			theResult = False
-		assert theResult
-
-	def test_case_config_file_with_none_ext(self):
-		"""Tests the addExtension when input is (test, None)"""
-		theResult = True
-		try:
-			from .context import piaplib as piaplib
-			if piaplib.__name__ is None:
-				raise ImportError("Failed to import pku")
-			from piaplib import pocket as pocket
-			if pocket.__name__ is None:
-				raise ImportError("Failed to import utils")
-			from piaplib import pku as pku
-			if pku.__name__ is None:
-				raise ImportError("Failed to import pku")
-			from pku import config as config
-			if config.__name__ is None:
-				raise ImportError("Failed to import config")
-			test = None
-			test_name = str("test_no_dot")
-			self.assertIsNone(test)
-			test = config.addExtension(test_name, None)
-			self.assertIsNotNone(test)
-			self.assertEqual(test, test_name)
-		except Exception as err:
-			print(str(""))
-			print(str(type(err)))
-			print(str(err))
-			print(str((err.args)))
-			print(str(""))
-			err = None
-			del err
-			theResult = False
-		assert theResult
-
-	def test_case_config_file_with_short_ext(self):
-		"""Tests the addExtension when input is (test, txt)"""
-		theResult = True
-		try:
-			from .context import piaplib as piaplib
-			if piaplib.__name__ is None:
-				raise ImportError("Failed to import pku")
-			from piaplib import pocket as pocket
-			if pocket.__name__ is None:
-				raise ImportError("Failed to import utils")
-			from piaplib import pku as pku
-			if pku.__name__ is None:
-				raise ImportError("Failed to import pku")
-			from pku import config as config
-			if config.__name__ is None:
-				raise ImportError("Failed to import config")
-			test = None
-			test_name = str("test_no_dot")
-			test_ext = str("txt")
-			self.assertIsNone(test)
-			test = config.addExtension(test_name, test_ext)
-			self.assertIsNotNone(test)
-			self.assertNotEqual(test, test_name)
-		except Exception as err:
-			print(str(""))
-			print(str(type(err)))
-			print(str(err))
-			print(str((err.args)))
-			print(str(""))
-			err = None
-			del err
-			theResult = False
-		assert theResult
-
-	def test_case_config_file_with_long_ext(self):
-		"""Tests the addExtension when input is (test, much_longer_extension)"""
-		theResult = True
-		try:
-			from .context import piaplib as piaplib
-			if piaplib.__name__ is None:
-				raise ImportError("Failed to import pku")
-			from piaplib import pocket as pocket
-			if pocket.__name__ is None:
-				raise ImportError("Failed to import utils")
-			from piaplib import pku as pku
-			if pku.__name__ is None:
-				raise ImportError("Failed to import pku")
-			from pku import config as config
-			if config.__name__ is None:
-				raise ImportError("Failed to import config")
-			test = None
-			test_name = str("test")
-			test_ext = str("much_longer_extension")
-			self.assertIsNone(test)
-			test = config.addExtension(test_name, test_ext)
-			self.assertIsNotNone(test)
-			self.assertNotEqual(test, test_name)
-		except Exception as err:
-			print(str(""))
-			print(str(type(err)))
-			print(str(err))
-			print(str((err.args)))
-			print(str(""))
-			err = None
-			del err
-			theResult = False
-		assert theResult
-
 	def test_case_config_supports_json(self):
 		"""Tests the config.hasJsonSupport() function"""
 		theResult = True
diff --git a/tests/test_enc.py b/tests/test_enc.py
index a61192b..3af4b43 100644
--- a/tests/test_enc.py
+++ b/tests/test_enc.py
@@ -38,7 +38,7 @@
 	raise ImportError("Failed to import test context")
 
 
-class BookTestSuite(unittest.TestCase):
+class CryptoTestSuite(unittest.TestCase):
 	"""Special Pocket keyring crypto test cases."""
 
 	def test_absolute_truth_and_meaning(self):
@@ -112,7 +112,7 @@ def test_z_case_clearify_setKeyFile(self):
 				raise ImportError("Failed to import clearify")
 			self.assertIsNotNone(clearify.makeKeystoreFile(
 				str("This is not a real key"),
-				str("../test.secret")
+				str("./test.secret")
 			))
 		except Exception as err:
 			print(str(""))
@@ -156,7 +156,7 @@ def test_z_case_clearify_setKeyFile_no_key(self):
 				raise ImportError("Failed to import clearify")
 			self.assertIsNotNone(clearify.makeKeystoreFile(
 				None,
-				str("../test.secret")
+				str("./test.secret")
 			))
 		except Exception as err:
 			print(str(""))
@@ -319,6 +319,64 @@ def test_case_clearify_main_b(self):
 				raise unittest.SkipTest("BETA. Experemental feature not ready yet.")
 		assert theResult
 
+	def test_case_clearify_read_write(self):
+		"""Tests the helper function pack to file of keyring.clearify and then unpack"""
+		theResult = False
+		try:
+			from piaplib.keyring import clearify as clearify
+			if clearify.__name__ is None:
+				raise ImportError("Failed to import clearify")
+			from piaplib.keyring import rand as rand
+			if rand.__name__ is None:
+				raise ImportError("Failed to import rand")
+			sometestfile = str("./the_test_file.enc")
+			theteststore = clearify.makeKeystoreFile(
+				str("testkeyneedstobelong"),
+				str("./.weak_test_key_{}").format(rand.randInt(1, 10, 99))
+			)
+			self.assertIsNotNone(theteststore)
+			if (theteststore is not None):
+				print(" ... Wrote key file ... ")
+			test_write = clearify.packToFile(
+				sometestfile,
+				str("This is a test Message"),
+				theteststore
+			)
+			if (test_write is True):
+				print(" ... Wrote enc file ... ")
+			self.assertTrue(test_write)
+			if (test_write is True):
+				test_read = clearify.unpackFromFile(sometestfile, theteststore)
+				try:
+					if isinstance(test_read, bytes):
+						test_read = test_read.decode('utf8')
+				except UnicodeDecodeError:
+					test_read = str(repr(bytes(test_read)))
+				self.assertIsNotNone(test_read)
+				if (str("This is a test Message") in str(test_read)):
+					theResult = True
+				else:
+					if sys.platform.startswith("linux"):
+						print(str(repr(bytes(test_read))))
+						theResult = False
+					else:
+						raise unittest.SkipTest("BETA. Experemental feature not ready yet.")
+			else:
+				theResult = False
+		except Exception as err:
+			print(str(""))
+			print(str(type(err)))
+			print(str(err))
+			print(str((err.args)))
+			print(str(""))
+			err = None
+			del err
+			if sys.platform.startswith("linux"):
+				theResult = False
+			else:
+				raise unittest.SkipTest("BETA. Experemental feature not ready yet.")
+		assert theResult
+
 
 if __name__ == u'__main__':
 	unittest.main()
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 461cb0a..13df45e 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -304,6 +304,135 @@ def test_case_utils_regex_tty_clients_output(self):
 			theResult = False
 		assert theResult
 
+	def test_case_utils_none_ext(self):
+		"""Tests the addExtension when input is None"""
+		theResult = True
+		try:
+			from .context import piaplib as piaplib
+			if piaplib.__name__ is None:
+				raise ImportError("Failed to import pku")
+			from piaplib import pocket as pocket
+			if pocket.__name__ is None:
+				raise ImportError("Failed to import utils")
+			from piaplib import pku as pku
+			if pku.__name__ is None:
+				raise ImportError("Failed to import pku")
+			from pku import utils as utils
+			if utils.__name__ is None:
+				raise ImportError("Failed to import utils")
+			self.assertIsNone(utils.addExtension(None, None))
+		except Exception as err:
+			print(str(""))
+			print(str(type(err)))
+			print(str(err))
+			print(str((err.args)))
+			print(str(""))
+			err = None
+			del err
+			theResult = False
+		assert theResult
+
+	def test_case_utils_file_with_none_ext(self):
+		"""Tests the addExtension when input is (test, None)"""
+		theResult = True
+		try:
+			from .context import piaplib as piaplib
+			if piaplib.__name__ is None:
+				raise ImportError("Failed to import pku")
+			from piaplib import pocket as pocket
+			if pocket.__name__ is None:
+				raise ImportError("Failed to import utils")
+			from piaplib import pku as pku
+			if pku.__name__ is None:
+				raise ImportError("Failed to import pku")
+			from pku import utils as utils
+			if utils.__name__ is None:
+				raise ImportError("Failed to import utils")
+			test = None
+			test_name = str("test_no_dot")
+			self.assertIsNone(test)
+			test = utils.addExtension(test_name, None)
+			self.assertIsNotNone(test)
+			self.assertEqual(test, test_name)
+		except Exception as err:
+			print(str(""))
+			print(str(type(err)))
+			print(str(err))
+			print(str((err.args)))
+			print(str(""))
+			err = None
+			del err
+			theResult = False
+		assert theResult
+
+	def test_case_utils_file_with_short_ext(self):
+		"""Tests the addExtension when input is (test, txt)"""
+		theResult = True
+		try:
+			from .context import piaplib as piaplib
+			if piaplib.__name__ is None:
+				raise ImportError("Failed to import pku")
+			from piaplib import pocket as pocket
+			if pocket.__name__ is None:
+				raise ImportError("Failed to import utils")
+			from piaplib import pku as pku
+			if pku.__name__ is None:
+				raise ImportError("Failed to import pku")
+			from pku import utils as utils
+			if utils.__name__ is None:
+				raise ImportError("Failed to import utils")
+			test = None
+			test_name = str("test_no_dot")
+			test_ext = str("txt")
+			self.assertIsNone(test)
+			test = utils.addExtension(test_name, test_ext)
+			self.assertIsNotNone(test)
+			self.assertNotEqual(test, test_name)
+		except Exception as err:
+			print(str(""))
+			print(str(type(err)))
+			print(str(err))
+			print(str((err.args)))
+			print(str(""))
+			err = None
+			del err
+			theResult = False
+		assert theResult
+
+	def test_case_utils_file_with_long_ext(self):
+		"""Tests the addExtension when input is (test, much_longer_extension)"""
+		theResult = True
+		try:
+			from .context import piaplib as piaplib
+			if piaplib.__name__ is None:
+				raise ImportError("Failed to import pku")
+			from piaplib import pocket as pocket
+			if pocket.__name__ is None:
+				raise ImportError("Failed to import utils")
+			from piaplib import pku as pku
+			if pku.__name__ is None:
+				raise ImportError("Failed to import pku")
+			from pku import utils as utils
+			if utils.__name__ is None:
+				raise ImportError("Failed to import utils")
+			test = None
+			test_name = str("test")
+			test_ext = str("much_longer_extension")
+			self.assertIsNone(test)
+			test = utils.addExtension(test_name, test_ext)
+			self.assertIsNotNone(test)
+			self.assertNotEqual(test, test_name)
+		except Exception as err:
+			print(str(""))
+			print(str(type(err)))
+			print(str(err))
+			print(str((err.args)))
+			print(str(""))
+			err = None
+			del err
+			theResult = False
+		assert theResult
+
 	def test_case_utils_read_write_file(self):
 		"""Tests the read and write functions"""
 		theResult = False