wolfronix-sdk 1.0.0__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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Wolfronix Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,347 @@
1
+ Metadata-Version: 2.4
2
+ Name: wolfronix-sdk
3
+ Version: 1.0.0
4
+ Summary: Official Wolfronix SDK for Python — Zero-knowledge encryption made simple
5
+ Author: Wolfronix Team
6
+ License: MIT
7
+ Project-URL: Homepage, https://wolfronix.com
8
+ Project-URL: Documentation, https://wolfronix.com/docs/sdk/python
9
+ Project-URL: Repository, https://github.com/wolfronix/sdk-python
10
+ Project-URL: Issues, https://github.com/wolfronix/sdk-python/issues
11
+ Keywords: wolfronix,encryption,security,zero-knowledge,aes-256,file-encryption,crypto,privacy
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Security :: Cryptography
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.9
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: httpx>=0.25.0
28
+ Requires-Dist: cryptography>=41.0.0
29
+ Provides-Extra: websocket
30
+ Requires-Dist: websockets>=12.0; extra == "websocket"
31
+ Provides-Extra: dev
32
+ Requires-Dist: pytest>=7.0; extra == "dev"
33
+ Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
34
+ Requires-Dist: respx>=0.20; extra == "dev"
35
+ Requires-Dist: websockets>=12.0; extra == "dev"
36
+ Dynamic: license-file
37
+
38
+ # Wolfronix SDK for Python
39
+
40
+ > Official Python SDK for [Wolfronix](https://wolfronix.com) — Zero-knowledge encryption made simple.
41
+
42
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9%2B-blue.svg)](https://www.python.org/downloads/)
43
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
44
+
45
+ ## Installation
46
+
47
+ ```bash
48
+ pip install wolfronix-sdk
49
+ ```
50
+
51
+ For WebSocket streaming support:
52
+
53
+ ```bash
54
+ pip install wolfronix-sdk[websocket]
55
+ ```
56
+
57
+ ## Quick Start
58
+
59
+ ```python
60
+ import asyncio
61
+ from wolfronix import Wolfronix, WolfronixConfig
62
+
63
+ async def main():
64
+ # Initialize client
65
+ wfx = Wolfronix(WolfronixConfig(
66
+ base_url="https://your-wolfronix-server:9443",
67
+ client_id="your_client_id",
68
+ wolfronix_key="your_wolfronix_key",
69
+ insecure=True, # For self-signed certs
70
+ ))
71
+
72
+ # Health check
73
+ healthy = await wfx.health_check()
74
+ print(f"Server healthy: {healthy}")
75
+
76
+ # Register a new user
77
+ result = await wfx.register("user@example.com", "secure_password")
78
+ print(f"Registered: {result.user_id}")
79
+
80
+ # Or login with existing credentials
81
+ result = await wfx.login("user@example.com", "secure_password")
82
+ print(f"Logged in: {result.user_id}")
83
+
84
+ # Encrypt a file
85
+ with open("document.pdf", "rb") as f:
86
+ enc = await wfx.encrypt(f.read(), filename="document.pdf")
87
+ print(f"Encrypted! File ID: {enc.file_id}")
88
+
89
+ # Decrypt a file
90
+ decrypted_bytes = await wfx.decrypt(enc.file_id)
91
+ with open("decrypted.pdf", "wb") as f:
92
+ f.write(decrypted_bytes)
93
+
94
+ # List files
95
+ files = await wfx.list_files()
96
+ for f in files.files:
97
+ print(f" {f.original_name} (ID: {f.file_id})")
98
+
99
+ asyncio.run(main())
100
+ ```
101
+
102
+ ## Features
103
+
104
+ ### Authentication (Zero-Knowledge)
105
+
106
+ ```python
107
+ # Register — generates RSA-2048 keys client-side, wraps private key with password
108
+ result = await wfx.register("user@example.com", "password123")
109
+
110
+ # Login — fetches wrapped key, unwraps client-side (server never sees raw private key)
111
+ result = await wfx.login("user@example.com", "password123")
112
+
113
+ # Direct token auth (for server-side apps)
114
+ wfx.set_token("jwt-token", "user-id")
115
+
116
+ # Logout (clears keys from memory)
117
+ wfx.logout()
118
+ ```
119
+
120
+ ### File Encryption (4-Layer Architecture)
121
+
122
+ ```python
123
+ # Encrypt
124
+ with open("secret.pdf", "rb") as f:
125
+ result = await wfx.encrypt(f.read(), filename="secret.pdf")
126
+ print(f"File ID: {result.file_id}, Time: {result.enc_time_ms}ms")
127
+
128
+ # Decrypt (zero-knowledge flow — private key never leaves client)
129
+ data = await wfx.decrypt(result.file_id)
130
+ with open("decrypted.pdf", "wb") as f:
131
+ f.write(data)
132
+
133
+ # List all files
134
+ files = await wfx.list_files()
135
+
136
+ # Delete a file
137
+ await wfx.delete_file(result.file_id)
138
+ ```
139
+
140
+ ### E2E Chat Encryption (RSA + AES Hybrid)
141
+
142
+ ```python
143
+ # Encrypt a message for a recipient
144
+ packet = await wfx.encrypt_message("Hello, Bob!", "bob@example.com")
145
+ # Send `packet` (JSON string) via your chat transport
146
+
147
+ # Decrypt a received message
148
+ plaintext = await wfx.decrypt_message(packet)
149
+ print(plaintext) # "Hello, Bob!"
150
+ ```
151
+
152
+ ### Server-Side Message Encryption (Dual-Key Split)
153
+
154
+ ```python
155
+ # Layer 4 (default) — server splits key, you get key_part_a
156
+ result = await wfx.server_encrypt("Sensitive message")
157
+
158
+ # Decrypt with your key_part_a
159
+ from wolfronix import ServerDecryptParams
160
+ text = await wfx.server_decrypt(ServerDecryptParams(
161
+ encrypted_message=result.encrypted_message,
162
+ nonce=result.nonce,
163
+ key_part_a=result.key_part_a,
164
+ message_tag=result.message_tag,
165
+ ))
166
+
167
+ # Batch encryption (up to 100 messages, single round-trip)
168
+ batch = await wfx.server_encrypt_batch([
169
+ {"id": "msg1", "message": "Hello"},
170
+ {"id": "msg2", "message": "World"},
171
+ ])
172
+
173
+ # Decrypt batch items
174
+ text1 = await wfx.server_decrypt_batch_item(batch, 0)
175
+ text2 = await wfx.server_decrypt_batch_item(batch, 1)
176
+ ```
177
+
178
+ ### WebSocket Streaming Encryption
179
+
180
+ > Requires `pip install wolfronix-sdk[websocket]`
181
+
182
+ ```python
183
+ # Encrypt stream
184
+ stream = await wfx.create_stream("encrypt")
185
+ enc1 = await stream.send("Chunk 1 data")
186
+ enc2 = await stream.send("Chunk 2 data")
187
+ summary = await stream.end()
188
+ print(f"Processed {summary['chunks_processed']} chunks")
189
+
190
+ # Save stream.key_part_a and stream.stream_tag for decryption
191
+
192
+ # Decrypt stream
193
+ dec_stream = await wfx.create_stream("decrypt", {
194
+ "key_part_a": stream.key_part_a,
195
+ "stream_tag": stream.stream_tag,
196
+ })
197
+ plain1 = await dec_stream.send(enc1)
198
+ plain2 = await dec_stream.send(enc2)
199
+ await dec_stream.end()
200
+ ```
201
+
202
+ ### Enterprise Admin Client
203
+
204
+ ```python
205
+ from wolfronix import WolfronixAdmin, WolfronixAdminConfig
206
+
207
+ admin = WolfronixAdmin(WolfronixAdminConfig(
208
+ base_url="https://wolfronix-server:9443",
209
+ admin_key="your-admin-api-key",
210
+ insecure=True,
211
+ ))
212
+
213
+ # Register a client with managed Supabase connector
214
+ result = await admin.register_client({
215
+ "client_id": "acme_corp",
216
+ "client_name": "Acme Corporation",
217
+ "db_type": "supabase",
218
+ "db_config": '{"supabase_url": "https://xxx.supabase.co", "supabase_service_key": "eyJ..."}',
219
+ })
220
+ print(f"Wolfronix key: {result.wolfronix_key}")
221
+
222
+ # Register with custom API
223
+ result = await admin.register_client({
224
+ "client_id": "my_app",
225
+ "client_name": "My Application",
226
+ "db_type": "custom_api",
227
+ "api_endpoint": "https://my-storage-api.com",
228
+ })
229
+
230
+ # List all clients
231
+ clients = await admin.list_clients()
232
+ for c in clients.clients:
233
+ print(f" {c.client_id} ({c.db_type}) — active: {c.is_active}")
234
+
235
+ # Get / update / deactivate
236
+ client = await admin.get_client("acme_corp")
237
+ await admin.update_client("acme_corp", {"db_config": '{"new": "config"}'})
238
+ await admin.deactivate_client("acme_corp")
239
+ ```
240
+
241
+ ### Metrics
242
+
243
+ ```python
244
+ metrics = await wfx.get_metrics()
245
+ print(f"Total encryptions: {metrics.total_encryptions}")
246
+ print(f"Total decryptions: {metrics.total_decryptions}")
247
+ ```
248
+
249
+ ## Crypto Utilities
250
+
251
+ You can use the low-level crypto functions directly:
252
+
253
+ ```python
254
+ from wolfronix.crypto import (
255
+ generate_key_pair,
256
+ export_key_to_pem,
257
+ import_key_from_pem,
258
+ wrap_private_key,
259
+ unwrap_private_key,
260
+ generate_session_key,
261
+ encrypt_data,
262
+ decrypt_data,
263
+ rsa_encrypt,
264
+ rsa_decrypt,
265
+ )
266
+
267
+ # Generate RSA-2048 key pair
268
+ keys = generate_key_pair()
269
+ pub_pem = export_key_to_pem(keys.public_key, "public")
270
+ priv_pem = export_key_to_pem(keys.private_key, "private")
271
+
272
+ # Wrap private key with password (PBKDF2 + AES-256-GCM)
273
+ wrapped = wrap_private_key(keys.private_key, "my_password")
274
+ # wrapped.encrypted_key (base64), wrapped.salt (hex)
275
+
276
+ # Unwrap private key
277
+ private_key = unwrap_private_key(wrapped.encrypted_key, "my_password", wrapped.salt)
278
+
279
+ # AES-256-GCM encryption
280
+ session_key = generate_session_key()
281
+ encrypted, iv = encrypt_data("Hello, World!", session_key)
282
+ plaintext = decrypt_data(encrypted, iv, session_key)
283
+
284
+ # RSA-OAEP encryption
285
+ ciphertext = rsa_encrypt(b"secret data", keys.public_key)
286
+ plaintext_bytes = rsa_decrypt(ciphertext, keys.private_key)
287
+ ```
288
+
289
+ ## Security Architecture
290
+
291
+ | Layer | Protection | Implementation |
292
+ |-------|-----------|----------------|
293
+ | Layer 1 | Fake data generation | Synthetic PAN, Aadhaar, SSN for dev/test |
294
+ | Layer 2 | RBAC masking | Role-based partial/full data masking |
295
+ | Layer 3 | AES-256-GCM encryption | Server-side symmetric encryption |
296
+ | Layer 4 | Dual-key RSA split | RSA-2048 OAEP — key split between client & server |
297
+
298
+ **Zero-Knowledge Design:** Your private key is never stored on or transmitted to the server. It's wrapped with your password client-side using PBKDF2 (100,000 iterations) + AES-256-GCM before upload.
299
+
300
+ ## Error Handling
301
+
302
+ ```python
303
+ from wolfronix.errors import (
304
+ WolfronixError,
305
+ AuthenticationError,
306
+ ValidationError,
307
+ NetworkError,
308
+ PermissionDeniedError,
309
+ )
310
+
311
+ try:
312
+ await wfx.login("user@example.com", "wrong_password")
313
+ except AuthenticationError as e:
314
+ print(f"Auth failed: {e}")
315
+ except NetworkError as e:
316
+ print(f"Network error: {e}")
317
+ except WolfronixError as e:
318
+ print(f"Error [{e.code}]: {e} (HTTP {e.status_code})")
319
+ ```
320
+
321
+ ## API Parity with JavaScript SDK
322
+
323
+ This Python SDK mirrors the [JavaScript/TypeScript SDK](../javascript/) 1:1:
324
+
325
+ | JavaScript | Python |
326
+ |-----------|--------|
327
+ | `new Wolfronix(config)` | `Wolfronix(WolfronixConfig(...))` |
328
+ | `wfx.register(email, pass)` | `await wfx.register(email, pass)` |
329
+ | `wfx.login(email, pass)` | `await wfx.login(email, pass)` |
330
+ | `wfx.encrypt(file, name)` | `await wfx.encrypt(data, filename=name)` |
331
+ | `wfx.decrypt(fileId)` | `await wfx.decrypt(file_id)` |
332
+ | `wfx.encryptMessage(text, id)` | `await wfx.encrypt_message(text, id)` |
333
+ | `wfx.serverEncrypt(msg)` | `await wfx.server_encrypt(msg)` |
334
+ | `wfx.createStream(dir)` | `await wfx.create_stream(dir)` |
335
+ | `new WolfronixAdmin(config)` | `WolfronixAdmin(WolfronixAdminConfig(...))` |
336
+ | `admin.registerClient(...)` | `await admin.register_client(...)` |
337
+
338
+ ## Requirements
339
+
340
+ - Python 3.9+
341
+ - `httpx` >= 0.25.0
342
+ - `cryptography` >= 41.0.0
343
+ - `websockets` >= 12.0 (optional, for streaming)
344
+
345
+ ## License
346
+
347
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,310 @@
1
+ # Wolfronix SDK for Python
2
+
3
+ > Official Python SDK for [Wolfronix](https://wolfronix.com) — Zero-knowledge encryption made simple.
4
+
5
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9%2B-blue.svg)](https://www.python.org/downloads/)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ pip install wolfronix-sdk
12
+ ```
13
+
14
+ For WebSocket streaming support:
15
+
16
+ ```bash
17
+ pip install wolfronix-sdk[websocket]
18
+ ```
19
+
20
+ ## Quick Start
21
+
22
+ ```python
23
+ import asyncio
24
+ from wolfronix import Wolfronix, WolfronixConfig
25
+
26
+ async def main():
27
+ # Initialize client
28
+ wfx = Wolfronix(WolfronixConfig(
29
+ base_url="https://your-wolfronix-server:9443",
30
+ client_id="your_client_id",
31
+ wolfronix_key="your_wolfronix_key",
32
+ insecure=True, # For self-signed certs
33
+ ))
34
+
35
+ # Health check
36
+ healthy = await wfx.health_check()
37
+ print(f"Server healthy: {healthy}")
38
+
39
+ # Register a new user
40
+ result = await wfx.register("user@example.com", "secure_password")
41
+ print(f"Registered: {result.user_id}")
42
+
43
+ # Or login with existing credentials
44
+ result = await wfx.login("user@example.com", "secure_password")
45
+ print(f"Logged in: {result.user_id}")
46
+
47
+ # Encrypt a file
48
+ with open("document.pdf", "rb") as f:
49
+ enc = await wfx.encrypt(f.read(), filename="document.pdf")
50
+ print(f"Encrypted! File ID: {enc.file_id}")
51
+
52
+ # Decrypt a file
53
+ decrypted_bytes = await wfx.decrypt(enc.file_id)
54
+ with open("decrypted.pdf", "wb") as f:
55
+ f.write(decrypted_bytes)
56
+
57
+ # List files
58
+ files = await wfx.list_files()
59
+ for f in files.files:
60
+ print(f" {f.original_name} (ID: {f.file_id})")
61
+
62
+ asyncio.run(main())
63
+ ```
64
+
65
+ ## Features
66
+
67
+ ### Authentication (Zero-Knowledge)
68
+
69
+ ```python
70
+ # Register — generates RSA-2048 keys client-side, wraps private key with password
71
+ result = await wfx.register("user@example.com", "password123")
72
+
73
+ # Login — fetches wrapped key, unwraps client-side (server never sees raw private key)
74
+ result = await wfx.login("user@example.com", "password123")
75
+
76
+ # Direct token auth (for server-side apps)
77
+ wfx.set_token("jwt-token", "user-id")
78
+
79
+ # Logout (clears keys from memory)
80
+ wfx.logout()
81
+ ```
82
+
83
+ ### File Encryption (4-Layer Architecture)
84
+
85
+ ```python
86
+ # Encrypt
87
+ with open("secret.pdf", "rb") as f:
88
+ result = await wfx.encrypt(f.read(), filename="secret.pdf")
89
+ print(f"File ID: {result.file_id}, Time: {result.enc_time_ms}ms")
90
+
91
+ # Decrypt (zero-knowledge flow — private key never leaves client)
92
+ data = await wfx.decrypt(result.file_id)
93
+ with open("decrypted.pdf", "wb") as f:
94
+ f.write(data)
95
+
96
+ # List all files
97
+ files = await wfx.list_files()
98
+
99
+ # Delete a file
100
+ await wfx.delete_file(result.file_id)
101
+ ```
102
+
103
+ ### E2E Chat Encryption (RSA + AES Hybrid)
104
+
105
+ ```python
106
+ # Encrypt a message for a recipient
107
+ packet = await wfx.encrypt_message("Hello, Bob!", "bob@example.com")
108
+ # Send `packet` (JSON string) via your chat transport
109
+
110
+ # Decrypt a received message
111
+ plaintext = await wfx.decrypt_message(packet)
112
+ print(plaintext) # "Hello, Bob!"
113
+ ```
114
+
115
+ ### Server-Side Message Encryption (Dual-Key Split)
116
+
117
+ ```python
118
+ # Layer 4 (default) — server splits key, you get key_part_a
119
+ result = await wfx.server_encrypt("Sensitive message")
120
+
121
+ # Decrypt with your key_part_a
122
+ from wolfronix import ServerDecryptParams
123
+ text = await wfx.server_decrypt(ServerDecryptParams(
124
+ encrypted_message=result.encrypted_message,
125
+ nonce=result.nonce,
126
+ key_part_a=result.key_part_a,
127
+ message_tag=result.message_tag,
128
+ ))
129
+
130
+ # Batch encryption (up to 100 messages, single round-trip)
131
+ batch = await wfx.server_encrypt_batch([
132
+ {"id": "msg1", "message": "Hello"},
133
+ {"id": "msg2", "message": "World"},
134
+ ])
135
+
136
+ # Decrypt batch items
137
+ text1 = await wfx.server_decrypt_batch_item(batch, 0)
138
+ text2 = await wfx.server_decrypt_batch_item(batch, 1)
139
+ ```
140
+
141
+ ### WebSocket Streaming Encryption
142
+
143
+ > Requires `pip install wolfronix-sdk[websocket]`
144
+
145
+ ```python
146
+ # Encrypt stream
147
+ stream = await wfx.create_stream("encrypt")
148
+ enc1 = await stream.send("Chunk 1 data")
149
+ enc2 = await stream.send("Chunk 2 data")
150
+ summary = await stream.end()
151
+ print(f"Processed {summary['chunks_processed']} chunks")
152
+
153
+ # Save stream.key_part_a and stream.stream_tag for decryption
154
+
155
+ # Decrypt stream
156
+ dec_stream = await wfx.create_stream("decrypt", {
157
+ "key_part_a": stream.key_part_a,
158
+ "stream_tag": stream.stream_tag,
159
+ })
160
+ plain1 = await dec_stream.send(enc1)
161
+ plain2 = await dec_stream.send(enc2)
162
+ await dec_stream.end()
163
+ ```
164
+
165
+ ### Enterprise Admin Client
166
+
167
+ ```python
168
+ from wolfronix import WolfronixAdmin, WolfronixAdminConfig
169
+
170
+ admin = WolfronixAdmin(WolfronixAdminConfig(
171
+ base_url="https://wolfronix-server:9443",
172
+ admin_key="your-admin-api-key",
173
+ insecure=True,
174
+ ))
175
+
176
+ # Register a client with managed Supabase connector
177
+ result = await admin.register_client({
178
+ "client_id": "acme_corp",
179
+ "client_name": "Acme Corporation",
180
+ "db_type": "supabase",
181
+ "db_config": '{"supabase_url": "https://xxx.supabase.co", "supabase_service_key": "eyJ..."}',
182
+ })
183
+ print(f"Wolfronix key: {result.wolfronix_key}")
184
+
185
+ # Register with custom API
186
+ result = await admin.register_client({
187
+ "client_id": "my_app",
188
+ "client_name": "My Application",
189
+ "db_type": "custom_api",
190
+ "api_endpoint": "https://my-storage-api.com",
191
+ })
192
+
193
+ # List all clients
194
+ clients = await admin.list_clients()
195
+ for c in clients.clients:
196
+ print(f" {c.client_id} ({c.db_type}) — active: {c.is_active}")
197
+
198
+ # Get / update / deactivate
199
+ client = await admin.get_client("acme_corp")
200
+ await admin.update_client("acme_corp", {"db_config": '{"new": "config"}'})
201
+ await admin.deactivate_client("acme_corp")
202
+ ```
203
+
204
+ ### Metrics
205
+
206
+ ```python
207
+ metrics = await wfx.get_metrics()
208
+ print(f"Total encryptions: {metrics.total_encryptions}")
209
+ print(f"Total decryptions: {metrics.total_decryptions}")
210
+ ```
211
+
212
+ ## Crypto Utilities
213
+
214
+ You can use the low-level crypto functions directly:
215
+
216
+ ```python
217
+ from wolfronix.crypto import (
218
+ generate_key_pair,
219
+ export_key_to_pem,
220
+ import_key_from_pem,
221
+ wrap_private_key,
222
+ unwrap_private_key,
223
+ generate_session_key,
224
+ encrypt_data,
225
+ decrypt_data,
226
+ rsa_encrypt,
227
+ rsa_decrypt,
228
+ )
229
+
230
+ # Generate RSA-2048 key pair
231
+ keys = generate_key_pair()
232
+ pub_pem = export_key_to_pem(keys.public_key, "public")
233
+ priv_pem = export_key_to_pem(keys.private_key, "private")
234
+
235
+ # Wrap private key with password (PBKDF2 + AES-256-GCM)
236
+ wrapped = wrap_private_key(keys.private_key, "my_password")
237
+ # wrapped.encrypted_key (base64), wrapped.salt (hex)
238
+
239
+ # Unwrap private key
240
+ private_key = unwrap_private_key(wrapped.encrypted_key, "my_password", wrapped.salt)
241
+
242
+ # AES-256-GCM encryption
243
+ session_key = generate_session_key()
244
+ encrypted, iv = encrypt_data("Hello, World!", session_key)
245
+ plaintext = decrypt_data(encrypted, iv, session_key)
246
+
247
+ # RSA-OAEP encryption
248
+ ciphertext = rsa_encrypt(b"secret data", keys.public_key)
249
+ plaintext_bytes = rsa_decrypt(ciphertext, keys.private_key)
250
+ ```
251
+
252
+ ## Security Architecture
253
+
254
+ | Layer | Protection | Implementation |
255
+ |-------|-----------|----------------|
256
+ | Layer 1 | Fake data generation | Synthetic PAN, Aadhaar, SSN for dev/test |
257
+ | Layer 2 | RBAC masking | Role-based partial/full data masking |
258
+ | Layer 3 | AES-256-GCM encryption | Server-side symmetric encryption |
259
+ | Layer 4 | Dual-key RSA split | RSA-2048 OAEP — key split between client & server |
260
+
261
+ **Zero-Knowledge Design:** Your private key is never stored on or transmitted to the server. It's wrapped with your password client-side using PBKDF2 (100,000 iterations) + AES-256-GCM before upload.
262
+
263
+ ## Error Handling
264
+
265
+ ```python
266
+ from wolfronix.errors import (
267
+ WolfronixError,
268
+ AuthenticationError,
269
+ ValidationError,
270
+ NetworkError,
271
+ PermissionDeniedError,
272
+ )
273
+
274
+ try:
275
+ await wfx.login("user@example.com", "wrong_password")
276
+ except AuthenticationError as e:
277
+ print(f"Auth failed: {e}")
278
+ except NetworkError as e:
279
+ print(f"Network error: {e}")
280
+ except WolfronixError as e:
281
+ print(f"Error [{e.code}]: {e} (HTTP {e.status_code})")
282
+ ```
283
+
284
+ ## API Parity with JavaScript SDK
285
+
286
+ This Python SDK mirrors the [JavaScript/TypeScript SDK](../javascript/) 1:1:
287
+
288
+ | JavaScript | Python |
289
+ |-----------|--------|
290
+ | `new Wolfronix(config)` | `Wolfronix(WolfronixConfig(...))` |
291
+ | `wfx.register(email, pass)` | `await wfx.register(email, pass)` |
292
+ | `wfx.login(email, pass)` | `await wfx.login(email, pass)` |
293
+ | `wfx.encrypt(file, name)` | `await wfx.encrypt(data, filename=name)` |
294
+ | `wfx.decrypt(fileId)` | `await wfx.decrypt(file_id)` |
295
+ | `wfx.encryptMessage(text, id)` | `await wfx.encrypt_message(text, id)` |
296
+ | `wfx.serverEncrypt(msg)` | `await wfx.server_encrypt(msg)` |
297
+ | `wfx.createStream(dir)` | `await wfx.create_stream(dir)` |
298
+ | `new WolfronixAdmin(config)` | `WolfronixAdmin(WolfronixAdminConfig(...))` |
299
+ | `admin.registerClient(...)` | `await admin.register_client(...)` |
300
+
301
+ ## Requirements
302
+
303
+ - Python 3.9+
304
+ - `httpx` >= 0.25.0
305
+ - `cryptography` >= 41.0.0
306
+ - `websockets` >= 12.0 (optional, for streaming)
307
+
308
+ ## License
309
+
310
+ MIT — see [LICENSE](LICENSE).