p3lib 1.1.99__tar.gz → 1.1.101__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. {p3lib-1.1.99 → p3lib-1.1.101}/PKG-INFO +1 -1
  2. {p3lib-1.1.99 → p3lib-1.1.101}/setup.cfg +1 -1
  3. p3lib-1.1.101/src/p3lib/file_io.py +154 -0
  4. {p3lib-1.1.99 → p3lib-1.1.101}/src/p3lib/pconfig.py +4 -4
  5. {p3lib-1.1.99 → p3lib-1.1.101}/src/p3lib.egg-info/PKG-INFO +1 -1
  6. {p3lib-1.1.99 → p3lib-1.1.101}/src/p3lib.egg-info/SOURCES.txt +1 -0
  7. {p3lib-1.1.99 → p3lib-1.1.101}/LICENSE +0 -0
  8. {p3lib-1.1.99 → p3lib-1.1.101}/README.md +0 -0
  9. {p3lib-1.1.99 → p3lib-1.1.101}/pyproject.toml +0 -0
  10. {p3lib-1.1.99 → p3lib-1.1.101}/src/p3lib/__init__.py +0 -0
  11. {p3lib-1.1.99 → p3lib-1.1.101}/src/p3lib/ate.py +0 -0
  12. {p3lib-1.1.99 → p3lib-1.1.101}/src/p3lib/bokeh_auth.py +0 -0
  13. {p3lib-1.1.99 → p3lib-1.1.101}/src/p3lib/bokeh_gui.py +0 -0
  14. {p3lib-1.1.99 → p3lib-1.1.101}/src/p3lib/boot_manager.py +0 -0
  15. {p3lib-1.1.99 → p3lib-1.1.101}/src/p3lib/conduit.py +0 -0
  16. {p3lib-1.1.99 → p3lib-1.1.101}/src/p3lib/database_if.py +0 -0
  17. {p3lib-1.1.99 → p3lib-1.1.101}/src/p3lib/helper.py +0 -0
  18. {p3lib-1.1.99 → p3lib-1.1.101}/src/p3lib/json_networking.py +0 -0
  19. {p3lib-1.1.99 → p3lib-1.1.101}/src/p3lib/mqtt_rpc.py +0 -0
  20. {p3lib-1.1.99 → p3lib-1.1.101}/src/p3lib/netif.py +0 -0
  21. {p3lib-1.1.99 → p3lib-1.1.101}/src/p3lib/netplotly.py +0 -0
  22. {p3lib-1.1.99 → p3lib-1.1.101}/src/p3lib/ngt.py +0 -0
  23. {p3lib-1.1.99 → p3lib-1.1.101}/src/p3lib/ssh.py +0 -0
  24. {p3lib-1.1.99 → p3lib-1.1.101}/src/p3lib/table_plot.py +0 -0
  25. {p3lib-1.1.99 → p3lib-1.1.101}/src/p3lib/uio.py +0 -0
  26. {p3lib-1.1.99 → p3lib-1.1.101}/src/p3lib.egg-info/dependency_links.txt +0 -0
  27. {p3lib-1.1.99 → p3lib-1.1.101}/src/p3lib.egg-info/requires.txt +0 -0
  28. {p3lib-1.1.99 → p3lib-1.1.101}/src/p3lib.egg-info/top_level.txt +0 -0
  29. {p3lib-1.1.99 → p3lib-1.1.101}/tests/test_conduit.py +0 -0
  30. {p3lib-1.1.99 → p3lib-1.1.101}/tests/test_json_networking.py +0 -0
  31. {p3lib-1.1.99 → p3lib-1.1.101}/tests/test_netif.py +0 -0
  32. {p3lib-1.1.99 → p3lib-1.1.101}/tests/test_ssh.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: p3lib
3
- Version: 1.1.99
3
+ Version: 1.1.101
4
4
  Summary: A group of python modules for networking, plotting data, config storage, automating boot scripts, ssh access and user input output.
5
5
  Home-page: https://github.com/pjaos/p3lib
6
6
  Author: Paul Austen
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = p3lib
3
- version = 1.1.99
3
+ version = 1.1.101
4
4
  author = Paul Austen
5
5
  author_email = pausten.os@gmail.com
6
6
  description = A group of python modules for networking, plotting data, config storage, automating boot scripts, ssh access and user input output.
@@ -0,0 +1,154 @@
1
+ import json
2
+ import os
3
+ from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
4
+ from cryptography.hazmat.primitives.hashes import SHA256
5
+ from cryptography.hazmat.backends import default_backend
6
+ from cryptography.fernet import Fernet
7
+ from base64 import urlsafe_b64encode
8
+
9
+ class CryptFile(object):
10
+ """@brief Responsible for encrypting and decrypting data to/from files using a password."""
11
+
12
+ def __init__(self,
13
+ filename: str,
14
+ password: str,
15
+ add_enc_extension: bool = True,
16
+ dict_data: bool = True):
17
+ """@brief Constructor
18
+ @param filename The filename to save the data into.
19
+ @param password The password to used encrypt data to and load encrypted data from file.
20
+ @param add_enc_extension If True then the .enc extension is added to the filename
21
+ supplied.
22
+ @param dict_data If True the data is a python dictionary."""
23
+ self._filename = filename
24
+ self._password = password
25
+ self._add_enc_extension = add_enc_extension
26
+ self._dict_data = dict_data
27
+
28
+ if not self._filename:
29
+ raise Exception("No filename defined to save data to.")
30
+
31
+ if len(self._filename) < 1:
32
+ raise Exception("No filename defined. String length = 0.")
33
+
34
+ if not self._password:
35
+ raise Exception("No password defined to encrypt/decrypt data.")
36
+
37
+ if len(self._password) < 1:
38
+ raise Exception("No password defined. String length = 0.")
39
+
40
+ self._add_extension()
41
+
42
+ def save(self,
43
+ data):
44
+ """@brief Save the data to an encrypted file.
45
+ @param data The data to be encrypted.
46
+ """
47
+ encrypted_data = self._encrypt_data(data)
48
+ with open(self._filename, "wb") as file:
49
+ file.write(encrypted_data)
50
+
51
+ def load(self):
52
+ """@brief Load data from an encrypted file.
53
+ @return The decrypted data.
54
+ """
55
+ with open(self._filename, "rb") as file:
56
+ data_bytes = file.read()
57
+ return self._decrypt_data(data_bytes)
58
+
59
+ def _decrypt_data(self, encrypted_data):
60
+ # Extract the salt (first 16 bytes) from the encrypted data
61
+ salt = encrypted_data[:16]
62
+ encrypted_content = encrypted_data[16:]
63
+ key = self._derive_key_from_password(salt)
64
+ fernet = Fernet(key)
65
+ decrypted_data = fernet.decrypt(encrypted_content)
66
+ if self._dict_data:
67
+ # Convert bytes back to a dict
68
+ data = json.loads(decrypted_data.decode())
69
+
70
+ else:
71
+ data = decrypted_data
72
+
73
+ return data
74
+
75
+ def get_file(self):
76
+ """@return Get the name of the encrypted file."""
77
+ return self._filename
78
+
79
+ def _add_extension(self):
80
+ """@brief Add the enc extension to the filename if required."""
81
+ if self._add_enc_extension and self._filename and not self._filename.endswith('.enc') :
82
+ self._filename = self._filename + ".enc"
83
+
84
+ def _derive_key_from_password(self,
85
+ salt: bytes) -> bytes:
86
+ kdf = PBKDF2HMAC(
87
+ algorithm=SHA256(),
88
+ length=32,
89
+ salt=salt,
90
+ iterations=100_000,
91
+ backend=default_backend(),
92
+ )
93
+ return urlsafe_b64encode(kdf.derive(self._password.encode()))
94
+
95
+ def _encrypt_data(self,
96
+ data):
97
+ # Generate a random salt for key derivation
98
+ salt = os.urandom(16)
99
+ key = self._derive_key_from_password(salt)
100
+ fernet = Fernet(key)
101
+ # If we expect a dict
102
+ if self._dict_data:
103
+ data_bytes = json.dumps(data).encode() # Convert JSON to bytes
104
+
105
+ # else check we have bytes
106
+ elif isinstance(data, bytes):
107
+ data_bytes = data
108
+
109
+ else:
110
+ raise Exception("data to be stored is not a bytes instance.")
111
+
112
+ encrypted_data = fernet.encrypt(data_bytes)
113
+ return salt + encrypted_data # Store the salt with the encrypted data
114
+
115
+ # Example usage
116
+ if __name__ == "__main__":
117
+
118
+ password = input("Enter a password for encryption: ")
119
+
120
+ # JSON data to encrypt
121
+ json_data = {
122
+ "name": "Alice",
123
+ "age": 30,
124
+ "is_admin": True,
125
+ "preferences": {
126
+ "theme": "dark",
127
+ "language": "English"
128
+ }
129
+ }
130
+
131
+ filename = "afile.txt"
132
+
133
+ # Save and load a python dict
134
+ cjf = CryptFile(filename=filename,
135
+ password=password)
136
+ cjf.save(json_data)
137
+ print(f"Saved {cjf.get_file()}")
138
+
139
+ decrypted_data = cjf.load()
140
+ print(f"Decrypted data: {decrypted_data}")
141
+
142
+
143
+ # Save and load data bytes
144
+ data_bytes = "123".encode()
145
+ cjf = CryptFile(filename=filename,
146
+ password=password,
147
+ dict_data=False)
148
+ cjf.save(data_bytes)
149
+ print(f"Saved {cjf.get_file()}")
150
+
151
+ decrypted_data = cjf.load()
152
+ print("Decrypted data:")
153
+ for _byte in decrypted_data:
154
+ print(f"_byte={_byte}")
@@ -338,7 +338,7 @@ class ConfigManager(object):
338
338
  configPath = configPath.strip()
339
339
 
340
340
  return join( configPath, cfgFilename )
341
-
341
+
342
342
  def __init__(self, uio, cfgFilename, defaultConfig, addDotToFilename=True, encrypt=False, cfgPath=None):
343
343
  """@brief Constructor
344
344
  @param uio A UIO (User Input Output) instance. May be set to None if no user messages are required.
@@ -773,11 +773,11 @@ class DotConfigManager(ConfigManager):
773
773
 
774
774
  if not os.path.isdir(homePath):
775
775
  raise Exception(f"{homePath} HOME path does not exist.")
776
-
776
+
777
777
  # Create the ~/.config folder if it does not exist
778
778
  if not os.path.isdir(configFolder):
779
779
  # Create the ~/.config folder
780
- os.makedir(configFolder)
780
+ os.makedirs(configFolder)
781
781
 
782
782
  progName = sys.argv[0]
783
783
  if progName.endswith('.py'):
@@ -802,7 +802,7 @@ class DotConfigManager(ConfigManager):
802
802
  @param encrypt If True then data will be encrypted in the saved files.
803
803
  The encryption uses part of the the local SSH RSA private key.
804
804
  This is not secure but assuming the private key has not been compromised it's
805
- probably the best we can do.
805
+ probably the best we can do.
806
806
  !!! Therefore if encrypt is set True then the an ssh key must be present !!!
807
807
  ||| in the ~/.ssh folder named id_rsa. !!!"""
808
808
  super().__init__(uio, DotConfigManager.GetDefaultConfigFilename(), defaultConfig, encrypt=encrypt)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: p3lib
3
- Version: 1.1.99
3
+ Version: 1.1.101
4
4
  Summary: A group of python modules for networking, plotting data, config storage, automating boot scripts, ssh access and user input output.
5
5
  Home-page: https://github.com/pjaos/p3lib
6
6
  Author: Paul Austen
@@ -9,6 +9,7 @@ src/p3lib/bokeh_gui.py
9
9
  src/p3lib/boot_manager.py
10
10
  src/p3lib/conduit.py
11
11
  src/p3lib/database_if.py
12
+ src/p3lib/file_io.py
12
13
  src/p3lib/helper.py
13
14
  src/p3lib/json_networking.py
14
15
  src/p3lib/mqtt_rpc.py
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes