mangayomi/lib/utils/cryptoaes/crypto_aes.dart
2024-12-14 12:38:56 +02:00

85 lines
3 KiB
Dart

import 'dart:convert';
import 'dart:math';
import 'dart:typed_data';
import 'package:crypto/crypto.dart';
import 'package:encrypt/encrypt.dart' as encrypt;
class CryptoAES {
static String encryptAESCryptoJS(String plainText, String passphrase) {
try {
final salt = genRandomWithNonZero(8);
var keyndIV = deriveKeyAndIV(passphrase.trim(), salt);
final key = encrypt.Key(keyndIV.$1);
final iv = encrypt.IV(keyndIV.$2);
final encrypter = encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.cbc, padding: "PKCS7"));
final encrypted = encrypter.encrypt(plainText.trim(), iv: iv);
Uint8List encryptedBytesWithSalt =
Uint8List.fromList(createUint8ListFromString("Salted__") + salt + encrypted.bytes);
return base64.encode(encryptedBytesWithSalt);
} catch (error) {
rethrow;
}
}
static String decryptAESCryptoJS(String encrypted, String passphrase) {
try {
Uint8List encryptedBytesWithSalt = base64.decode(encrypted.trim());
Uint8List encryptedBytes = encryptedBytesWithSalt.sublist(16, encryptedBytesWithSalt.length);
final salt = encryptedBytesWithSalt.sublist(8, 16);
var keyndIV = deriveKeyAndIV(passphrase.trim(), salt);
final key = encrypt.Key(keyndIV.$1);
final iv = encrypt.IV(keyndIV.$2);
final encrypter = encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.cbc, padding: "PKCS7"));
final decrypted = encrypter.decrypt64(base64.encode(encryptedBytes), iv: iv);
return decrypted;
} catch (error) {
rethrow;
}
}
static (Uint8List, Uint8List) deriveKeyAndIV(String passphrase, Uint8List salt) {
var password = createUint8ListFromString(passphrase);
Uint8List concatenatedHashes = Uint8List(0);
Uint8List currentHash = Uint8List(0);
bool enoughBytesForKey = false;
Uint8List preHash = Uint8List(0);
while (!enoughBytesForKey) {
// int preHashLength = currentHash.length + password.length + salt.length;
if (currentHash.isNotEmpty) {
preHash = Uint8List.fromList(currentHash + password + salt);
} else {
preHash = Uint8List.fromList(password + salt);
}
currentHash = md5.convert(preHash).bytes as Uint8List;
concatenatedHashes = Uint8List.fromList(concatenatedHashes + currentHash);
if (concatenatedHashes.length >= 48) enoughBytesForKey = true;
}
var keyBtyes = concatenatedHashes.sublist(0, 32);
var ivBtyes = concatenatedHashes.sublist(32, 48);
return (keyBtyes, ivBtyes);
}
static Uint8List createUint8ListFromString(String s) {
var ret = Uint8List(s.length);
for (var i = 0; i < s.length; i++) {
ret[i] = s.codeUnitAt(i);
}
return ret;
}
static Uint8List genRandomWithNonZero(int seedLength) {
final random = Random.secure();
const int randomMax = 245;
final Uint8List uint8list = Uint8List(seedLength);
for (int i = 0; i < seedLength; i++) {
uint8list[i] = random.nextInt(randomMax) + 1;
}
return uint8list;
}
}