lum_ccc_rust/flutter_src/ccc/ccc_iso_operation.dart

191 lines
5.5 KiB
Dart

///
/// 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<int> data;
final List<int> cipherSequence;
final Map<String, dynamic> 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<int> plaintext,
required List<int> cipherSequence,
required Map<String, dynamic> 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<int> ciphertext,
required List<int> cipherSequence,
required Map<String, dynamic> 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<String, dynamic> 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<String, dynamic> map) {
return CryptoOperation.withId(
id: map['id'] as String,
data: List<int>.from(map['data'] as List),
cipherSequence: List<int>.from(map['cipherSequence'] as List),
params: Map<String, dynamic>.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;
}