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.
@@ -0,0 +1,542 @@
1
+ """
2
+ Enhanced Compressor with Native Library Integration
3
+
4
+ This module provides an enhanced version of the compressor that automatically
5
+ uses native C/C++ libraries when available for maximum performance.
6
+ """
7
+
8
+ from typing import Union, Optional, Dict, Any
9
+ from .compressor import Compressor, CompressionAlgorithmType, CompressionLevel
10
+ from .encryptor import Encryptor, EncryptionAlgorithmType
11
+ from .key_manager import KeyManager
12
+ from .custom_encoder import CustomEncoder
13
+ from ..exceptions import EncrypterError, ValidationError, ErrorCodes
14
+
15
+ # Import native library support
16
+ try:
17
+ from ..native.native_loader import (
18
+ get_native_manager, get_crypto_core, get_hash_algorithms, is_native_available
19
+ )
20
+ NATIVE_SUPPORT = True
21
+ except ImportError:
22
+ NATIVE_SUPPORT = False
23
+
24
+
25
+ class EnhancedCompressor:
26
+ """
27
+ Enhanced compressor with native library integration for maximum performance.
28
+
29
+ This class automatically detects and uses native C/C++ libraries when available,
30
+ falling back to pure Python implementations when necessary.
31
+ """
32
+
33
+ def __init__(self,
34
+ password: str,
35
+ compression_algorithm: Union[CompressionAlgorithmType, str] = CompressionAlgorithmType.ZLIB,
36
+ compression_level: Union[CompressionLevel, int] = CompressionLevel.BALANCED,
37
+ encryption_algorithm: Union[EncryptionAlgorithmType, str] = EncryptionAlgorithmType.AES_256_GCM,
38
+ auto_select_compression: bool = True,
39
+ kdf_algorithm: str = 'pbkdf2',
40
+ kdf_iterations: int = 100000,
41
+ custom_charset: Optional[str] = None,
42
+ prefer_native: bool = True):
43
+ """
44
+ Initialize the EnhancedCompressor.
45
+
46
+ Args:
47
+ password (str): Password for encryption key derivation.
48
+ compression_algorithm: Compression algorithm to use.
49
+ compression_level: Compression level (1-9).
50
+ encryption_algorithm: Encryption algorithm to use.
51
+ auto_select_compression (bool): Auto-select best compression algorithm.
52
+ kdf_algorithm (str): Key derivation function algorithm.
53
+ kdf_iterations (int): Number of KDF iterations.
54
+ custom_charset (str, optional): Custom character set for encoding output.
55
+ prefer_native (bool): Prefer native libraries when available.
56
+ """
57
+ # Validate password
58
+ if not password or len(password) < 8:
59
+ raise ValidationError(
60
+ "Password must be at least 8 characters long",
61
+ ErrorCodes.KEY_TOO_WEAK
62
+ )
63
+
64
+ self.password = password
65
+ self.prefer_native = prefer_native and NATIVE_SUPPORT
66
+
67
+ # Initialize native library manager
68
+ if self.prefer_native:
69
+ self.native_manager = get_native_manager()
70
+ self.crypto_core = get_crypto_core()
71
+ self.hash_algorithms = get_hash_algorithms()
72
+ else:
73
+ self.native_manager = None
74
+ self.crypto_core = None
75
+ self.hash_algorithms = None
76
+
77
+ # Initialize standard components
78
+ self.compressor = Compressor(
79
+ algorithm=compression_algorithm,
80
+ level=compression_level,
81
+ auto_select=auto_select_compression
82
+ )
83
+
84
+ self.encryptor = Encryptor(
85
+ algorithm=encryption_algorithm,
86
+ derive_key=True
87
+ )
88
+
89
+ self.key_manager = KeyManager(
90
+ kdf_algorithm=kdf_algorithm,
91
+ iterations=kdf_iterations
92
+ )
93
+
94
+ # Initialize custom encoder if charset provided
95
+ self.custom_encoder = None
96
+ if custom_charset:
97
+ self.custom_encoder = CustomEncoder(charset=custom_charset)
98
+
99
+ # Store configuration
100
+ self.config = {
101
+ 'compression_algorithm': compression_algorithm,
102
+ 'compression_level': compression_level,
103
+ 'encryption_algorithm': encryption_algorithm,
104
+ 'auto_select_compression': auto_select_compression,
105
+ 'kdf_algorithm': kdf_algorithm,
106
+ 'kdf_iterations': kdf_iterations,
107
+ 'custom_charset': custom_charset,
108
+ 'prefer_native': self.prefer_native,
109
+ 'native_available': self.is_native_available(),
110
+ }
111
+
112
+ def is_native_available(self) -> bool:
113
+ """Check if native libraries are available."""
114
+ return self.prefer_native and (self.crypto_core is not None or self.hash_algorithms is not None)
115
+
116
+ def _fast_key_derivation(self, password: str, salt: bytes, iterations: int, key_length: int) -> bytes:
117
+ """Use native key derivation if available."""
118
+ if self.hash_algorithms:
119
+ try:
120
+ password_bytes = password.encode('utf-8')
121
+ return self.hash_algorithms.fast_pbkdf2(password_bytes, salt, iterations, key_length)
122
+ except Exception:
123
+ pass
124
+
125
+ # Fallback to standard key manager
126
+ return self.key_manager.derive_key(password, salt, key_length)
127
+
128
+ def _fast_compression(self, data: bytes) -> bytes:
129
+ """Use native compression if available."""
130
+ if self.crypto_core:
131
+ try:
132
+ # Try native RLE compression first
133
+ compressed = self.crypto_core.fast_compress_rle(data)
134
+ if len(compressed) < len(data):
135
+ return compressed
136
+ except Exception:
137
+ pass
138
+
139
+ # Fallback to standard compressor
140
+ return self.compressor.compress(data)
141
+
142
+ def _fast_decompression(self, data: bytes) -> bytes:
143
+ """Use native decompression if available."""
144
+ if self.crypto_core:
145
+ try:
146
+ # Check if this looks like RLE compressed data
147
+ if len(data) > 0 and data[0] == 0xFF:
148
+ return self.crypto_core.fast_decompress_rle(data)
149
+ except Exception:
150
+ pass
151
+
152
+ # Fallback to standard compressor
153
+ return self.compressor.decompress(data)
154
+
155
+ def _fast_xor_encryption(self, data: bytes, key: bytes) -> bytes:
156
+ """Use native XOR if available for additional obfuscation."""
157
+ if self.crypto_core:
158
+ try:
159
+ return self.crypto_core.fast_xor(data, key)
160
+ except Exception:
161
+ pass
162
+
163
+ # Fallback to Python XOR
164
+ result = bytearray(data)
165
+ for i in range(len(result)):
166
+ result[i] ^= key[i % len(key)]
167
+ return bytes(result)
168
+
169
+ def _fast_hash(self, data: bytes) -> bytes:
170
+ """Use native SHA-256 if available."""
171
+ if self.hash_algorithms:
172
+ try:
173
+ return self.hash_algorithms.fast_sha256(data)
174
+ except Exception:
175
+ pass
176
+
177
+ # Fallback to standard hash
178
+ import hashlib
179
+ return hashlib.sha256(data).digest()
180
+
181
+ def _fast_hmac(self, key: bytes, data: bytes) -> bytes:
182
+ """Use native HMAC if available."""
183
+ if self.hash_algorithms:
184
+ try:
185
+ return self.hash_algorithms.fast_hmac_sha256(key, data)
186
+ except Exception:
187
+ pass
188
+
189
+ # Fallback to standard HMAC
190
+ import hmac
191
+ import hashlib
192
+ return hmac.new(key, data, hashlib.sha256).digest()
193
+
194
+ def _fast_custom_encoding(self, data: bytes, charset: str) -> str:
195
+ """Use native base conversion if available."""
196
+ if self.crypto_core:
197
+ try:
198
+ return self.crypto_core.base_convert_encode(data, charset)
199
+ except Exception:
200
+ pass
201
+
202
+ # Fallback to custom encoder
203
+ if self.custom_encoder and self.custom_encoder.charset == charset:
204
+ return self.custom_encoder.encode(data)
205
+
206
+ temp_encoder = CustomEncoder(charset=charset)
207
+ return temp_encoder.encode(data)
208
+
209
+ def _calculate_entropy(self, data: bytes) -> float:
210
+ """Calculate data entropy using native library if available."""
211
+ if self.crypto_core:
212
+ try:
213
+ return self.crypto_core.calculate_entropy(data)
214
+ except Exception:
215
+ pass
216
+
217
+ # Fallback to Python implementation
218
+ if not data:
219
+ return 0.0
220
+
221
+ freq = {}
222
+ for byte in data:
223
+ freq[byte] = freq.get(byte, 0) + 1
224
+
225
+ entropy = 0.0
226
+ length = len(data)
227
+ for count in freq.values():
228
+ p = count / length
229
+ if p > 0:
230
+ # Use approximation: log2(p) ≈ (p.bit_length() - 1) for integers
231
+ # For floats, we'll use a simple approximation
232
+ import math
233
+ entropy -= p * math.log2(p)
234
+
235
+ return entropy
236
+
237
+ def compress_and_encrypt(self, data: Union[str, bytes],
238
+ output_format: str = 'binary',
239
+ use_native_optimizations: bool = True) -> Union[bytes, str]:
240
+ """
241
+ Compress and encrypt data with native optimizations.
242
+
243
+ Args:
244
+ data: Data to compress and encrypt.
245
+ output_format: Output format ('binary', 'custom', 'steganographic').
246
+ use_native_optimizations: Use native libraries for optimization.
247
+
248
+ Returns:
249
+ Union[bytes, str]: Encrypted compressed data.
250
+ """
251
+ try:
252
+ # Convert string to bytes if necessary
253
+ if isinstance(data, str):
254
+ data_bytes = data.encode('utf-8')
255
+ else:
256
+ data_bytes = data
257
+
258
+ # Step 1: Analyze data for optimal compression
259
+ entropy = self._calculate_entropy(data_bytes)
260
+
261
+ # Step 2: Compress data (with native optimization if available)
262
+ if use_native_optimizations and self.is_native_available():
263
+ compressed_data = self._fast_compression(data_bytes)
264
+ else:
265
+ compressed_data = self.compressor.compress(data_bytes)
266
+
267
+ # Step 3: Generate encryption key with native optimization
268
+ salt = self._generate_salt()
269
+ if use_native_optimizations and self.hash_algorithms:
270
+ key = self._fast_key_derivation(self.password, salt, self.key_manager.iterations, 32)
271
+ else:
272
+ key = self.key_manager.derive_key(self.password, salt, 32)
273
+
274
+ # Step 4: Apply additional XOR obfuscation with native optimization
275
+ if use_native_optimizations and self.crypto_core:
276
+ xor_key = self._fast_hash(key + salt)[:16] # 16-byte XOR key
277
+ obfuscated_data = self._fast_xor_encryption(compressed_data, xor_key)
278
+ else:
279
+ obfuscated_data = compressed_data
280
+
281
+ # Step 5: Encrypt data
282
+ encrypted_data = self.encryptor.encrypt(obfuscated_data, self.password)
283
+
284
+ # Step 6: Apply custom encoding if requested
285
+ if output_format == 'binary':
286
+ return encrypted_data
287
+ elif output_format == 'custom' and self.custom_encoder:
288
+ if use_native_optimizations and self.crypto_core:
289
+ return self._fast_custom_encoding(encrypted_data, self.custom_encoder.charset)
290
+ else:
291
+ return self.custom_encoder.encode(encrypted_data)
292
+ elif output_format == 'steganographic' and self.custom_encoder:
293
+ return self.custom_encoder.create_steganographic_text(encrypted_data)
294
+ else:
295
+ return encrypted_data
296
+
297
+ except Exception as e:
298
+ raise EncrypterError(
299
+ f"Enhanced compression failed: {str(e)}",
300
+ details={
301
+ "operation": "compress_and_encrypt",
302
+ "native_used": use_native_optimizations and self.is_native_available(),
303
+ "error": str(e)
304
+ }
305
+ )
306
+
307
+ def decrypt_and_decompress(self, data: Union[bytes, str],
308
+ input_format: str = 'binary',
309
+ use_native_optimizations: bool = True) -> bytes:
310
+ """
311
+ Decrypt and decompress data with native optimizations.
312
+
313
+ Args:
314
+ data: Encrypted compressed data to decrypt and decompress.
315
+ input_format: Input format ('binary', 'custom', 'steganographic').
316
+ use_native_optimizations: Use native libraries for optimization.
317
+
318
+ Returns:
319
+ bytes: Original decompressed data.
320
+ """
321
+ try:
322
+ # Step 1: Decode from custom format if necessary
323
+ if input_format == 'custom' and self.custom_encoder and isinstance(data, str):
324
+ encrypted_data = self.custom_encoder.decode(data)
325
+ elif input_format == 'binary':
326
+ encrypted_data = data
327
+ else:
328
+ encrypted_data = data
329
+
330
+ # Step 2: Decrypt data
331
+ decrypted_data = self.encryptor.decrypt(encrypted_data, self.password)
332
+
333
+ # Step 3: Remove XOR obfuscation if it was applied
334
+ if use_native_optimizations and self.crypto_core:
335
+ # Try to detect if XOR was applied by checking entropy
336
+ entropy = self._calculate_entropy(decrypted_data)
337
+ if entropy > 7.0: # High entropy suggests XOR was applied
338
+ # Reconstruct XOR key
339
+ salt = encrypted_data[:16] # Assume salt is in first 16 bytes
340
+ key = self._fast_key_derivation(self.password, salt, self.key_manager.iterations, 32)
341
+ xor_key = self._fast_hash(key + salt)[:16]
342
+ deobfuscated_data = self._fast_xor_encryption(decrypted_data, xor_key)
343
+ else:
344
+ deobfuscated_data = decrypted_data
345
+ else:
346
+ deobfuscated_data = decrypted_data
347
+
348
+ # Step 4: Decompress data (with native optimization if available)
349
+ if use_native_optimizations and self.is_native_available():
350
+ decompressed_data = self._fast_decompression(deobfuscated_data)
351
+ else:
352
+ decompressed_data = self.compressor.decompress(deobfuscated_data)
353
+
354
+ return decompressed_data
355
+
356
+ except Exception as e:
357
+ raise EncrypterError(
358
+ f"Enhanced decompression failed: {str(e)}",
359
+ details={
360
+ "operation": "decrypt_and_decompress",
361
+ "native_used": use_native_optimizations and self.is_native_available(),
362
+ "error": str(e)
363
+ }
364
+ )
365
+
366
+ def _generate_salt(self) -> bytes:
367
+ """Generate cryptographically secure salt."""
368
+ if self.crypto_core:
369
+ try:
370
+ return self.crypto_core.secure_random_bytes(16)
371
+ except Exception:
372
+ pass
373
+
374
+ # Fallback to standard random
375
+ import secrets
376
+ return secrets.token_bytes(16)
377
+
378
+ def benchmark_native_vs_python(self, data_size: int = 1024, iterations: int = 100) -> Dict[str, Any]:
379
+ """
380
+ Benchmark native vs Python implementations.
381
+
382
+ Args:
383
+ data_size: Size of test data in bytes.
384
+ iterations: Number of iterations for benchmarking.
385
+
386
+ Returns:
387
+ Dict[str, Any]: Benchmark results.
388
+ """
389
+ import time
390
+ import secrets
391
+
392
+ # Generate test data
393
+ test_data = secrets.token_bytes(data_size)
394
+
395
+ results = {
396
+ 'data_size': data_size,
397
+ 'iterations': iterations,
398
+ 'native_available': self.is_native_available()
399
+ }
400
+
401
+ if not self.is_native_available():
402
+ results['error'] = 'Native libraries not available'
403
+ return results
404
+
405
+ # Benchmark compression
406
+ if self.crypto_core:
407
+ # Native compression
408
+ start_time = time.time()
409
+ for _ in range(iterations):
410
+ compressed = self.crypto_core.fast_compress_rle(test_data)
411
+ native_compress_time = time.time() - start_time
412
+
413
+ # Python compression
414
+ start_time = time.time()
415
+ for _ in range(iterations):
416
+ compressed = self.compressor.compress(test_data)
417
+ python_compress_time = time.time() - start_time
418
+
419
+ results['compression'] = {
420
+ 'native_time': native_compress_time,
421
+ 'python_time': python_compress_time,
422
+ 'speedup': python_compress_time / native_compress_time if native_compress_time > 0 else 0
423
+ }
424
+
425
+ # Benchmark hashing
426
+ if self.hash_algorithms:
427
+ # Native hashing
428
+ start_time = time.time()
429
+ for _ in range(iterations):
430
+ hash_result = self.hash_algorithms.fast_sha256(test_data)
431
+ native_hash_time = time.time() - start_time
432
+
433
+ # Python hashing
434
+ import hashlib
435
+ start_time = time.time()
436
+ for _ in range(iterations):
437
+ hash_result = hashlib.sha256(test_data).digest()
438
+ python_hash_time = time.time() - start_time
439
+
440
+ results['hashing'] = {
441
+ 'native_time': native_hash_time,
442
+ 'python_time': python_hash_time,
443
+ 'speedup': python_hash_time / native_hash_time if native_hash_time > 0 else 0
444
+ }
445
+
446
+ # Benchmark key derivation
447
+ if self.hash_algorithms:
448
+ password = b"test_password"
449
+ salt = b"test_salt_16bytes"
450
+
451
+ # Native PBKDF2
452
+ start_time = time.time()
453
+ for _ in range(10): # Fewer iterations for expensive operation
454
+ key = self.hash_algorithms.fast_pbkdf2(password, salt, 1000, 32)
455
+ native_kdf_time = time.time() - start_time
456
+
457
+ # Python PBKDF2
458
+ start_time = time.time()
459
+ for _ in range(10):
460
+ key = self.key_manager.derive_key("test_password", salt, 32)
461
+ python_kdf_time = time.time() - start_time
462
+
463
+ results['key_derivation'] = {
464
+ 'native_time': native_kdf_time,
465
+ 'python_time': python_kdf_time,
466
+ 'speedup': python_kdf_time / native_kdf_time if native_kdf_time > 0 else 0
467
+ }
468
+
469
+ return results
470
+
471
+ def get_native_info(self) -> Dict[str, Any]:
472
+ """Get information about native library availability and performance."""
473
+ info = {
474
+ 'native_support': NATIVE_SUPPORT,
475
+ 'prefer_native': self.prefer_native,
476
+ 'native_available': self.is_native_available(),
477
+ 'libraries': {}
478
+ }
479
+
480
+ if self.native_manager:
481
+ manager_info = self.native_manager.get_info()
482
+ info.update(manager_info)
483
+
484
+ # Add performance info
485
+ if self.hash_algorithms:
486
+ try:
487
+ perf_time = self.hash_algorithms.benchmark_hash_performance(1024, 100)
488
+ info['hash_performance'] = {
489
+ 'time_seconds': perf_time,
490
+ 'throughput_mbps': (1024 * 100 / (1024 * 1024)) / perf_time if perf_time > 0 else 0
491
+ }
492
+ except Exception as e:
493
+ info['hash_performance'] = {'error': str(e)}
494
+
495
+ return info
496
+
497
+ def get_info(self) -> Dict[str, Any]:
498
+ """Get comprehensive information about the EnhancedCompressor."""
499
+ base_info = {
500
+ 'version': '2.0.0',
501
+ 'type': 'EnhancedCompressor',
502
+ 'configuration': self.config,
503
+ }
504
+
505
+ # Add native library info
506
+ base_info['native'] = self.get_native_info()
507
+
508
+ # Add standard component info
509
+ base_info['compressor_info'] = self.compressor.get_info()
510
+ base_info['encryptor_info'] = self.encryptor.get_info()
511
+ base_info['key_manager_info'] = self.key_manager.get_info()
512
+
513
+ if self.custom_encoder:
514
+ base_info['custom_encoder_info'] = self.custom_encoder.get_charset_info()
515
+
516
+ return base_info
517
+
518
+ def __repr__(self) -> str:
519
+ """String representation of the EnhancedCompressor."""
520
+ native_status = "native" if self.is_native_available() else "python"
521
+ charset_info = f", charset={self.custom_encoder.charset}" if self.custom_encoder else ""
522
+
523
+ return (f"EnhancedCompressor("
524
+ f"compression={self.compressor.algorithm.value}, "
525
+ f"encryption={self.encryptor.algorithm.value}, "
526
+ f"mode={native_status}"
527
+ f"{charset_info})")
528
+
529
+ def __str__(self) -> str:
530
+ """Human-readable string representation."""
531
+ base_str = (f"Enhanced Compressor with {self.compressor.algorithm.value.upper()} compression "
532
+ f"and {self.encryptor.algorithm.value.upper()} encryption")
533
+
534
+ if self.is_native_available():
535
+ base_str += " (native acceleration enabled)"
536
+ else:
537
+ base_str += " (pure Python mode)"
538
+
539
+ if self.custom_encoder:
540
+ base_str += f" using custom charset '{self.custom_encoder.charset}'"
541
+
542
+ return base_str