import 'dart:async'; import 'dart:convert'; import 'dart:typed_data'; import 'dart:math'; class SkyEncrypt { static const int bfSize = 2048; static const String enStrTag = r'$'; // Generates a random salt of size between 16 and 64 bytes static Uint8List randSalt() { final rand = Random.secure(); final size = rand.nextInt(49) + 16; // 16..64 return Uint8List.fromList(List.generate(size, (_) => rand.nextInt(256))); } // Encrypts the given data with a random salt static Uint8List en(Uint8List data) { if (data.isEmpty) return data; final salt = randSalt(); final encryptedData = enWithSalt(data, salt); return Uint8List.fromList([salt.length, ...salt, ...encryptedData]); } // Decrypts the given encrypted data static Uint8List de(Uint8List data) { if (data.isEmpty) return data; final saltLen = data[0]; final salt = data.sublist(1, 1 + saltLen); final encrypted = data.sublist(1 + saltLen); return deWithSalt(encrypted, salt); } // Encrypts data with a specified salt static Uint8List enWithSalt(Uint8List data, Uint8List salt) { final mixedData = mixSalt(data, salt); return cxEd(mixedData); } // Decrypts data with a specified salt static Uint8List deWithSalt(Uint8List data, Uint8List salt) { final decryptedData = cxEd(data); return removeSalt(decryptedData, salt); } // Simple XOR-based encryption/decryption (bitwise negation) static Uint8List cxEd(Uint8List data) { return Uint8List.fromList(data.map((b) => b ^ 0xFF).toList()); } // Apply salt to the data for encryption static Uint8List mixSalt(Uint8List data, Uint8List salt) { if (salt.isEmpty) return data; return Uint8List.fromList( List.generate(data.length, (i) { final s = salt[i % salt.length]; return calSalt(data[i], s); }), ); } // Remove salt from the data after decryption static Uint8List removeSalt(Uint8List data, Uint8List salt) { if (salt.isEmpty) return data; return Uint8List.fromList( List.generate(data.length, (i) { final s = salt[i % salt.length]; return calRemoveSalt(data[i], s); }), ); } // Calculate a modified value after mixing salt (for encryption) static int calSalt(int v, int s) { final r = v ^ 0xFF; return s > r ? (s - r - 1) & 0xFF : (v + s) & 0xFF; } // Reverse the salt mixing process for decryption static int calRemoveSalt(int v, int s) { return v >= s ? (v - s) & 0xFF : (0xFF - (s - v) + 1) & 0xFF; } // Encrypt a string and return the hex representation static String cxEStr(String data) { return cxEStrAsBytes( data, ).map((b) => b.toRadixString(16).padLeft(2, '0')).join(); } // Encrypt string and return as bytes static Uint8List cxEStrAsBytes(String data) { return cxEd(Uint8List.fromList(utf8.encode(data))); } // Decrypt a hex string to a regular string static String cxDStr(String data) { final bytes = Uint8List.fromList([ for (int i = 0; i < data.length; i += 2) int.parse(data.substring(i, i + 2), radix: 16), ]); return utf8.decode(cxEd(bytes)); } // Encrypt string data and return in the form of hex string with prefix static String enStr(String data) { return enBytesStr(Uint8List.fromList(utf8.encode(data))); } // Encrypt bytes and return as hex string with prefix static String enBytesStr(Uint8List data) { final encrypted = en(data); return '$enStrTag${encrypted.map((b) => b.toRadixString(16).padLeft(2, '0')).join()}'; } // Decrypt a string with encoded prefix (e.g., "$" symbol) static String deStr(String data) { return utf8.decode(deStrBytes(data)); } // Decrypt the byte array extracted from a string static Uint8List deStrBytes(String data) { if (!data.startsWith(enStrTag)) { throw ArgumentError("Invalid encoded string"); } final hexData = data.substring(1); final bytes = Uint8List.fromList([ for (int i = 0; i < hexData.length; i += 2) int.parse(hexData.substring(i, i + 2), radix: 16), ]); return de(bytes); } // Copy encrypted data from a stream to another stream static Future copy( Stream> reader, StreamSink> writer, ) async { int total = 0; await for (final chunk in reader) { total += chunk.length; final encrypted = chunk.map((b) => b ^ 0xFF).toList(); writer.add(encrypted); } await writer.close(); return total; } // Custom encryption with condition (even and odd byte values handled differently) static Uint8List cxEd1(Uint8List data) { return Uint8List.fromList( data.map((b) => (b % 2 == 1) ? (b ^ 0xFF) : b).toList(), ); } }