import 'dart:convert';
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:pointycastle/pointycastle.dart';
|
|
import 'package:uuid/uuid.dart';
|
|
|
|
import '/models/conversations.dart';
|
|
import '/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<String, dynamic> 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<String, dynamic> 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<Map<String, dynamic>> payloadJson(Conversation conversation) async {
|
|
final String messageDataId = (const Uuid()).v4();
|
|
|
|
final symmetricKey = AesHelper.deriveKey(generateRandomString(32));
|
|
|
|
final userSymmetricKey = AesHelper.deriveKey(generateRandomString(32));
|
|
|
|
List<Map<String, String>> messages = await super.payloadJsonBase(
|
|
symmetricKey,
|
|
userSymmetricKey,
|
|
conversation,
|
|
id,
|
|
messageDataId,
|
|
);
|
|
|
|
Map<String, String> 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 <String, dynamic>{
|
|
'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
|
|
''';
|
|
}
|
|
}
|