import 'dart:convert'; import 'dart:typed_data'; import 'package:pointycastle/pointycastle.dart'; import 'package:uuid/uuid.dart'; import '/database/models/conversations.dart'; import '/database/models/messages.dart'; import '/utils/encryption/aes_helper.dart'; import '/utils/encryption/crypto_utils.dart'; import '/utils/strings.dart'; class TextMessage extends Message { String text; TextMessage({ id, symmetricKey, userSymmetricKey, senderId, senderUsername, associationKey, createdAt, failedToSend, required this.text, }) : super( id: id, symmetricKey: symmetricKey, userSymmetricKey: userSymmetricKey, senderId: senderId, senderUsername: senderUsername, associationKey: associationKey, createdAt: createdAt, failedToSend: failedToSend, ); factory TextMessage.fromJson(Map json, RSAPrivateKey privKey) { var userSymmetricKey = CryptoUtils.rsaDecrypt( base64.decode(json['symmetric_key']), privKey, ); var symmetricKey = AesHelper.aesDecrypt( userSymmetricKey, base64.decode(json['message_data']['symmetric_key']), ); var senderId = AesHelper.aesDecrypt( base64.decode(symmetricKey), base64.decode(json['message_data']['sender_id']), ); var data = AesHelper.aesDecrypt( base64.decode(symmetricKey), base64.decode(json['message_data']['data']), ); return TextMessage( id: json['id'], symmetricKey: symmetricKey, userSymmetricKey: base64.encode(userSymmetricKey), senderId: senderId, senderUsername: 'Unknown', associationKey: json['association_key'], createdAt: json['created_at'], failedToSend: false, text: data, ); } @override Map toMap() { return { 'id': id, 'symmetric_key': symmetricKey, 'user_symmetric_key': userSymmetricKey, 'data': text, 'sender_id': senderId, 'sender_username': senderUsername, 'association_key': associationKey, 'created_at': createdAt, 'failed_to_send': failedToSend ? 1 : 0, }; } Future> payloadJson(Conversation conversation) async { final String messageDataId = (const Uuid()).v4(); final symmetricKey = AesHelper.deriveKey(generateRandomString(32)); final userSymmetricKey = AesHelper.deriveKey(generateRandomString(32)); List> messages = await super.payloadJsonBase( symmetricKey, userSymmetricKey, conversation, id, messageDataId, ); Map messageData = { 'id': messageDataId, 'data': AesHelper.aesEncrypt(symmetricKey, Uint8List.fromList(text.codeUnits)), 'sender_id': AesHelper.aesEncrypt(symmetricKey, Uint8List.fromList(senderId.codeUnits)), 'symmetric_key': AesHelper.aesEncrypt( userSymmetricKey, Uint8List.fromList(base64.encode(symmetricKey).codeUnits), ), }; return { 'message_data': messageData, 'message': messages, }; } @override String getContent() { return text; } @override String toString() { return ''' id: $id data: $text, senderId: $senderId senderUsername: $senderUsername associationKey: $associationKey createdAt: $createdAt '''; } }