Update: 2026-06-16 01:17:28
This commit is contained in:
@@ -35,8 +35,12 @@ class CRUD {
|
||||
String payload = parts[1];
|
||||
// إضافة padding للـ base64
|
||||
switch (payload.length % 4) {
|
||||
case 2: payload += '=='; break;
|
||||
case 3: payload += '='; break;
|
||||
case 2:
|
||||
payload += '==';
|
||||
break;
|
||||
case 3:
|
||||
payload += '=';
|
||||
break;
|
||||
}
|
||||
final decoded = jsonDecode(utf8.decode(base64Url.decode(payload)));
|
||||
final exp = decoded['exp'];
|
||||
@@ -116,7 +120,8 @@ class CRUD {
|
||||
|
||||
http.Response? response;
|
||||
int attempts = 0;
|
||||
final requestId = DateTime.now().millisecondsSinceEpoch.toString().substring(7);
|
||||
final requestId =
|
||||
DateTime.now().millisecondsSinceEpoch.toString().substring(7);
|
||||
|
||||
Log.print('🚀 [REQ-$requestId] $link');
|
||||
if (payload != null) Log.print('📦 [PAYLOAD-$requestId] $payload');
|
||||
@@ -448,10 +453,11 @@ class CRUD {
|
||||
required String prompt,
|
||||
}) async {
|
||||
var url = Uri.parse(link);
|
||||
// API key مشفر ومحمي في api_key.dart عبر X.r() ثلاثي المستوى
|
||||
var apiKey = AK.llamaKey;
|
||||
var headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization':
|
||||
'Bearer LL-X5lJ0Px9CzKK0HTuVZ3u2u4v3tGWkImLTG7okGRk4t25zrsLqJ0qNoUzZ2x4ciPy',
|
||||
'Authorization': 'Bearer $apiKey',
|
||||
};
|
||||
var data = json.encode({
|
||||
'model': 'Llama-3-70b-Inst-FW',
|
||||
@@ -535,7 +541,6 @@ class CRUD {
|
||||
return response.statusCode;
|
||||
}
|
||||
|
||||
|
||||
Future<dynamic> postPayMob(
|
||||
{required String link, Map<String, dynamic>? payload}) async {
|
||||
var url = Uri.parse(link);
|
||||
@@ -699,7 +704,8 @@ class CRUD {
|
||||
if (response.statusCode == 200 || response.statusCode == 201) {
|
||||
return jsonDecode(response.body);
|
||||
}
|
||||
Log.print('MapSaas Post Error: ${response.statusCode} - ${response.body}');
|
||||
Log.print(
|
||||
'MapSaas Post Error: ${response.statusCode} - ${response.body}');
|
||||
return null;
|
||||
} catch (e) {
|
||||
Log.print('MapSaas Post Exception: $e');
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:math';
|
||||
import 'dart:typed_data';
|
||||
import 'package:encrypt/encrypt.dart' as encrypt;
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:secure_string_operations/secure_string_operations.dart';
|
||||
@@ -11,9 +13,13 @@ class EncryptionHelper {
|
||||
static EncryptionHelper? _instance;
|
||||
|
||||
late final encrypt.Key key;
|
||||
late final encrypt.IV iv;
|
||||
late final encrypt.IV iv; // Legacy CBC IV (kept for backward-compat)
|
||||
|
||||
/// Prefix to distinguish new GCM ciphertext from old CBC ciphertext
|
||||
static const String _gcmPrefix = 'GCM:';
|
||||
|
||||
EncryptionHelper._(this.key, this.iv);
|
||||
|
||||
static EncryptionHelper get instance {
|
||||
if (_instance == null) {
|
||||
throw Exception(
|
||||
@@ -26,14 +32,13 @@ class EncryptionHelper {
|
||||
static Future<void> initialize() async {
|
||||
if (_instance != null) {
|
||||
debugPrint("EncryptionHelper is already initialized.");
|
||||
return; // Prevent re-initialization
|
||||
return;
|
||||
}
|
||||
debugPrint("Initializing EncryptionHelper...");
|
||||
var keyOfApp = r(Env.keyOfApp).toString().split(Env.addd)[0];
|
||||
var initializationVector =
|
||||
r(Env.initializationVector).toString().split(Env.addd)[0];
|
||||
|
||||
// Set the global instance
|
||||
_instance = EncryptionHelper._(
|
||||
encrypt.Key.fromUtf8(keyOfApp!),
|
||||
encrypt.IV.fromUtf8(initializationVector!),
|
||||
@@ -41,31 +46,74 @@ class EncryptionHelper {
|
||||
debugPrint("EncryptionHelper initialized successfully.");
|
||||
}
|
||||
|
||||
/// Encrypts a string
|
||||
/// ✅ FIX H-04: Encrypts a string using AES-256-GCM with a random IV
|
||||
/// Format: "GCM:<base64_iv>:<base64_ciphertext>"
|
||||
String encryptData(String plainText) {
|
||||
try {
|
||||
final encrypter =
|
||||
encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.cbc));
|
||||
final encrypted = encrypter.encrypt(plainText, iv: iv);
|
||||
return encrypted.base64;
|
||||
final randomIv = _generateRandomIv(12); // 12-byte nonce recommended for GCM
|
||||
final gcmEncrypter =
|
||||
encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.gcm));
|
||||
final encrypted = gcmEncrypter.encrypt(plainText, iv: randomIv);
|
||||
// Prepend GCM prefix + IV so the server/decoder knows the format
|
||||
return '$_gcmPrefix${randomIv.base64}:${encrypted.base64}';
|
||||
} catch (e) {
|
||||
debugPrint('Encryption Error: $e');
|
||||
return '';
|
||||
debugPrint('GCM Encryption failed, falling back to CBC: $e');
|
||||
// Fallback to CBC for environments that don't support GCM
|
||||
try {
|
||||
final cbcEncrypter =
|
||||
encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.cbc));
|
||||
final encrypted = cbcEncrypter.encrypt(plainText, iv: iv);
|
||||
return encrypted.base64;
|
||||
} catch (e2) {
|
||||
debugPrint('CBC Encryption Error: $e2');
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Decrypts a string
|
||||
/// ✅ FIX H-04: Decrypts a string — supports both GCM (new) and CBC (legacy)
|
||||
String decryptData(String encryptedText) {
|
||||
try {
|
||||
final encrypter =
|
||||
encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.cbc));
|
||||
final encrypted = encrypt.Encrypted.fromBase64(encryptedText);
|
||||
return encrypter.decrypt(encrypted, iv: iv);
|
||||
if (encryptedText.startsWith(_gcmPrefix)) {
|
||||
// New GCM format: "GCM:<iv_b64>:<cipher_b64>"
|
||||
final parts = encryptedText.substring(_gcmPrefix.length).split(':');
|
||||
if (parts.length != 2) {
|
||||
debugPrint('Invalid GCM format, falling back to CBC');
|
||||
return _decryptLegacyCbc(encryptedText);
|
||||
}
|
||||
final gcmIv = encrypt.IV.fromBase64(parts[0]);
|
||||
final gcmEncrypter =
|
||||
encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.gcm));
|
||||
return gcmEncrypter.decrypt(
|
||||
encrypt.Encrypted.fromBase64(parts[1]),
|
||||
iv: gcmIv);
|
||||
}
|
||||
// Legacy CBC format (no prefix)
|
||||
return _decryptLegacyCbc(encryptedText);
|
||||
} catch (e) {
|
||||
debugPrint('Decryption Error: $e');
|
||||
return '';
|
||||
try {
|
||||
return _decryptLegacyCbc(encryptedText);
|
||||
} catch (_) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Legacy CBC decryption (backward compatibility with existing data)
|
||||
String _decryptLegacyCbc(String encryptedText) {
|
||||
final cbcEncrypter =
|
||||
encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.cbc));
|
||||
final encrypted = encrypt.Encrypted.fromBase64(encryptedText);
|
||||
return cbcEncrypter.decrypt(encrypted, iv: iv);
|
||||
}
|
||||
|
||||
/// Generates a cryptographically secure random IV
|
||||
encrypt.IV _generateRandomIv(int length) {
|
||||
final random = Random.secure();
|
||||
final bytes = List<int>.generate(length, (_) => random.nextInt(256));
|
||||
return encrypt.IV(Uint8List.fromList(bytes));
|
||||
}
|
||||
}
|
||||
|
||||
r(String string) {
|
||||
|
||||
Reference in New Issue
Block a user