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.

131 lines
3.2 KiB

  1. import 'dart:convert';
  2. import 'dart:typed_data';
  3. import 'package:pointycastle/pointycastle.dart';
  4. import 'package:uuid/uuid.dart';
  5. import '/models/conversations.dart';
  6. import '/models/messages.dart';
  7. import '/utils/encryption/aes_helper.dart';
  8. import '/utils/encryption/crypto_utils.dart';
  9. import '/utils/strings.dart';
  10. class ImageMessage extends Message {
  11. String text;
  12. ImageMessage({
  13. id,
  14. symmetricKey,
  15. userSymmetricKey,
  16. senderId,
  17. senderUsername,
  18. associationKey,
  19. createdAt,
  20. failedToSend,
  21. required this.text,
  22. }) : super(
  23. id: id,
  24. symmetricKey: symmetricKey,
  25. userSymmetricKey: userSymmetricKey,
  26. senderId: senderId,
  27. senderUsername: senderUsername,
  28. associationKey: associationKey,
  29. createdAt: createdAt,
  30. failedToSend: failedToSend,
  31. );
  32. factory ImageMessage.fromJson(Map<String, dynamic> json, RSAPrivateKey privKey) {
  33. var userSymmetricKey = CryptoUtils.rsaDecrypt(
  34. base64.decode(json['symmetric_key']),
  35. privKey,
  36. );
  37. var symmetricKey = AesHelper.aesDecrypt(
  38. userSymmetricKey,
  39. base64.decode(json['message_data']['symmetric_key']),
  40. );
  41. var senderId = AesHelper.aesDecrypt(
  42. base64.decode(symmetricKey),
  43. base64.decode(json['message_data']['sender_id']),
  44. );
  45. var data = AesHelper.aesDecrypt(
  46. base64.decode(symmetricKey),
  47. base64.decode(json['message_data']['data']),
  48. );
  49. return ImageMessage(
  50. id: json['id'],
  51. symmetricKey: symmetricKey,
  52. userSymmetricKey: base64.encode(userSymmetricKey),
  53. senderId: senderId,
  54. senderUsername: 'Unknown',
  55. associationKey: json['association_key'],
  56. createdAt: json['created_at'],
  57. failedToSend: false,
  58. text: data,
  59. );
  60. }
  61. Map<String, dynamic> toMap() {
  62. return {
  63. 'id': id,
  64. 'symmetric_key': symmetricKey,
  65. 'user_symmetric_key': userSymmetricKey,
  66. 'data': text,
  67. 'sender_id': senderId,
  68. 'sender_username': senderUsername,
  69. 'association_key': associationKey,
  70. 'created_at': createdAt,
  71. 'failed_to_send': failedToSend ? 1 : 0,
  72. };
  73. }
  74. Future<Map<String, dynamic>> payloadJson(Conversation conversation, String messageId) async {
  75. final String messageDataId = (const Uuid()).v4();
  76. final symmetricKey = AesHelper.deriveKey(generateRandomString(32));
  77. List<Map<String, String>> messages = await super.payloadJsonBase(
  78. symmetricKey,
  79. conversation,
  80. messageId,
  81. messageDataId,
  82. );
  83. Map<String, String> messageData = {
  84. 'id': messageDataId,
  85. 'data': AesHelper.aesEncrypt(symmetricKey, Uint8List.fromList(text.codeUnits)),
  86. 'sender_id': AesHelper.aesEncrypt(symmetricKey, Uint8List.fromList(senderId.codeUnits)),
  87. 'symmetric_key': AesHelper.aesEncrypt(
  88. userSymmetricKey,
  89. Uint8List.fromList(base64.encode(symmetricKey).codeUnits),
  90. ),
  91. };
  92. return <String, dynamic>{
  93. 'message_data': messageData,
  94. 'message': messages,
  95. };
  96. }
  97. @override
  98. String getContent() {
  99. return 'Image';
  100. }
  101. @override
  102. String toString() {
  103. return '''
  104. id: $id
  105. data: $text,
  106. senderId: $senderId
  107. senderUsername: $senderUsername
  108. associationKey: $associationKey
  109. createdAt: $createdAt
  110. ''';
  111. }
  112. }