extract method
Future<Uint8List>
extract({
- required Uint8List imageBytes,
- required Uint8List key,
- required SteganographyMethod method,
Implementation
Future<Uint8List> extract({
required Uint8List imageBytes,
required Uint8List key,
required SteganographyMethod method,
}) async {
if (method != SteganographyMethod.telegramRobust2 &&
!isSupportedCarrierImage(imageBytes)) {
throw ArgumentError.value(
imageBytes.length,
'imageBytes',
'Not a PNG or JPEG (invalid signature)',
);
}
Uint8List? packed;
try {
packed = await _native.extractPng(
pngBytes: imageBytes,
method: steganographyMethodToInt(method),
);
} on PlatformException catch (e) {
throw _mapPlatform(e);
}
if (packed == null) {
throw StateError('No steganographic payload found');
}
final encrypted = switch (method) {
SteganographyMethod.telegramRobust2 => StegoPayload.tryUnpackRobust(
packed,
keyBytes: key,
),
SteganographyMethod.dct => StegoPayload.tryUnpackRobust(
packed,
keyBytes: key,
),
SteganographyMethod.dctResidualModulation => StegoPayload.tryUnpackDrm(
packed,
),
_ => StegoPayload.tryUnpack(packed),
};
if (encrypted == null) {
throw StateError('Invalid payload header');
}
try {
return await SteganographyCrypto.decrypt(encrypted, keyBytes: key);
} catch (e) {
final macLike = e.toString().contains('MAC') ||
e.toString().contains('authentication') ||
e.toString().contains('SecretBoxAuthentication');
if (macLike) {
throw StateError(
'AES-GCM MAC mismatch: wrong key or payload corrupted after recompression. '
'Use SteganographyMethod.telegramRobust2 for lossy channels.',
);
}
throw StateError('Decryption failed: $e');
}
}