fastcrypter 2.3.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.
- fastcrypter/__init__.py +285 -0
- fastcrypter/advanced_encryptor.py +368 -0
- fastcrypter/algorithms/__init__.py +119 -0
- fastcrypter/algorithms/compression/__init__.py +17 -0
- fastcrypter/algorithms/encryption/__init__.py +17 -0
- fastcrypter/core/__init__.py +16 -0
- fastcrypter/core/compressor.py +409 -0
- fastcrypter/core/custom_encoder.py +309 -0
- fastcrypter/core/encryptor.py +703 -0
- fastcrypter/core/enhanced_compressor.py +542 -0
- fastcrypter/core/key_manager.py +315 -0
- fastcrypter/exceptions.py +219 -0
- fastcrypter/file_encryptor.py +135 -0
- fastcrypter/secure_compressor.py +568 -0
- fastcrypter/utils/__init__.py +17 -0
- fastcrypter-2.3.0.dist-info/METADATA +381 -0
- fastcrypter-2.3.0.dist-info/RECORD +21 -0
- fastcrypter-2.3.0.dist-info/WHEEL +5 -0
- fastcrypter-2.3.0.dist-info/entry_points.txt +2 -0
- fastcrypter-2.3.0.dist-info/licenses/LICENSE +21 -0
- fastcrypter-2.3.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,568 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Secure Compressor - High-level interface for compression and encryption.
|
|
3
|
+
|
|
4
|
+
This module provides a simple, secure interface that combines compression
|
|
5
|
+
and encryption in a single operation for maximum security and efficiency.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Union, Optional, Dict, Any
|
|
9
|
+
from .core.compressor import Compressor, CompressionAlgorithmType, CompressionLevel
|
|
10
|
+
from .core.encryptor import Encryptor, EncryptionAlgorithmType
|
|
11
|
+
from .core.key_manager import KeyManager
|
|
12
|
+
from .core.custom_encoder import CustomEncoder
|
|
13
|
+
from .exceptions import EncrypterError, ValidationError, ErrorCodes
|
|
14
|
+
|
|
15
|
+
# Try to import C/C++ extensions for speed
|
|
16
|
+
try:
|
|
17
|
+
from .core import fast_crypto
|
|
18
|
+
FAST_CRYPTO_AVAILABLE = True
|
|
19
|
+
except ImportError:
|
|
20
|
+
FAST_CRYPTO_AVAILABLE = False
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
from .core import fast_compression
|
|
24
|
+
FAST_COMPRESSION_AVAILABLE = True
|
|
25
|
+
except ImportError:
|
|
26
|
+
FAST_COMPRESSION_AVAILABLE = False
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class SecureCompressor:
|
|
30
|
+
"""
|
|
31
|
+
High-level secure compressor that combines compression and encryption.
|
|
32
|
+
|
|
33
|
+
This class provides a simple interface for securely compressing and
|
|
34
|
+
encrypting data in a single operation, with automatic algorithm selection
|
|
35
|
+
and key management. Now includes custom encoding for specified character sets.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
def __init__(self,
|
|
39
|
+
password: str,
|
|
40
|
+
compression_algorithm: Union[CompressionAlgorithmType, str] = CompressionAlgorithmType.ZLIB,
|
|
41
|
+
compression_level: Union[CompressionLevel, int] = CompressionLevel.BALANCED,
|
|
42
|
+
encryption_algorithm: Union[EncryptionAlgorithmType, str] = EncryptionAlgorithmType.AES_256_GCM,
|
|
43
|
+
auto_select_compression: bool = True,
|
|
44
|
+
kdf_algorithm: str = 'pbkdf2',
|
|
45
|
+
kdf_iterations: int = 100000,
|
|
46
|
+
custom_charset: Optional[str] = None,
|
|
47
|
+
use_fast_extensions: bool = True):
|
|
48
|
+
"""
|
|
49
|
+
Initialize the SecureCompressor.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
password (str): Password for encryption key derivation.
|
|
53
|
+
compression_algorithm: Compression algorithm to use.
|
|
54
|
+
compression_level: Compression level (1-9).
|
|
55
|
+
encryption_algorithm: Encryption algorithm to use.
|
|
56
|
+
auto_select_compression (bool): Auto-select best compression algorithm.
|
|
57
|
+
kdf_algorithm (str): Key derivation function algorithm.
|
|
58
|
+
kdf_iterations (int): Number of KDF iterations.
|
|
59
|
+
custom_charset (str, optional): Custom character set for encoding output.
|
|
60
|
+
use_fast_extensions (bool): Use C/C++ extensions if available.
|
|
61
|
+
|
|
62
|
+
Raises:
|
|
63
|
+
ValidationError: If parameters are invalid.
|
|
64
|
+
"""
|
|
65
|
+
# Validate password
|
|
66
|
+
if not password or len(password) < 8:
|
|
67
|
+
raise ValidationError(
|
|
68
|
+
"Password must be at least 8 characters long",
|
|
69
|
+
ErrorCodes.KEY_TOO_WEAK
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
self.password = password
|
|
73
|
+
self.use_fast_extensions = use_fast_extensions and (FAST_CRYPTO_AVAILABLE or FAST_COMPRESSION_AVAILABLE)
|
|
74
|
+
|
|
75
|
+
# Initialize components
|
|
76
|
+
self.compressor = Compressor(
|
|
77
|
+
algorithm=compression_algorithm,
|
|
78
|
+
level=compression_level,
|
|
79
|
+
auto_select=auto_select_compression
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
self.encryptor = Encryptor(
|
|
83
|
+
algorithm=encryption_algorithm,
|
|
84
|
+
derive_key=True
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
self.key_manager = KeyManager(
|
|
88
|
+
kdf_algorithm=kdf_algorithm,
|
|
89
|
+
iterations=kdf_iterations
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
# Initialize custom encoder if charset provided
|
|
93
|
+
self.custom_encoder = None
|
|
94
|
+
if custom_charset:
|
|
95
|
+
self.custom_encoder = CustomEncoder(charset=custom_charset)
|
|
96
|
+
|
|
97
|
+
# Store configuration
|
|
98
|
+
self.config = {
|
|
99
|
+
'compression_algorithm': compression_algorithm,
|
|
100
|
+
'compression_level': compression_level,
|
|
101
|
+
'encryption_algorithm': encryption_algorithm,
|
|
102
|
+
'auto_select_compression': auto_select_compression,
|
|
103
|
+
'kdf_algorithm': kdf_algorithm,
|
|
104
|
+
'kdf_iterations': kdf_iterations,
|
|
105
|
+
'custom_charset': custom_charset,
|
|
106
|
+
'use_fast_extensions': self.use_fast_extensions,
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
def compress_and_encrypt(self, data: Union[str, bytes],
|
|
110
|
+
output_format: str = 'binary') -> Union[bytes, str]:
|
|
111
|
+
"""
|
|
112
|
+
Compress and encrypt data in a single operation.
|
|
113
|
+
|
|
114
|
+
The process follows these steps:
|
|
115
|
+
1. Compress the data using the configured compression algorithm
|
|
116
|
+
2. Encrypt the compressed data using the configured encryption algorithm
|
|
117
|
+
3. Optionally encode to custom character set
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
data: Data to compress and encrypt (string or bytes).
|
|
121
|
+
output_format: Output format ('binary', 'custom', 'steganographic').
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
Union[bytes, str]: Encrypted compressed data.
|
|
125
|
+
|
|
126
|
+
Raises:
|
|
127
|
+
EncrypterError: If compression or encryption fails.
|
|
128
|
+
ValidationError: If input data is invalid.
|
|
129
|
+
"""
|
|
130
|
+
try:
|
|
131
|
+
# Step 1: Compress data (with fast extension if available)
|
|
132
|
+
if self.use_fast_extensions and FAST_COMPRESSION_AVAILABLE:
|
|
133
|
+
if isinstance(data, str):
|
|
134
|
+
data = data.encode('utf-8')
|
|
135
|
+
compressed_data = fast_compression.fast_compress(data)
|
|
136
|
+
else:
|
|
137
|
+
compressed_data = self.compressor.compress(data)
|
|
138
|
+
|
|
139
|
+
# Step 2: Encrypt compressed data
|
|
140
|
+
encrypted_data = self.encryptor.encrypt(compressed_data, self.password)
|
|
141
|
+
|
|
142
|
+
# Step 3: Apply custom encoding if requested
|
|
143
|
+
if output_format == 'binary':
|
|
144
|
+
return encrypted_data
|
|
145
|
+
elif output_format == 'custom' and self.custom_encoder:
|
|
146
|
+
return self.custom_encoder.encode(encrypted_data)
|
|
147
|
+
elif output_format == 'steganographic' and self.custom_encoder:
|
|
148
|
+
return self.custom_encoder.create_steganographic_text(encrypted_data)
|
|
149
|
+
else:
|
|
150
|
+
return encrypted_data
|
|
151
|
+
|
|
152
|
+
except Exception as e:
|
|
153
|
+
raise EncrypterError(
|
|
154
|
+
f"Secure compression failed: {str(e)}",
|
|
155
|
+
details={"operation": "compress_and_encrypt", "error": str(e)}
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
def decrypt_and_decompress(self, data: Union[bytes, str],
|
|
159
|
+
input_format: str = 'binary') -> bytes:
|
|
160
|
+
"""
|
|
161
|
+
Decrypt and decompress data in a single operation.
|
|
162
|
+
|
|
163
|
+
The process follows these steps:
|
|
164
|
+
1. Decode from custom format if necessary
|
|
165
|
+
2. Decrypt the data using the configured encryption algorithm
|
|
166
|
+
3. Decompress the decrypted data using the appropriate compression algorithm
|
|
167
|
+
4. Return the original data
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
data: Encrypted compressed data to decrypt and decompress.
|
|
171
|
+
input_format: Input format ('binary', 'custom', 'steganographic').
|
|
172
|
+
|
|
173
|
+
Returns:
|
|
174
|
+
bytes: Original decompressed data.
|
|
175
|
+
|
|
176
|
+
Raises:
|
|
177
|
+
EncrypterError: If decryption or decompression fails.
|
|
178
|
+
ValidationError: If input data is invalid.
|
|
179
|
+
"""
|
|
180
|
+
try:
|
|
181
|
+
# Step 1: Decode from custom format if necessary
|
|
182
|
+
if input_format == 'custom' and self.custom_encoder and isinstance(data, str):
|
|
183
|
+
encrypted_data = self.custom_encoder.decode(data)
|
|
184
|
+
elif input_format == 'binary':
|
|
185
|
+
encrypted_data = data
|
|
186
|
+
else:
|
|
187
|
+
encrypted_data = data
|
|
188
|
+
|
|
189
|
+
# Step 2: Decrypt data
|
|
190
|
+
decrypted_data = self.encryptor.decrypt(encrypted_data, self.password)
|
|
191
|
+
|
|
192
|
+
# Step 3: Decompress decrypted data (with fast extension if available)
|
|
193
|
+
if self.use_fast_extensions and FAST_COMPRESSION_AVAILABLE:
|
|
194
|
+
decompressed_data = fast_compression.fast_decompress(decrypted_data)
|
|
195
|
+
else:
|
|
196
|
+
decompressed_data = self.compressor.decompress(decrypted_data)
|
|
197
|
+
|
|
198
|
+
return decompressed_data
|
|
199
|
+
|
|
200
|
+
except Exception as e:
|
|
201
|
+
raise EncrypterError(
|
|
202
|
+
f"Secure decompression failed: {str(e)}",
|
|
203
|
+
details={"operation": "decrypt_and_decompress", "error": str(e)}
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
def compress_and_encrypt_to_custom(self, data: Union[str, bytes],
|
|
207
|
+
charset: str = "abcdef98Xvbvii") -> str:
|
|
208
|
+
"""
|
|
209
|
+
Compress, encrypt, and encode to custom character set.
|
|
210
|
+
|
|
211
|
+
Args:
|
|
212
|
+
data: Data to process.
|
|
213
|
+
charset: Custom character set to use.
|
|
214
|
+
|
|
215
|
+
Returns:
|
|
216
|
+
str: Encoded string using only specified characters.
|
|
217
|
+
"""
|
|
218
|
+
# Create temporary encoder if different charset
|
|
219
|
+
if not self.custom_encoder or self.custom_encoder.charset != charset:
|
|
220
|
+
temp_encoder = CustomEncoder(charset=charset)
|
|
221
|
+
else:
|
|
222
|
+
temp_encoder = self.custom_encoder
|
|
223
|
+
|
|
224
|
+
# Compress and encrypt
|
|
225
|
+
encrypted_data = self.compress_and_encrypt(data, output_format='binary')
|
|
226
|
+
|
|
227
|
+
# Encode to custom charset
|
|
228
|
+
return temp_encoder.encode(encrypted_data)
|
|
229
|
+
|
|
230
|
+
def decrypt_and_decompress_from_custom(self, encoded_data: str,
|
|
231
|
+
charset: str = "abcdef98Xvbvii") -> bytes:
|
|
232
|
+
"""
|
|
233
|
+
Decode from custom character set, decrypt, and decompress.
|
|
234
|
+
|
|
235
|
+
Args:
|
|
236
|
+
encoded_data: Data encoded with custom charset.
|
|
237
|
+
charset: Custom character set used for encoding.
|
|
238
|
+
|
|
239
|
+
Returns:
|
|
240
|
+
bytes: Original data.
|
|
241
|
+
"""
|
|
242
|
+
# Create temporary encoder if different charset
|
|
243
|
+
if not self.custom_encoder or self.custom_encoder.charset != charset:
|
|
244
|
+
temp_encoder = CustomEncoder(charset=charset)
|
|
245
|
+
else:
|
|
246
|
+
temp_encoder = self.custom_encoder
|
|
247
|
+
|
|
248
|
+
# Decode from custom charset
|
|
249
|
+
encrypted_data = temp_encoder.decode(encoded_data)
|
|
250
|
+
|
|
251
|
+
# Decrypt and decompress
|
|
252
|
+
return self.decrypt_and_decompress(encrypted_data, input_format='binary')
|
|
253
|
+
|
|
254
|
+
def compress_and_encrypt_string(self, text: str,
|
|
255
|
+
output_format: str = 'binary') -> Union[bytes, str]:
|
|
256
|
+
"""
|
|
257
|
+
Compress and encrypt a string, returning encrypted data.
|
|
258
|
+
|
|
259
|
+
Args:
|
|
260
|
+
text (str): Text to compress and encrypt.
|
|
261
|
+
output_format: Output format ('binary', 'custom', 'steganographic').
|
|
262
|
+
|
|
263
|
+
Returns:
|
|
264
|
+
Union[bytes, str]: Encrypted compressed data.
|
|
265
|
+
"""
|
|
266
|
+
return self.compress_and_encrypt(text, output_format)
|
|
267
|
+
|
|
268
|
+
def decrypt_and_decompress_to_string(self, data: Union[bytes, str],
|
|
269
|
+
input_format: str = 'binary',
|
|
270
|
+
encoding: str = 'utf-8') -> str:
|
|
271
|
+
"""
|
|
272
|
+
Decrypt and decompress data, returning a string.
|
|
273
|
+
|
|
274
|
+
Args:
|
|
275
|
+
data: Encrypted compressed data.
|
|
276
|
+
input_format: Input format ('binary', 'custom', 'steganographic').
|
|
277
|
+
encoding (str): Text encoding to use for decoding.
|
|
278
|
+
|
|
279
|
+
Returns:
|
|
280
|
+
str: Original text.
|
|
281
|
+
|
|
282
|
+
Raises:
|
|
283
|
+
UnicodeDecodeError: If data cannot be decoded as text.
|
|
284
|
+
"""
|
|
285
|
+
decompressed_data = self.decrypt_and_decompress(data, input_format)
|
|
286
|
+
return decompressed_data.decode(encoding)
|
|
287
|
+
|
|
288
|
+
def get_compression_ratio(self, original_data: Union[str, bytes],
|
|
289
|
+
compressed_encrypted_data: Union[bytes, str]) -> float:
|
|
290
|
+
"""
|
|
291
|
+
Calculate the overall compression ratio (including encryption overhead).
|
|
292
|
+
|
|
293
|
+
Args:
|
|
294
|
+
original_data: Original uncompressed data.
|
|
295
|
+
compressed_encrypted_data: Final encrypted compressed data.
|
|
296
|
+
|
|
297
|
+
Returns:
|
|
298
|
+
float: Compression ratio (final_size / original_size).
|
|
299
|
+
"""
|
|
300
|
+
if isinstance(original_data, str):
|
|
301
|
+
original_data = original_data.encode('utf-8')
|
|
302
|
+
|
|
303
|
+
if len(original_data) == 0:
|
|
304
|
+
return 0.0
|
|
305
|
+
|
|
306
|
+
if isinstance(compressed_encrypted_data, str):
|
|
307
|
+
final_size = len(compressed_encrypted_data.encode('utf-8'))
|
|
308
|
+
else:
|
|
309
|
+
final_size = len(compressed_encrypted_data)
|
|
310
|
+
|
|
311
|
+
return final_size / len(original_data)
|
|
312
|
+
|
|
313
|
+
def estimate_output_size(self, input_size: int, output_format: str = 'binary') -> Dict[str, int]:
|
|
314
|
+
"""
|
|
315
|
+
Estimate the output size for given input size.
|
|
316
|
+
|
|
317
|
+
Args:
|
|
318
|
+
input_size (int): Size of input data in bytes.
|
|
319
|
+
output_format: Output format to estimate for.
|
|
320
|
+
|
|
321
|
+
Returns:
|
|
322
|
+
Dict[str, int]: Estimated sizes for different stages.
|
|
323
|
+
"""
|
|
324
|
+
# Rough estimates based on typical compression ratios and encryption overhead
|
|
325
|
+
compression_ratios = {
|
|
326
|
+
CompressionAlgorithmType.ZLIB: 0.6,
|
|
327
|
+
CompressionAlgorithmType.LZMA: 0.4,
|
|
328
|
+
CompressionAlgorithmType.BROTLI: 0.5,
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
# Get compression ratio estimate
|
|
332
|
+
comp_ratio = compression_ratios.get(self.compressor.algorithm, 0.6)
|
|
333
|
+
compressed_size = int(input_size * comp_ratio) + 8 # Add header overhead
|
|
334
|
+
|
|
335
|
+
# Encryption adds overhead (headers, IV, tag, etc.)
|
|
336
|
+
encryption_overhead = 64 # Conservative estimate
|
|
337
|
+
encrypted_size = compressed_size + encryption_overhead
|
|
338
|
+
|
|
339
|
+
# Custom encoding overhead
|
|
340
|
+
if output_format == 'custom' and self.custom_encoder:
|
|
341
|
+
# Base conversion typically increases size
|
|
342
|
+
custom_size = int(encrypted_size * 1.4) # Rough estimate
|
|
343
|
+
else:
|
|
344
|
+
custom_size = encrypted_size
|
|
345
|
+
|
|
346
|
+
return {
|
|
347
|
+
'original_size': input_size,
|
|
348
|
+
'estimated_compressed_size': compressed_size,
|
|
349
|
+
'estimated_encrypted_size': encrypted_size,
|
|
350
|
+
'estimated_final_size': custom_size,
|
|
351
|
+
'estimated_compression_ratio': comp_ratio,
|
|
352
|
+
'estimated_total_ratio': custom_size / input_size if input_size > 0 else 0,
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
def change_password(self, new_password: str) -> None:
|
|
356
|
+
"""
|
|
357
|
+
Change the password used for encryption.
|
|
358
|
+
|
|
359
|
+
Args:
|
|
360
|
+
new_password (str): New password to use.
|
|
361
|
+
|
|
362
|
+
Raises:
|
|
363
|
+
ValidationError: If new password is too weak.
|
|
364
|
+
"""
|
|
365
|
+
if not new_password or len(new_password) < 8:
|
|
366
|
+
raise ValidationError(
|
|
367
|
+
"New password must be at least 8 characters long",
|
|
368
|
+
ErrorCodes.KEY_TOO_WEAK
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
self.password = new_password
|
|
372
|
+
|
|
373
|
+
def set_custom_charset(self, charset: str) -> None:
|
|
374
|
+
"""
|
|
375
|
+
Set or change the custom character set for encoding.
|
|
376
|
+
|
|
377
|
+
Args:
|
|
378
|
+
charset (str): New character set to use.
|
|
379
|
+
"""
|
|
380
|
+
self.custom_encoder = CustomEncoder(charset=charset)
|
|
381
|
+
self.config['custom_charset'] = charset
|
|
382
|
+
|
|
383
|
+
def validate_password_strength(self, password: Optional[str] = None) -> Dict[str, Any]:
|
|
384
|
+
"""
|
|
385
|
+
Validate password strength.
|
|
386
|
+
|
|
387
|
+
Args:
|
|
388
|
+
password (str, optional): Password to validate. Uses current password if None.
|
|
389
|
+
|
|
390
|
+
Returns:
|
|
391
|
+
Dict[str, Any]: Password strength analysis.
|
|
392
|
+
"""
|
|
393
|
+
pwd = password or self.password
|
|
394
|
+
|
|
395
|
+
# Basic strength checks
|
|
396
|
+
length_ok = len(pwd) >= 8
|
|
397
|
+
has_upper = any(c.isupper() for c in pwd)
|
|
398
|
+
has_lower = any(c.islower() for c in pwd)
|
|
399
|
+
has_digit = any(c.isdigit() for c in pwd)
|
|
400
|
+
has_special = any(not c.isalnum() for c in pwd)
|
|
401
|
+
|
|
402
|
+
# Calculate strength score
|
|
403
|
+
score = 0
|
|
404
|
+
if length_ok:
|
|
405
|
+
score += 1
|
|
406
|
+
if len(pwd) >= 12:
|
|
407
|
+
score += 1
|
|
408
|
+
if has_upper:
|
|
409
|
+
score += 1
|
|
410
|
+
if has_lower:
|
|
411
|
+
score += 1
|
|
412
|
+
if has_digit:
|
|
413
|
+
score += 1
|
|
414
|
+
if has_special:
|
|
415
|
+
score += 1
|
|
416
|
+
|
|
417
|
+
# Determine strength level
|
|
418
|
+
if score >= 5:
|
|
419
|
+
strength = "Strong"
|
|
420
|
+
elif score >= 3:
|
|
421
|
+
strength = "Medium"
|
|
422
|
+
else:
|
|
423
|
+
strength = "Weak"
|
|
424
|
+
|
|
425
|
+
return {
|
|
426
|
+
'strength': strength,
|
|
427
|
+
'score': score,
|
|
428
|
+
'max_score': 6,
|
|
429
|
+
'checks': {
|
|
430
|
+
'length_ok': length_ok,
|
|
431
|
+
'has_uppercase': has_upper,
|
|
432
|
+
'has_lowercase': has_lower,
|
|
433
|
+
'has_digits': has_digit,
|
|
434
|
+
'has_special_chars': has_special,
|
|
435
|
+
},
|
|
436
|
+
'recommendations': self._get_password_recommendations(pwd)
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
def _get_password_recommendations(self, password: str) -> list:
|
|
440
|
+
"""Get password improvement recommendations."""
|
|
441
|
+
recommendations = []
|
|
442
|
+
|
|
443
|
+
if len(password) < 8:
|
|
444
|
+
recommendations.append("Use at least 8 characters")
|
|
445
|
+
elif len(password) < 12:
|
|
446
|
+
recommendations.append("Consider using 12+ characters for better security")
|
|
447
|
+
|
|
448
|
+
if not any(c.isupper() for c in password):
|
|
449
|
+
recommendations.append("Add uppercase letters")
|
|
450
|
+
|
|
451
|
+
if not any(c.islower() for c in password):
|
|
452
|
+
recommendations.append("Add lowercase letters")
|
|
453
|
+
|
|
454
|
+
if not any(c.isdigit() for c in password):
|
|
455
|
+
recommendations.append("Add numbers")
|
|
456
|
+
|
|
457
|
+
if not any(not c.isalnum() for c in password):
|
|
458
|
+
recommendations.append("Add special characters (!@#$%^&*)")
|
|
459
|
+
|
|
460
|
+
if not recommendations:
|
|
461
|
+
recommendations.append("Password strength is good!")
|
|
462
|
+
|
|
463
|
+
return recommendations
|
|
464
|
+
|
|
465
|
+
def get_info(self) -> Dict[str, Any]:
|
|
466
|
+
"""
|
|
467
|
+
Get comprehensive information about the SecureCompressor configuration.
|
|
468
|
+
|
|
469
|
+
Returns:
|
|
470
|
+
Dict[str, Any]: Configuration and status information.
|
|
471
|
+
"""
|
|
472
|
+
info = {
|
|
473
|
+
'version': '1.0.0',
|
|
474
|
+
'configuration': self.config,
|
|
475
|
+
'compressor_info': self.compressor.get_info(),
|
|
476
|
+
'encryptor_info': self.encryptor.get_info(),
|
|
477
|
+
'key_manager_info': self.key_manager.get_info(),
|
|
478
|
+
'password_strength': self.validate_password_strength(),
|
|
479
|
+
'fast_extensions': {
|
|
480
|
+
'crypto_available': FAST_CRYPTO_AVAILABLE,
|
|
481
|
+
'compression_available': FAST_COMPRESSION_AVAILABLE,
|
|
482
|
+
'enabled': self.use_fast_extensions,
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
if self.custom_encoder:
|
|
487
|
+
info['custom_encoder_info'] = self.custom_encoder.get_charset_info()
|
|
488
|
+
|
|
489
|
+
return info
|
|
490
|
+
|
|
491
|
+
def benchmark_performance(self, data_size: int = 1024) -> Dict[str, Any]:
|
|
492
|
+
"""
|
|
493
|
+
Benchmark the performance of different operations.
|
|
494
|
+
|
|
495
|
+
Args:
|
|
496
|
+
data_size: Size of test data in bytes.
|
|
497
|
+
|
|
498
|
+
Returns:
|
|
499
|
+
Dict[str, Any]: Benchmark results.
|
|
500
|
+
"""
|
|
501
|
+
import time
|
|
502
|
+
import secrets
|
|
503
|
+
|
|
504
|
+
# Generate test data
|
|
505
|
+
test_data = secrets.token_bytes(data_size)
|
|
506
|
+
|
|
507
|
+
results = {}
|
|
508
|
+
|
|
509
|
+
# Benchmark binary format
|
|
510
|
+
start_time = time.time()
|
|
511
|
+
encrypted = self.compress_and_encrypt(test_data, 'binary')
|
|
512
|
+
encrypt_time = time.time() - start_time
|
|
513
|
+
|
|
514
|
+
start_time = time.time()
|
|
515
|
+
decrypted = self.decrypt_and_decompress(encrypted, 'binary')
|
|
516
|
+
decrypt_time = time.time() - start_time
|
|
517
|
+
|
|
518
|
+
results['binary'] = {
|
|
519
|
+
'encrypt_time': encrypt_time,
|
|
520
|
+
'decrypt_time': decrypt_time,
|
|
521
|
+
'total_time': encrypt_time + decrypt_time,
|
|
522
|
+
'throughput_mbps': (data_size / (1024 * 1024)) / (encrypt_time + decrypt_time),
|
|
523
|
+
'compression_ratio': len(encrypted) / data_size,
|
|
524
|
+
'correctness': test_data == decrypted
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
# Benchmark custom encoding if available
|
|
528
|
+
if self.custom_encoder:
|
|
529
|
+
start_time = time.time()
|
|
530
|
+
custom_encrypted = self.compress_and_encrypt(test_data, 'custom')
|
|
531
|
+
custom_encrypt_time = time.time() - start_time
|
|
532
|
+
|
|
533
|
+
start_time = time.time()
|
|
534
|
+
custom_decrypted = self.decrypt_and_decompress(custom_encrypted, 'custom')
|
|
535
|
+
custom_decrypt_time = time.time() - start_time
|
|
536
|
+
|
|
537
|
+
results['custom'] = {
|
|
538
|
+
'encrypt_time': custom_encrypt_time,
|
|
539
|
+
'decrypt_time': custom_decrypt_time,
|
|
540
|
+
'total_time': custom_encrypt_time + custom_decrypt_time,
|
|
541
|
+
'throughput_mbps': (data_size / (1024 * 1024)) / (custom_encrypt_time + custom_decrypt_time),
|
|
542
|
+
'expansion_ratio': len(custom_encrypted.encode('utf-8')) / data_size,
|
|
543
|
+
'correctness': test_data == custom_decrypted
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
return results
|
|
547
|
+
|
|
548
|
+
def __repr__(self) -> str:
|
|
549
|
+
"""String representation of the SecureCompressor."""
|
|
550
|
+
charset_info = f", charset={self.custom_encoder.charset}" if self.custom_encoder else ""
|
|
551
|
+
return (f"SecureCompressor("
|
|
552
|
+
f"compression={self.compressor.algorithm.value}, "
|
|
553
|
+
f"encryption={self.encryptor.algorithm.value}, "
|
|
554
|
+
f"kdf={self.key_manager.kdf_algorithm}"
|
|
555
|
+
f"{charset_info})")
|
|
556
|
+
|
|
557
|
+
def __str__(self) -> str:
|
|
558
|
+
"""Human-readable string representation."""
|
|
559
|
+
base_str = (f"Secure Compressor with {self.compressor.algorithm.value.upper()} compression "
|
|
560
|
+
f"and {self.encryptor.algorithm.value.upper()} encryption")
|
|
561
|
+
|
|
562
|
+
if self.custom_encoder:
|
|
563
|
+
base_str += f" using custom charset '{self.custom_encoder.charset}'"
|
|
564
|
+
|
|
565
|
+
if self.use_fast_extensions:
|
|
566
|
+
base_str += " (fast extensions enabled)"
|
|
567
|
+
|
|
568
|
+
return base_str
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Utility modules for the Encrypter package.
|
|
3
|
+
|
|
4
|
+
This package contains helper functions, validators,
|
|
5
|
+
and other utility components.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
# Import will be added when utility files are created
|
|
9
|
+
# from .validators import validate_input, validate_key
|
|
10
|
+
# from .helpers import secure_random, clear_memory
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
# "validate_input",
|
|
14
|
+
# "validate_key",
|
|
15
|
+
# "secure_random",
|
|
16
|
+
# "clear_memory",
|
|
17
|
+
]
|