Encrypted messaging app
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

151 lines
4.1 KiB

  1. import 'dart:convert';
  2. import 'dart:io';
  3. import 'dart:typed_data';
  4. import 'package:pointycastle/pointycastle.dart';
  5. import 'package:uuid/uuid.dart';
  6. import '/models/image_message.dart';
  7. import '/models/conversation_users.dart';
  8. import '/models/my_profile.dart';
  9. import '/models/text_messages.dart';
  10. import '/models/conversations.dart';
  11. import '/utils/encryption/crypto_utils.dart';
  12. import '/utils/storage/database.dart';
  13. const messageTypeReceiver = 'receiver';
  14. const messageTypeSender = 'sender';
  15. Future<List<Message>> getMessagesForThread(Conversation conversation) async {
  16. final db = await getDatabaseConnection();
  17. final List<Map<String, dynamic>> maps = await db.rawQuery(
  18. '''
  19. SELECT * FROM messages WHERE association_key IN (
  20. SELECT association_key FROM conversation_users WHERE conversation_id = ?
  21. )
  22. ORDER BY created_at DESC;
  23. ''',
  24. [conversation.id]
  25. );
  26. return List.generate(maps.length, (i) {
  27. if (maps[i]['data'] == null) {
  28. File file = File(maps[i]['file']);
  29. return ImageMessage(
  30. id: maps[i]['id'],
  31. symmetricKey: maps[i]['symmetric_key'],
  32. userSymmetricKey: maps[i]['user_symmetric_key'],
  33. file: file,
  34. senderId: maps[i]['sender_id'],
  35. senderUsername: maps[i]['sender_username'],
  36. associationKey: maps[i]['association_key'],
  37. createdAt: maps[i]['created_at'],
  38. failedToSend: maps[i]['failed_to_send'] == 1,
  39. );
  40. }
  41. return TextMessage(
  42. id: maps[i]['id'],
  43. symmetricKey: maps[i]['symmetric_key'],
  44. userSymmetricKey: maps[i]['user_symmetric_key'],
  45. text: maps[i]['data'],
  46. senderId: maps[i]['sender_id'],
  47. senderUsername: maps[i]['sender_username'],
  48. associationKey: maps[i]['association_key'],
  49. createdAt: maps[i]['created_at'],
  50. failedToSend: maps[i]['failed_to_send'] == 1,
  51. );
  52. });
  53. }
  54. class Message {
  55. String id;
  56. String symmetricKey;
  57. String userSymmetricKey;
  58. String senderId;
  59. String senderUsername;
  60. String associationKey;
  61. String createdAt;
  62. bool failedToSend;
  63. Message({
  64. required this.id,
  65. required this.symmetricKey,
  66. required this.userSymmetricKey,
  67. required this.senderId,
  68. required this.senderUsername,
  69. required this.associationKey,
  70. required this.createdAt,
  71. required this.failedToSend,
  72. });
  73. Future<List<Map<String, String>>> payloadJsonBase(
  74. Uint8List symmetricKey,
  75. Uint8List userSymmetricKey,
  76. Conversation conversation,
  77. String messageId,
  78. String messageDataId,
  79. ) async {
  80. MyProfile profile = await MyProfile.getProfile();
  81. if (profile.publicKey == null) {
  82. throw Exception('Could not get profile.publicKey');
  83. }
  84. RSAPublicKey publicKey = profile.publicKey!;
  85. List<Map<String, String>> messages = [];
  86. List<ConversationUser> conversationUsers = await getConversationUsers(conversation);
  87. for (var i = 0; i < conversationUsers.length; i++) {
  88. ConversationUser user = conversationUsers[i];
  89. if (profile.id == user.userId) {
  90. messages.add({
  91. 'id': messageId,
  92. 'message_data_id': messageDataId,
  93. 'symmetric_key': base64.encode(CryptoUtils.rsaEncrypt(
  94. userSymmetricKey,
  95. publicKey,
  96. )),
  97. 'association_key': user.associationKey,
  98. });
  99. continue;
  100. }
  101. ConversationUser conversationUser = await getConversationUser(conversation, user.userId);
  102. RSAPublicKey friendPublicKey = conversationUser.publicKey;
  103. messages.add({
  104. 'message_data_id': messageDataId,
  105. 'symmetric_key': base64.encode(CryptoUtils.rsaEncrypt(
  106. userSymmetricKey,
  107. friendPublicKey,
  108. )),
  109. 'association_key': user.associationKey,
  110. });
  111. }
  112. return messages;
  113. }
  114. String getContent() {
  115. return '';
  116. }
  117. Map<String, dynamic> toMap() {
  118. return {
  119. 'id': id,
  120. 'symmetric_key': symmetricKey,
  121. 'user_symmetric_key': userSymmetricKey,
  122. 'sender_id': senderId,
  123. 'sender_username': senderUsername,
  124. 'association_key': associationKey,
  125. 'created_at': createdAt,
  126. 'failed_to_send': failedToSend ? 1 : 0,
  127. };
  128. }
  129. }