/// /// Data structure for crypto operations in isolates /// Handles serialization for isolate communication /// import 'package:worker_manager/worker_manager.dart'; import 'ccc_iso_operation_id.dart'; import 'cipher_constants.dart'; /// Type of cryptographic operation enum OperationType { encrypt, decrypt; @override String toString() => name; static OperationType fromString(String value) { return OperationType.values.firstWhere( (type) => type.name == value, orElse: () => throw ArgumentError('Invalid OperationType: $value'), ); } } /// Cryptographic operation data for isolate workers /// /// Key derivation (future ratchet implementation): /// - channelUuid: Scope for key derivation (each channel has unique root key) /// - messageSequence: Per-message key derivation index /// - Final key = ratchet(channelRootKey, messageSequence) /// /// Same derived key encrypts: MsgData + attachment files + thumbnails class CryptoOperation { final String id; final List data; final List cipherSequence; final Map params; final OperationType type; final WorkPriority priority; final String channelUuid; // Channel UUID for key derivation scope final int? messageSequence; // Future: ratchet index for per-message key final DateTime timestamp; /// Create new crypto operation with auto-generated ID CryptoOperation({ required this.data, required this.cipherSequence, required this.params, required this.type, required this.channelUuid, this.messageSequence, this.priority = WorkPriority.high, }) : id = CryptoOperationId.generate(), timestamp = DateTime.now(); /// Create crypto operation with custom ID (for testing) CryptoOperation.withId({ required this.id, required this.data, required this.cipherSequence, required this.params, required this.type, required this.channelUuid, this.messageSequence, this.priority = WorkPriority.high, }) : timestamp = DateTime.now(); /// Create operation for encryption factory CryptoOperation.encrypt({ required List plaintext, required List cipherSequence, required Map params, required String channelUuid, int? messageSequence, bool isUserMessage = false, }) { return CryptoOperation( data: plaintext, cipherSequence: cipherSequence, params: params, type: OperationType.encrypt, channelUuid: channelUuid, messageSequence: messageSequence, priority: isUserMessage ? WorkPriority.immediately : WorkPriority.high, ); } /// Create operation for decryption factory CryptoOperation.decrypt({ required List ciphertext, required List cipherSequence, required Map params, required String channelUuid, int? messageSequence, }) { return CryptoOperation( data: ciphertext, cipherSequence: cipherSequence, params: params, type: OperationType.decrypt, channelUuid: channelUuid, messageSequence: messageSequence, priority: WorkPriority.high, ); } /// Serialize for isolate communication Map toMap() { return { 'id': id, 'data': data, 'cipherSequence': cipherSequence, 'params': params, 'type': type.name, 'priority': priority.index, 'channelUuid': channelUuid, 'messageSequence': messageSequence, 'timestamp': timestamp.millisecondsSinceEpoch, }; } /// Deserialize from isolate communication static CryptoOperation fromMap(Map map) { return CryptoOperation.withId( id: map['id'] as String, data: List.from(map['data'] as List), cipherSequence: List.from(map['cipherSequence'] as List), params: Map.from(map['params'] as Map), type: OperationType.fromString(map['type'] as String), channelUuid: map['channelUuid'] as String, messageSequence: map['messageSequence'] as int?, priority: WorkPriority.values[map['priority'] as int], ); } /// Get cipher sequence as human-readable string String get cipherSequenceDescription { return CipherConstants.getSequenceDescription(cipherSequence); } /// Validate cipher sequence bool get hasValidCipherSequence { return CipherConstants.isValidSequence(cipherSequence); } /// Get data size in bytes int get dataSize => data.length; /// Get operation age Duration get age => DateTime.now().difference(timestamp); /// Check if operation is high priority bool get isHighPriority => priority == WorkPriority.immediately; /// Copy with new priority CryptoOperation copyWithPriority(WorkPriority newPriority) { return CryptoOperation.withId( id: id, data: data, cipherSequence: cipherSequence, params: params, type: type, channelUuid: channelUuid, messageSequence: messageSequence, priority: newPriority, ); } @override String toString() { return 'CryptoOperation(' 'id: $id, ' 'type: $type, ' 'dataSize: ${dataSize}B, ' 'ciphers: ${cipherSequence.length}, ' 'priority: $priority, ' 'channel: $channelUuid' ')'; } @override bool operator ==(Object other) => identical(this, other) || other is CryptoOperation && runtimeType == other.runtimeType && id == other.id; @override int get hashCode => id.hashCode; }