import 'dart:convert'; import 'dart:typed_data'; import 'package:pointycastle/export.dart'; class AesDecrypt { static const String _cn = 'i0.a'; static const List _obf = [ 0xED, 0x7A, 0x7F, 0x3F, 0x9E, 0x6E, 0xE7, 0xF9, 0x06, 0xA0, 0xA8, 0xE4, 0x16, 0xE5, 0x69, 0x70, ]; /// Java String.hashCode() 等价实现(32-bit signed) static int javaStringHashCode(String str) { int h = 0; for (int i = 0; i < str.length; i++) { h = _toSigned32(h * 31 + str.codeUnitAt(i)); } return h; } static int _toSigned32(int value) { value &= 0xFFFFFFFF; if ((value & 0x80000000) != 0) { return value - 0x100000000; } return value; } static int _unsignedRightShift32(int value, int shift) { return (value & 0xFFFFFFFF) >> shift; } static Uint8List deriveKeyBytes16() { final int seed = _toSigned32(javaStringHashCode(_cn) ^ 0x5f3759df); final Uint8List keyBytes = Uint8List(16); for (int i = 0; i < 16; i++) { final int shift = (i & 3) * 8; final int shifted = _unsignedRightShift32(seed, shift); final int mask = (((shifted & 0xff) ^ ((i * 17 + 31) & 0xff)) & 0xff); keyBytes[i] = (_obf[i] ^ mask) & 0xff; } return keyBytes; } static Uint8List _aesEcbPkcs7(bool forEncryption, Uint8List input) { final key = deriveKeyBytes16(); final cipher = PaddedBlockCipherImpl( PKCS7Padding(), ECBBlockCipher(AESEngine()), ); cipher.init( forEncryption, PaddedBlockCipherParameters( KeyParameter(key), null, ), ); return cipher.process(input); } /// 对应 JS / Java encrypt(String) -> Base64.NO_WRAP static String encrypt(String plainText) { try { final Uint8List input = Uint8List.fromList(utf8.encode(plainText)); final Uint8List encrypted = _aesEcbPkcs7(true, input); return base64.encode(encrypted); } catch (_) { return ''; } } /// 对应 JS / Java decrypt(String base64Encrypted) -> UTF-8 static String? decrypt(String base64Encrypted) { try { final Uint8List encrypted = Uint8List.fromList( base64.decode(base64Encrypted), ); final Uint8List decrypted = _aesEcbPkcs7(false, encrypted); final String text = utf8.decode(decrypted, allowMalformed: false); return text.isNotEmpty ? text : null; } catch (_) { return null; } } }