filanti 1.0.0__py3-none-any.whl → 1.1.0__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.
- filanti/__init__.py +1 -1
- filanti/api/sdk.py +115 -14
- filanti/cli/main.py +426 -73
- filanti/core/file_manager.py +83 -0
- filanti/core/secrets.py +183 -33
- filanti/crypto/asymmetric.py +195 -10
- filanti/crypto/decryption.py +0 -1
- filanti/crypto/encryption.py +210 -4
- filanti/integrity/mac.py +64 -8
- {filanti-1.0.0.dist-info → filanti-1.1.0.dist-info}/METADATA +161 -51
- {filanti-1.0.0.dist-info → filanti-1.1.0.dist-info}/RECORD +14 -14
- {filanti-1.0.0.dist-info → filanti-1.1.0.dist-info}/WHEEL +1 -1
- {filanti-1.0.0.dist-info → filanti-1.1.0.dist-info}/entry_points.txt +0 -0
- {filanti-1.0.0.dist-info → filanti-1.1.0.dist-info}/licenses/LICENSE +0 -0
filanti/__init__.py
CHANGED
filanti/api/sdk.py
CHANGED
|
@@ -145,6 +145,9 @@ from filanti.core.secrets import (
|
|
|
145
145
|
resolve_secret,
|
|
146
146
|
resolve_secret_optional,
|
|
147
147
|
is_env_reference,
|
|
148
|
+
get_env_var_name,
|
|
149
|
+
load_dotenv,
|
|
150
|
+
get_supported_patterns,
|
|
148
151
|
redact_secret,
|
|
149
152
|
redact_secrets,
|
|
150
153
|
create_safe_json_output,
|
|
@@ -215,6 +218,36 @@ class Filanti:
|
|
|
215
218
|
use the underlying modules directly.
|
|
216
219
|
"""
|
|
217
220
|
|
|
221
|
+
# =========================================================================
|
|
222
|
+
# SECRETS & ENVIRONMENT
|
|
223
|
+
# =========================================================================
|
|
224
|
+
|
|
225
|
+
@staticmethod
|
|
226
|
+
def load_dotenv(
|
|
227
|
+
path: str | Path = ".env",
|
|
228
|
+
override: bool = False,
|
|
229
|
+
) -> dict[str, str]:
|
|
230
|
+
"""Load environment variables from a .env file.
|
|
231
|
+
|
|
232
|
+
Loads variables from the specified .env file into the environment.
|
|
233
|
+
This is useful for loading secrets before encryption/decryption.
|
|
234
|
+
|
|
235
|
+
Args:
|
|
236
|
+
path: Path to .env file (default: ".env" in current directory).
|
|
237
|
+
override: If True, override existing environment variables.
|
|
238
|
+
|
|
239
|
+
Returns:
|
|
240
|
+
Dictionary of loaded variables (name -> value).
|
|
241
|
+
|
|
242
|
+
Example:
|
|
243
|
+
# Load secrets from .env
|
|
244
|
+
Filanti.load_dotenv(".env")
|
|
245
|
+
|
|
246
|
+
# Now use ENV references
|
|
247
|
+
Filanti.encrypt("file.txt", password="ENV:MY_PASSWORD")
|
|
248
|
+
"""
|
|
249
|
+
return load_dotenv(path, override=override)
|
|
250
|
+
|
|
218
251
|
# =========================================================================
|
|
219
252
|
# HASHING
|
|
220
253
|
# =========================================================================
|
|
@@ -308,20 +341,30 @@ class Filanti:
|
|
|
308
341
|
key: bytes | None = None,
|
|
309
342
|
output: str | Path | None = None,
|
|
310
343
|
algorithm: str = "aes-256-gcm",
|
|
344
|
+
remove_source: bool = False,
|
|
345
|
+
secure_delete: bool = True,
|
|
346
|
+
dotenv_path: str | Path | None = None,
|
|
311
347
|
) -> EncryptResult:
|
|
312
348
|
"""Encrypt a file.
|
|
313
349
|
|
|
314
350
|
Provide either password OR key, not both.
|
|
315
351
|
|
|
316
|
-
Supports
|
|
352
|
+
Supports multiple secret reference formats:
|
|
317
353
|
Filanti.encrypt("file.txt", password="ENV:MY_PASSWORD")
|
|
354
|
+
Filanti.encrypt("file.txt", password="$env:MY_PASSWORD") # PowerShell
|
|
355
|
+
Filanti.encrypt("file.txt", password="${MY_PASSWORD}") # Shell-style
|
|
356
|
+
Filanti.encrypt("file.txt", password="env.MY_PASSWORD") # Dot notation
|
|
318
357
|
|
|
319
358
|
Args:
|
|
320
359
|
path: Path to file to encrypt.
|
|
321
|
-
password: Password for key derivation. Supports ENV
|
|
360
|
+
password: Password for key derivation. Supports ENV reference syntax.
|
|
322
361
|
key: Raw encryption key (32 bytes for AES-256).
|
|
323
362
|
output: Output path (default: path + .enc).
|
|
324
363
|
algorithm: Encryption algorithm.
|
|
364
|
+
remove_source: If True, delete original file after successful encryption.
|
|
365
|
+
secure_delete: If True and remove_source is True, securely overwrite
|
|
366
|
+
the original file before deletion.
|
|
367
|
+
dotenv_path: Optional path to .env file to load secrets from.
|
|
325
368
|
|
|
326
369
|
Returns:
|
|
327
370
|
EncryptResult with output path and metadata.
|
|
@@ -335,15 +378,23 @@ class Filanti:
|
|
|
335
378
|
|
|
336
379
|
if password:
|
|
337
380
|
# Resolve password from ENV if needed
|
|
338
|
-
resolved_password = resolve_secret(password)
|
|
339
|
-
metadata = encrypt_file_with_password(
|
|
381
|
+
resolved_password = resolve_secret(password, dotenv_path=dotenv_path)
|
|
382
|
+
metadata = encrypt_file_with_password(
|
|
383
|
+
path, out_path, resolved_password, alg,
|
|
384
|
+
remove_source=remove_source,
|
|
385
|
+
secure_delete=secure_delete,
|
|
386
|
+
)
|
|
340
387
|
return EncryptResult(
|
|
341
388
|
output_path=out_path,
|
|
342
389
|
algorithm=metadata.algorithm,
|
|
343
390
|
kdf_algorithm=metadata.kdf_algorithm,
|
|
344
391
|
)
|
|
345
392
|
elif key:
|
|
346
|
-
encrypt_file(
|
|
393
|
+
encrypt_file(
|
|
394
|
+
path, out_path, key, alg,
|
|
395
|
+
remove_source=remove_source,
|
|
396
|
+
secure_delete=secure_delete,
|
|
397
|
+
)
|
|
347
398
|
return EncryptResult(output_path=out_path, algorithm=algorithm)
|
|
348
399
|
else:
|
|
349
400
|
raise ValueError("Must provide either password or key")
|
|
@@ -354,19 +405,29 @@ class Filanti:
|
|
|
354
405
|
password: str | None = None,
|
|
355
406
|
key: bytes | None = None,
|
|
356
407
|
output: str | Path | None = None,
|
|
408
|
+
dotenv_path: str | Path | None = None,
|
|
409
|
+
remove_source: bool = False,
|
|
410
|
+
secure_delete: bool = True,
|
|
357
411
|
) -> DecryptResult:
|
|
358
412
|
"""Decrypt a file.
|
|
359
413
|
|
|
360
414
|
Provide either password OR key, not both.
|
|
361
415
|
|
|
362
|
-
Supports
|
|
416
|
+
Supports multiple secret reference formats:
|
|
363
417
|
Filanti.decrypt("file.enc", password="ENV:MY_PASSWORD")
|
|
418
|
+
Filanti.decrypt("file.enc", password="$env:MY_PASSWORD") # PowerShell
|
|
419
|
+
Filanti.decrypt("file.enc", password="${MY_PASSWORD}") # Shell-style
|
|
420
|
+
Filanti.decrypt("file.enc", password="env.MY_PASSWORD") # Dot notation
|
|
364
421
|
|
|
365
422
|
Args:
|
|
366
423
|
path: Path to encrypted file.
|
|
367
|
-
password: Password used for encryption. Supports ENV
|
|
424
|
+
password: Password used for encryption. Supports ENV reference syntax.
|
|
368
425
|
key: Raw encryption key.
|
|
369
426
|
output: Output path (default: removes .enc extension).
|
|
427
|
+
dotenv_path: Optional path to .env file to load secrets from.
|
|
428
|
+
remove_source: If True, delete encrypted file after successful decryption.
|
|
429
|
+
secure_delete: If True and remove_source is True, securely overwrite
|
|
430
|
+
the encrypted file before deletion.
|
|
370
431
|
|
|
371
432
|
Returns:
|
|
372
433
|
DecryptResult with output path and size.
|
|
@@ -384,13 +445,22 @@ class Filanti:
|
|
|
384
445
|
|
|
385
446
|
if password:
|
|
386
447
|
# Resolve password from ENV if needed
|
|
387
|
-
resolved_password = resolve_secret(password)
|
|
448
|
+
resolved_password = resolve_secret(password, dotenv_path=dotenv_path)
|
|
388
449
|
size = decrypt_file_with_password(path, out_path, resolved_password)
|
|
389
450
|
elif key:
|
|
390
451
|
size = decrypt_file(path, out_path, key)
|
|
391
452
|
else:
|
|
392
453
|
raise ValueError("Must provide either password or key")
|
|
393
454
|
|
|
455
|
+
# Remove encrypted source file if requested
|
|
456
|
+
if remove_source:
|
|
457
|
+
from filanti.core.file_manager import get_file_manager
|
|
458
|
+
fm = get_file_manager()
|
|
459
|
+
if secure_delete:
|
|
460
|
+
fm.secure_delete(path)
|
|
461
|
+
else:
|
|
462
|
+
fm.delete(path)
|
|
463
|
+
|
|
394
464
|
return DecryptResult(output_path=out_path, size=size)
|
|
395
465
|
|
|
396
466
|
@staticmethod
|
|
@@ -399,17 +469,22 @@ class Filanti:
|
|
|
399
469
|
password: str | None = None,
|
|
400
470
|
key: bytes | None = None,
|
|
401
471
|
algorithm: str = "aes-256-gcm",
|
|
472
|
+
dotenv_path: str | Path | None = None,
|
|
402
473
|
) -> bytes:
|
|
403
474
|
"""Encrypt bytes data.
|
|
404
475
|
|
|
405
|
-
Supports
|
|
476
|
+
Supports multiple secret reference formats:
|
|
406
477
|
Filanti.encrypt_bytes(data, password="ENV:MY_PASSWORD")
|
|
478
|
+
Filanti.encrypt_bytes(data, password="$env:MY_PASSWORD") # PowerShell
|
|
479
|
+
Filanti.encrypt_bytes(data, password="${MY_PASSWORD}") # Shell-style
|
|
480
|
+
Filanti.encrypt_bytes(data, password="env.MY_PASSWORD") # Dot notation
|
|
407
481
|
|
|
408
482
|
Args:
|
|
409
483
|
data: Data to encrypt.
|
|
410
|
-
password: Password for key derivation. Supports ENV
|
|
484
|
+
password: Password for key derivation. Supports ENV reference syntax.
|
|
411
485
|
key: Raw encryption key.
|
|
412
486
|
algorithm: Encryption algorithm.
|
|
487
|
+
dotenv_path: Optional path to .env file to load secrets from.
|
|
413
488
|
|
|
414
489
|
Returns:
|
|
415
490
|
Encrypted bytes (includes nonce and auth tag).
|
|
@@ -421,7 +496,7 @@ class Filanti:
|
|
|
421
496
|
|
|
422
497
|
if password is not None:
|
|
423
498
|
# Resolve password from ENV if needed
|
|
424
|
-
resolved_password = resolve_secret(password)
|
|
499
|
+
resolved_password = resolve_secret(password, dotenv_path=dotenv_path)
|
|
425
500
|
result = _encrypt_bytes_with_password(data, resolved_password, alg)
|
|
426
501
|
return result.to_bytes()
|
|
427
502
|
elif key is not None:
|
|
@@ -436,16 +511,21 @@ class Filanti:
|
|
|
436
511
|
data: bytes,
|
|
437
512
|
password: str | None = None,
|
|
438
513
|
key: bytes | None = None,
|
|
514
|
+
dotenv_path: str | Path | None = None,
|
|
439
515
|
) -> bytes:
|
|
440
516
|
"""Decrypt bytes data.
|
|
441
517
|
|
|
442
|
-
Supports
|
|
518
|
+
Supports multiple secret reference formats:
|
|
443
519
|
Filanti.decrypt_bytes(data, password="ENV:MY_PASSWORD")
|
|
520
|
+
Filanti.decrypt_bytes(data, password="$env:MY_PASSWORD") # PowerShell
|
|
521
|
+
Filanti.decrypt_bytes(data, password="${MY_PASSWORD}") # Shell-style
|
|
522
|
+
Filanti.decrypt_bytes(data, password="env.MY_PASSWORD") # Dot notation
|
|
444
523
|
|
|
445
524
|
Args:
|
|
446
525
|
data: Encrypted data.
|
|
447
|
-
password: Password used for encryption. Supports ENV
|
|
526
|
+
password: Password used for encryption. Supports ENV reference syntax.
|
|
448
527
|
key: Raw encryption key.
|
|
528
|
+
dotenv_path: Optional path to .env file to load secrets from.
|
|
449
529
|
|
|
450
530
|
Returns:
|
|
451
531
|
Decrypted bytes.
|
|
@@ -455,7 +535,7 @@ class Filanti:
|
|
|
455
535
|
"""
|
|
456
536
|
if password is not None:
|
|
457
537
|
# Resolve password from ENV if needed
|
|
458
|
-
resolved_password = resolve_secret(password)
|
|
538
|
+
resolved_password = resolve_secret(password, dotenv_path=dotenv_path)
|
|
459
539
|
# Parse the encrypted data from bytes
|
|
460
540
|
encrypted = EncryptedData.from_bytes(data)
|
|
461
541
|
return _decrypt_bytes_with_password(encrypted, resolved_password)
|
|
@@ -920,6 +1000,8 @@ class Filanti:
|
|
|
920
1000
|
output: str | Path | None = None,
|
|
921
1001
|
password: str | bytes | None = None,
|
|
922
1002
|
recipient_id: str | None = None,
|
|
1003
|
+
remove_source: bool = False,
|
|
1004
|
+
secure_delete: bool = True,
|
|
923
1005
|
) -> HybridDecryptResult:
|
|
924
1006
|
"""Decrypt a hybrid encrypted file.
|
|
925
1007
|
|
|
@@ -929,6 +1011,9 @@ class Filanti:
|
|
|
929
1011
|
output: Output path (default: removes .henc extension).
|
|
930
1012
|
password: Password if private key is encrypted.
|
|
931
1013
|
recipient_id: Optional recipient ID to select specific session key.
|
|
1014
|
+
remove_source: If True, delete encrypted file after successful decryption.
|
|
1015
|
+
secure_delete: If True and remove_source is True, securely overwrite
|
|
1016
|
+
the encrypted file before deletion.
|
|
932
1017
|
|
|
933
1018
|
Returns:
|
|
934
1019
|
HybridDecryptResult with output path and size.
|
|
@@ -943,6 +1028,13 @@ class Filanti:
|
|
|
943
1028
|
"my-key.pem",
|
|
944
1029
|
password="my-password"
|
|
945
1030
|
)
|
|
1031
|
+
|
|
1032
|
+
# Decrypt and remove encrypted file
|
|
1033
|
+
Filanti.hybrid_decrypt(
|
|
1034
|
+
"secret.txt.henc",
|
|
1035
|
+
"my-key.pem",
|
|
1036
|
+
remove_source=True
|
|
1037
|
+
)
|
|
946
1038
|
"""
|
|
947
1039
|
path = Path(path)
|
|
948
1040
|
if output:
|
|
@@ -957,6 +1049,15 @@ class Filanti:
|
|
|
957
1049
|
|
|
958
1050
|
size = _hybrid_decrypt_file(path, out_path, private_key, password, recipient_id)
|
|
959
1051
|
|
|
1052
|
+
# Remove encrypted source file if requested
|
|
1053
|
+
if remove_source:
|
|
1054
|
+
from filanti.core.file_manager import get_file_manager
|
|
1055
|
+
fm = get_file_manager()
|
|
1056
|
+
if secure_delete:
|
|
1057
|
+
fm.secure_delete(path)
|
|
1058
|
+
else:
|
|
1059
|
+
fm.delete(path)
|
|
1060
|
+
|
|
960
1061
|
return HybridDecryptResult(output_path=out_path, size=size)
|
|
961
1062
|
|
|
962
1063
|
@staticmethod
|