/// /// CCC isolate-backed crypto provider for message payloads. /// import 'dart:convert'; import 'package:letusmsg/ccc/ccc_iso_manager.dart'; import 'package:letusmsg/ccc/crypto_abstract.dart'; /// Real crypto provider backed by `CryptoIsolateManager`. /// /// Notes: /// - Requires `context.channelUuid` for channel-scoped operation. /// - Uses JSON map serialization for current message payload format. class CryptoCcc implements CryptoAbstract> { final CryptoIsolateManager _manager; bool _initialized = false; CryptoCcc(this._manager); @override String get providerName => 'CryptoCcc'; @override bool get isPlaintextMode => false; Future _ensureInitialized() async { if (_initialized) return; await _manager.initialize(); _initialized = true; } String _requireChannelUuid(CryptoContext? context) { final channelUuid = context?.channelUuid; if (channelUuid == null || channelUuid.isEmpty) { throw ArgumentError('CryptoCcc requires a non-empty channelUuid in CryptoContext'); } return channelUuid; } @override Future> encrypt(Map input, {CryptoContext? context}) async { await _ensureInitialized(); final channelUuid = _requireChannelUuid(context); final plainBytes = utf8.encode(jsonEncode(input)); final result = await _manager.encrypt( plainBytes, channelUuid: channelUuid, messageSequence: context?.messageSequence, cipherSequence: context?.cipherSequence, params: context?.cipherParams, isUserMessage: context?.isUserMessage ?? false, ); if (!result.success) { throw Exception('CryptoCcc encrypt failed: ${result.error ?? 'unknown error'}'); } return result.data; } @override Future> decrypt(List data, {CryptoContext? context}) async { await _ensureInitialized(); final channelUuid = _requireChannelUuid(context); final result = await _manager.decrypt( data, channelUuid: channelUuid, messageSequence: context?.messageSequence, cipherSequence: context?.cipherSequence, params: context?.cipherParams, ); if (!result.success) { throw Exception('CryptoCcc decrypt failed: ${result.error ?? 'unknown error'}'); } return jsonDecode(utf8.decode(result.data)); } }