escrowai-encrypt 0.0.1__py3-none-any.whl

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.
File without changes
@@ -0,0 +1,249 @@
1
+ import os
2
+ import uuid
3
+ import yaml
4
+ import pathlib
5
+ from cryptography.hazmat.primitives import hashes
6
+ from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
7
+ from cryptography.hazmat.primitives.ciphers.aead import AESGCM
8
+ from cryptography.hazmat.primitives.serialization import load_pem_public_key
9
+ from cryptography.hazmat.primitives.asymmetric import padding
10
+ from cryptography.hazmat.backends import default_backend
11
+ from zipfile import ZipFile
12
+ from azure.storage.blob import ContainerClient
13
+ from escrowai_encrypt.utils import encrypt_data
14
+ import shutil
15
+
16
+
17
+ def generate_content_encryption_key(filename=""):
18
+ """
19
+ Generate a Content Encryption Key (CEK), the key used to encrypt an algorithm or dataset.
20
+ """
21
+
22
+ if filename == "":
23
+ filename = f"cek_{uuid.uuid4()}.key"
24
+
25
+ with open(filename, "wb") as file:
26
+ file.write(os.urandom(32))
27
+
28
+ print(f"Content Encryption Key (CEK) downloaded successfully to {filename}.")
29
+
30
+
31
+ def generate_wrapped_content_encryption_key(
32
+ content_encryption_key: str, key_encryption_key: str, filename=""
33
+ ):
34
+ """
35
+ Generate a Wrapped Content Encryption Key (WCEK), a Content Encryption Key (CEK) that has been encrypted
36
+ using a Key Encryption Key (KEK).
37
+ """
38
+
39
+ if filename == "":
40
+ filename = f"wcek_{uuid.uuid4()}.key.bkenc"
41
+
42
+ with open(content_encryption_key, "rb") as file:
43
+ cek = file.read()
44
+ with open(key_encryption_key, "rb") as file:
45
+ kek = file.read()
46
+
47
+ print(
48
+ f"Wrapping CEK {content_encryption_key} with KEK {key_encryption_key} to file {filename}..."
49
+ )
50
+
51
+ public_key = load_pem_public_key(kek, backend=default_backend())
52
+ encrypted = public_key.encrypt(
53
+ cek,
54
+ padding=padding.OAEP(
55
+ mgf=padding.MGF1(algorithm=hashes.SHA1()),
56
+ algorithm=hashes.SHA1(),
57
+ label=None,
58
+ ),
59
+ )
60
+
61
+ with open(filename, "wb") as file:
62
+ file.write(encrypted)
63
+
64
+ print(
65
+ f"Wrapped Content Encryption Key (WCEK) downloaded successfully to {filename}."
66
+ )
67
+
68
+
69
+ def encrypt_algorithm(
70
+ algorithm_directory: str, content_encryption_key: str, filename=""
71
+ ):
72
+ """
73
+ Encrypt an Algorithm. Algorithm encryption safeguards your algorithm during storage, transmission,
74
+ and execution. The algorithm is encrypted using a Content Encryption Key (CEK).
75
+ """
76
+
77
+ if filename == "":
78
+ filename = f"{algorithm_directory}_encrypted_{uuid.uuid4()}.zip"
79
+
80
+ with open(content_encryption_key, "rb") as file:
81
+ cek = file.read()
82
+
83
+ original_files = []
84
+ new_files = []
85
+ with open(f"{algorithm_directory}/secrets.yaml", "r") as f:
86
+ files = yaml.safe_load(f)
87
+
88
+ count = str(len(files["secretFiles"]))
89
+ n = 1
90
+
91
+ print(f"{count} secret(s) to be encrypted.")
92
+ for f in files["secretFiles"]:
93
+ print(f"Encrypting secret {f[1]} ({n}/{count})...")
94
+ newpaths = ["", ""]
95
+ newpaths[0] = f"{algorithm_directory}/{f[0]}"
96
+ newpaths[1] = f"{algorithm_directory}/{f[1]}"
97
+
98
+ salt = os.urandom(8)
99
+ pbkdf2_hash = PBKDF2HMAC(
100
+ algorithm=hashes.SHA256(),
101
+ salt=salt,
102
+ length=32 + 12,
103
+ iterations=10000,
104
+ backend=default_backend(),
105
+ )
106
+
107
+ derived_password = pbkdf2_hash.derive(cek)
108
+ key = derived_password[0:32]
109
+ iv = derived_password[32 : (32 + 12)]
110
+
111
+ with open(newpaths[1], "rb") as encrypt:
112
+ data = encrypt.read()
113
+
114
+ encrypted = AESGCM(key).encrypt(iv, data, None)
115
+ encrypted = b"Salted__" + salt + encrypted
116
+
117
+ with open(newpaths[0], "wb") as write:
118
+ write.write(encrypted)
119
+
120
+ original_files.append(f[1])
121
+ new_files.append(newpaths[0])
122
+
123
+ print(f"Secret {f[0]} encrypted ({n}/{count}).")
124
+
125
+ shutil.make_archive("temp", "zip", algorithm_directory)
126
+ for i in new_files:
127
+ pathlib.Path(i).unlink()
128
+
129
+ zip_in = ZipFile("temp.zip", "r")
130
+ zip_out = ZipFile(filename, "w")
131
+
132
+ for item in zip_in.infolist():
133
+ buffer = zip_in.read(item.filename)
134
+ if item.filename not in original_files:
135
+ zip_out.writestr(item, buffer)
136
+ zip_in.close()
137
+ zip_out.close()
138
+
139
+ pathlib.Path("temp.zip").unlink()
140
+
141
+ print(f"Algorithm successfully encrypted as {filename}.")
142
+
143
+
144
+ def encrypt_upload_dataset(
145
+ dataset_directory: str, content_encryption_key: str, dataset_sas_uri: str
146
+ ):
147
+ """
148
+ Encrypt and upload a Dataset to Azure Blob Storage. Dataset encryption safeguards your dataset during storage,
149
+ transmission, and execution. The dataset is encrypted using a Content Encryption Key (CEK) and uploaded using
150
+ a Shared Access Signature (SAS) URL.
151
+ """
152
+
153
+ with open(content_encryption_key, "rb") as file:
154
+ cek = file.read()
155
+
156
+ salt = os.urandom(8)
157
+ pbkdf2_hash = PBKDF2HMAC(
158
+ algorithm=hashes.SHA256(),
159
+ salt=salt,
160
+ length=32 + 12,
161
+ iterations=10000,
162
+ backend=default_backend(),
163
+ )
164
+
165
+ derived_password = pbkdf2_hash.derive(cek)
166
+ key = derived_password[0:32]
167
+ iv = derived_password[32 : (32 + 12)]
168
+
169
+ count = sum(
170
+ len([x for x in files if x[0] != "."])
171
+ for _, _, files in os.walk(dataset_directory)
172
+ )
173
+ n = 1
174
+
175
+ print(f"{count} files(s) to be encrypted and uploaded.")
176
+ for root, _, files in os.walk(dataset_directory):
177
+ for filename in files:
178
+ file_path = os.path.join(root, filename)
179
+ dirname = os.path.dirname(file_path)
180
+ n += encrypt_data(
181
+ filename,
182
+ salt,
183
+ key,
184
+ dataset_directory,
185
+ dirname,
186
+ iv,
187
+ dataset_sas_uri,
188
+ n,
189
+ count,
190
+ )
191
+
192
+ print(f"Dataset successfully encrypted and uploaded to SAS URL {dataset_sas_uri}.")
193
+
194
+
195
+ def encrypt_upload_dataset_from_blob(
196
+ dataset_sas_uri_unencrypted: str, content_encryption_key: str, dataset_sas_uri: str
197
+ ):
198
+ """
199
+ Encrypt and upload a Dataset to Azure Blob Storage. Dataset encryption safeguards your dataset during storage,
200
+ transmission, and execution. The dataset is encrypted using a Content Encryption Key (CEK) and uploaded using
201
+ a Shared Access Signature (SAS) URL.
202
+ """
203
+
204
+ with open(content_encryption_key, "rb") as file:
205
+ cek = file.read()
206
+
207
+ salt = os.urandom(8)
208
+ pbkdf2_hash = PBKDF2HMAC(
209
+ algorithm=hashes.SHA256(),
210
+ salt=salt,
211
+ length=32 + 12,
212
+ iterations=10000,
213
+ backend=default_backend(),
214
+ )
215
+
216
+ derived_password = pbkdf2_hash.derive(cek)
217
+ key = derived_password[0:32]
218
+ iv = derived_password[32 : (32 + 12)]
219
+
220
+ unencrypted_client = ContainerClient.from_container_url(dataset_sas_uri_unencrypted)
221
+ encrypted_client = ContainerClient.from_container_url(dataset_sas_uri)
222
+ blobs = unencrypted_client.list_blob_names()
223
+
224
+ count = 0
225
+ for blob in blobs:
226
+ count += 1
227
+
228
+ blobs = unencrypted_client.list_blob_names() # reset page
229
+
230
+ n = 1
231
+ print(f"{str(count)} blob(s) to be encrypted and uploaded.")
232
+ for blob in blobs:
233
+ unencrypted_client = ContainerClient.from_container_url(
234
+ dataset_sas_uri_unencrypted
235
+ )
236
+ encrypted_client = ContainerClient.from_container_url(dataset_sas_uri)
237
+ print(f"Beginning download of blob {blob} ({n}/{str(count)})...")
238
+ data = unencrypted_client.download_blob(blob).readall()
239
+ print(f"Encrypting blob {blob}...")
240
+ encrypted = AESGCM(key).encrypt(iv, data, None)
241
+ encrypted = b"Salted__" + salt + encrypted
242
+ print(f"Uploading blob {blob}...")
243
+ encrypted_client.upload_blob(blob + ".bkenc", encrypted, overwrite=True)
244
+ print(f"Blob {blob + '.bkenc'} uploaded ({n}/{str(count)}).")
245
+ n += 1
246
+
247
+ print(
248
+ f"Dataset {dataset_sas_uri_unencrypted} successfully encrypted and uploaded to SAS URL {dataset_sas_uri}."
249
+ )
File without changes
@@ -0,0 +1,39 @@
1
+ import pathlib
2
+ from azure.storage.blob import BlobClient
3
+ from cryptography.hazmat.primitives.ciphers.aead import AESGCM
4
+
5
+
6
+ def encrypt_data(file, salt, key, base_folder, folder, iv, url, n, count):
7
+ if file[0] == ".":
8
+ return 0
9
+ if file.endswith(".bkenc"):
10
+ raise Exception(f"Error: cannot encrypt file {file}.")
11
+
12
+ print(f"Encrypting file {file} ({n}/{count})...")
13
+
14
+ with open(folder + "/" + file, "rb") as encrypt:
15
+ data = encrypt.read()
16
+
17
+ encrypted = AESGCM(key).encrypt(iv, data, None)
18
+ encrypted = b"Salted__" + salt + encrypted
19
+
20
+ # write new encrypted file, delete old
21
+ with open(folder + "/" + file + ".bkenc", "wb") as write:
22
+ write.write(encrypted)
23
+
24
+ upload_to_blob(url, folder + "/" + file + ".bkenc", base_folder)
25
+
26
+ pathlib.Path(folder + "/" + file + ".bkenc").unlink()
27
+
28
+ print(f"Uploaded file {file + '.bkenc'} ({n}/{count}).")
29
+
30
+ return 1
31
+
32
+
33
+ def upload_to_blob(url, file, folder):
34
+ uri = url.partition("?")
35
+ new_uri = uri[0] + file.split(folder, 1)[1] + uri[1] + uri[2]
36
+ client = BlobClient.from_blob_url(new_uri)
37
+
38
+ with open(file, "rb") as upload:
39
+ client.upload_blob(upload, overwrite=True)
@@ -0,0 +1,29 @@
1
+ Metadata-Version: 2.2
2
+ Name: escrowai-encrypt
3
+ Version: 0.0.1
4
+ Summary: This package allows EscrowAI users to programmatically encrypt their artifacts and add encryption to their workflows.
5
+ Home-page: https://github.com/BeeKeeperAI/escrowai-encrypt
6
+ Author: BeeKeeperAI
7
+ Author-email: engineering@beekeeperai.com
8
+ Classifier: Development Status :: 2 - Pre-Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Requires-Python: >=3.6
14
+ Description-Content-Type: text/markdown
15
+ Requires-Dist: azure-storage-blob
16
+ Requires-Dist: cryptography
17
+ Requires-Dist: pyyaml
18
+ Dynamic: author
19
+ Dynamic: author-email
20
+ Dynamic: classifier
21
+ Dynamic: description
22
+ Dynamic: description-content-type
23
+ Dynamic: home-page
24
+ Dynamic: requires-dist
25
+ Dynamic: requires-python
26
+ Dynamic: summary
27
+
28
+ # escrowai-encrypt
29
+ A module for encryption of artifacts and keys to be uploaded to EscrowAI.
@@ -0,0 +1,9 @@
1
+ escrowai_encrypt/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ escrowai_encrypt/encryption.py,sha256=HGP2AH5wEchaRIGGwFNoV0zGJMDDjvyHH7L5t-DnRqo,7901
3
+ escrowai_encrypt/main.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ escrowai_encrypt/utils.py,sha256=JQeozbUkwoSEnHG4JWFqPsJXC17Kv4lhzFJog5Lj0gA,1185
5
+ escrowai_encrypt-0.0.1.dist-info/METADATA,sha256=ePf7jOzp-IGMiPX53q1GDcyFjQ8OXyiykDTU2lYe9_I,988
6
+ escrowai_encrypt-0.0.1.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
7
+ escrowai_encrypt-0.0.1.dist-info/entry_points.txt,sha256=mjB_P4wzCRMYNUOBCdP6rz8xEyuTVwU7qZM4F5VWKBE,55
8
+ escrowai_encrypt-0.0.1.dist-info/top_level.txt,sha256=R8QP9gXiLcbs1sVwwxPHtfEgMf5Ww0eqBhnUQkD318I,17
9
+ escrowai_encrypt-0.0.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (75.8.2)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ encrypt = escrowai_encrypt.main:main
@@ -0,0 +1 @@
1
+ escrowai_encrypt