|
|
- import 'dart:convert';
- import 'dart:typed_data';
- import 'package:Envelope/models/conversation_users.dart';
- import 'package:Envelope/models/conversations.dart';
- import 'package:pointycastle/export.dart';
- import 'package:shared_preferences/shared_preferences.dart';
- import '/utils/encryption/crypto_utils.dart';
- import '/utils/encryption/aes_helper.dart';
- import '/utils/storage/database.dart';
- import '/utils/strings.dart';
- import '/models/friends.dart';
-
- const messageTypeSender = 'sender';
- const messageTypeReceiver = 'receiver';
-
- class Message {
- String id;
- String symmetricKey;
- String userSymmetricKey;
- String data;
- String senderId;
- String senderUsername;
- String associationKey;
- String createdAt;
- bool failedToSend;
- Message({
- required this.id,
- required this.symmetricKey,
- required this.userSymmetricKey,
- required this.data,
- required this.senderId,
- required this.senderUsername,
- required this.associationKey,
- required this.createdAt,
- required this.failedToSend,
- });
-
-
- factory Message.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 Message(
- id: json['id'],
- symmetricKey: symmetricKey,
- userSymmetricKey: base64.encode(userSymmetricKey),
- data: data,
- senderId: senderId,
- senderUsername: 'Unknown',
- associationKey: json['association_key'],
- createdAt: json['created_at'],
- failedToSend: false,
- );
- }
-
- Future<String> toJson(Conversation conversation, String messageDataId) async {
- final preferences = await SharedPreferences.getInstance();
- RSAPublicKey publicKey = CryptoUtils.rsaPublicKeyFromPem(preferences.getString('asymmetricPublicKey')!);
-
- final userSymmetricKey = AesHelper.deriveKey(generateRandomString(32));
- final symmetricKey = AesHelper.deriveKey(generateRandomString(32));
-
- List<Map<String, String>> messages = [];
-
- String id = '';
-
- List<ConversationUser> conversationUsers = await getConversationUsers(conversation);
-
- for (var i = 0; i < conversationUsers.length; i++) {
- ConversationUser user = conversationUsers[i];
- if (preferences.getString('username') == user.username) {
- id = user.id;
-
- messages.add({
- 'message_data_id': messageDataId,
- 'symmetric_key': base64.encode(CryptoUtils.rsaEncrypt(
- userSymmetricKey,
- publicKey,
- )),
- 'association_key': user.associationKey,
- });
-
- continue;
- }
-
- Friend friend = await getFriendByFriendId(user.id);
- RSAPublicKey friendPublicKey = CryptoUtils.rsaPublicKeyFromPem(friend.asymmetricPublicKey);
-
- messages.add({
- 'message_data_id': messageDataId,
- 'symmetric_key': base64.encode(CryptoUtils.rsaEncrypt(
- userSymmetricKey,
- friendPublicKey,
- )),
- 'association_key': user.associationKey,
- });
- }
-
- Map<String, String> messageData = {
- 'id': messageDataId,
- 'data': AesHelper.aesEncrypt(symmetricKey, Uint8List.fromList(data.codeUnits)),
- 'sender_id': AesHelper.aesEncrypt(symmetricKey, Uint8List.fromList(id.codeUnits)),
- 'symmetric_key': AesHelper.aesEncrypt(
- userSymmetricKey,
- Uint8List.fromList(base64.encode(symmetricKey).codeUnits),
- ),
- };
-
- return jsonEncode(<String, dynamic>{
- 'message_data': messageData,
- 'message': messages,
- });
- }
-
- @override
- String toString() {
- return '''
-
-
- id: $id
- data: $data
- senderId: $senderId
- senderUsername: $senderUsername
- associationKey: $associationKey
- createdAt: $createdAt
- ''';
- }
-
- Map<String, dynamic> toMap() {
- return {
- 'id': id,
- 'symmetric_key': symmetricKey,
- 'user_symmetric_key': userSymmetricKey,
- 'data': data,
- 'sender_id': senderId,
- 'sender_username': senderUsername,
- 'association_key': associationKey,
- 'created_at': createdAt,
- 'failed_to_send': failedToSend ? 1 : 0,
- };
- }
-
- }
-
- Future<List<Message>> getMessagesForThread(Conversation conversation) async {
- final db = await getDatabaseConnection();
-
- final List<Map<String, dynamic>> maps = await db.rawQuery(
- '''
- SELECT * FROM messages WHERE association_key IN (
- SELECT association_key FROM conversation_users WHERE conversation_id = ?
- )
- ORDER BY created_at DESC;
- ''',
- [conversation.id]
- );
-
- return List.generate(maps.length, (i) {
- return Message(
- id: maps[i]['id'],
- symmetricKey: maps[i]['symmetric_key'],
- userSymmetricKey: maps[i]['user_symmetric_key'],
- data: maps[i]['data'],
- senderId: maps[i]['sender_id'],
- senderUsername: maps[i]['sender_username'],
- associationKey: maps[i]['association_key'],
- createdAt: maps[i]['created_at'],
- failedToSend: maps[i]['failed_to_send'] == 1,
- );
- });
-
- }
|