@ -1,17 +1,48 @@  
														
													
														
															
																import  ' dart:convert ' ; import  ' dart:convert ' ;  
														
													
														
															
																import  ' dart:typed_data ' ; import  ' dart:typed_data ' ;  
														
													
														
															
																import  ' package:Envelope/models/conversation_users.dart ' ;  
														
													
														
															
																import  ' package:Envelope/models/conversations.dart ' ;  
														
													
														
															
																
  
														
													
														
															
																import  ' package:pointycastle/export.dart ' ; import  ' package:pointycastle/export.dart ' ;  
														
													
														
															
																import  ' package:shared_preferences/shared_preferences.dart ' ;  
														
													
														
															
																import  ' /utils/encryption/crypto_utils.dart ' ;  
														
													
														
															
																
  
														
													
														
															
																import  ' /models/conversation_users.dart ' ;  
														
													
														
															
																import  ' /models/conversations.dart ' ;  
														
													
														
															
																import  ' /models/my_profile.dart ' ;  
														
													
														
															
																import  ' /models/friends.dart ' ;  
														
													
														
															
																import  ' /utils/encryption/aes_helper.dart ' ; import  ' /utils/encryption/aes_helper.dart ' ;  
														
													
														
															
																import  ' /utils/encryption/crypto_utils.dart ' ;  
														
													
														
															
																import  ' /utils/storage/database.dart ' ; import  ' /utils/storage/database.dart ' ;  
														
													
														
															
																import  ' /utils/strings.dart ' ; import  ' /utils/strings.dart ' ;  
														
													
														
															
																import  ' /models/friends.dart ' ;  
														
													
														
															
																
 
  
														
													
														
															
																const  messageTypeSender  =  ' sender ' ;  
														
													
														
															
																const  messageTypeReceiver  =  ' receiver ' ; const  messageTypeReceiver  =  ' receiver ' ;  
														
													
														
															
																const  messageTypeSender  =  ' sender ' ;  
														
													
														
															
																
  
														
													
														
															
																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 ,   
														
													
														
															
																    ) ;   
														
													
														
															
																  } ) ;   
														
													
														
															
																
  
														
													
														
															
																}  
														
													
														
															
																
 
  
														
													
														
															
																class  Message  { class  Message  {  
														
													
														
															
																  String  id ;    String  id ;   
														
													
												
													
														
															
																
																	
																		
																			 
																	
																	
																		
																			 
																	
																	
																 
																@ -38,109 +69,99 @@ class Message {  
														
													
														
															
																
 
  
														
													
														
															
																  factory  Message . fromJson ( Map < String ,  dynamic >  json ,  RSAPrivateKey  privKey )  {    factory  Message . fromJson ( Map < String ,  dynamic >  json ,  RSAPrivateKey  privKey )  {   
														
													
														
															
																    var  userSymmetricKey  =  CryptoUtils . rsaDecrypt (      var  userSymmetricKey  =  CryptoUtils . rsaDecrypt (   
														
													
														
															
																         base64 . decode ( json [ ' symmetric_key ' ] ) ,   
														
													
														
															
																         privKey ,   
														
													
														
															
																      base64 . decode ( json [ ' symmetric_key ' ] ) ,   
														
													
														
															
																      privKey ,   
														
													
														
															
																    ) ;      ) ;   
														
													
														
															
																
 
  
														
													
														
															
																    var  symmetricKey  =  AesHelper . aesDecrypt (      var  symmetricKey  =  AesHelper . aesDecrypt (   
														
													
														
															
																         userSymmetricKey ,   
														
													
														
															
																         base64 . decode ( json [ ' message_data ' ] [ ' symmetric_key ' ] ) ,   
														
													
														
															
																      userSymmetricKey ,   
														
													
														
															
																      base64 . decode ( json [ ' message_data ' ] [ ' symmetric_key ' ] ) ,   
														
													
														
															
																    ) ;      ) ;   
														
													
														
															
																
 
  
														
													
														
															
																    var  senderId  =  AesHelper . aesDecrypt (      var  senderId  =  AesHelper . aesDecrypt (   
														
													
														
															
																         base64 . decode ( symmetricKey ) ,   
														
													
														
															
																         base64 . decode ( json [ ' message_data ' ] [ ' sender_id ' ] ) ,   
														
													
														
															
																      base64 . decode ( symmetricKey ) ,   
														
													
														
															
																      base64 . decode ( json [ ' message_data ' ] [ ' sender_id ' ] ) ,   
														
													
														
															
																    ) ;      ) ;   
														
													
														
															
																
 
  
														
													
														
															
																    var  data  =  AesHelper . aesDecrypt (      var  data  =  AesHelper . aesDecrypt (   
														
													
														
															
																         base64 . decode ( symmetricKey ) ,   
														
													
														
															
																         base64 . decode ( json [ ' message_data ' ] [ ' data ' ] ) ,   
														
													
														
															
																      base64 . decode ( symmetricKey ) ,   
														
													
														
															
																      base64 . decode ( json [ ' message_data ' ] [ ' data ' ] ) ,   
														
													
														
															
																    ) ;      ) ;   
														
													
														
															
																
 
  
														
													
														
															
																    return  Message (      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 ,   
														
													
														
															
																      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  {    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 ,   
														
													
														
															
																          } ) ;   
														
													
														
															
																      }   
														
													
														
															
																    MyProfile  profile  =  await  MyProfile . getProfile ( ) ;   
														
													
														
															
																    if  ( profile . publicKey  = =  null )  {   
														
													
														
															
																      throw  Exception ( ' Could not get profile.publicKey ' ) ;   
														
													
														
															
																    }   
														
													
														
															
																    RSAPublicKey  publicKey  =  profile . publicKey ! ;   
														
													
														
															
																
  
														
													
														
															
																    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 ) ;   
														
													
														
															
																
 
  
														
													
														
															
																      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 (   
														
													
														
															
																    for  ( var  i  =  0 ;  i  <  conversationUsers . length ;  i + + )  {   
														
													
														
															
																      ConversationUser  user  =  conversationUsers [ i ] ;   
														
													
														
															
																
  
														
													
														
															
																      if  ( profile . id  = =  user . userId )  {   
														
													
														
															
																        id  =  user . id ;   
														
													
														
															
																
  
														
													
														
															
																        messages . add ( {   
														
													
														
															
																          ' message_data_id ' :  messageDataId ,   
														
													
														
															
																          ' symmetric_key ' :  base64 . encode ( CryptoUtils . rsaEncrypt (   
														
													
														
															
																            userSymmetricKey ,              userSymmetricKey ,   
														
													
														
															
																            Uint8List . fromList ( base64 . encode ( symmetricKey ) . codeUnits ) ,   
														
													
														
															
																        ) ,   
														
													
														
															
																      } ;   
														
													
														
															
																            publicKey ,   
														
													
														
															
																          ) ) ,   
														
													
														
															
																          ' association_key ' :  user . associationKey ,   
														
													
														
															
																        } ) ;   
														
													
														
															
																
 
  
														
													
														
															
																      return  jsonEncode ( < String ,  dynamic > {   
														
													
														
															
																        ' message_data ' :  messageData ,   
														
													
														
															
																        ' message ' :  messages ,   
														
													
														
															
																      } ) ;   
														
													
														
															
																  }   
														
													
														
															
																        continue ;   
														
													
														
															
																      }   
														
													
														
															
																
 
  
														
													
														
															
																  @ override   
														
													
														
															
																  String  toString ( )  {   
														
													
														
															
																    return  '''   
														
													
														
															
																      Friend  friend  =  await  getFriendByFriendId ( user . userId ) ;   
														
													
														
															
																      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 ( senderId . codeUnits ) ) ,   
														
													
														
															
																      ' symmetric_key ' :  AesHelper . aesEncrypt (   
														
													
														
															
																        userSymmetricKey ,   
														
													
														
															
																        Uint8List . fromList ( base64 . encode ( symmetricKey ) . codeUnits ) ,   
														
													
														
															
																      ) ,   
														
													
														
															
																    } ;   
														
													
														
															
																
 
  
														
													
														
															
																        id:  $id   
														
													
														
															
																        data:  $data   
														
													
														
															
																        senderId:  $senderId   
														
													
														
															
																        senderUsername:  $senderUsername   
														
													
														
															
																        associationKey:  $associationKey   
														
													
														
															
																        createdAt:  $createdAt   
														
													
														
															
																''' ;  
														
													
														
															
																    return  jsonEncode ( < String ,  dynamic > {   
														
													
														
															
																      ' message_data ' :  messageData ,   
														
													
														
															
																      ' message ' :  messages ,   
														
													
														
															
																    } ) ;   
														
													
														
															
																  }    }   
														
													
														
															
																
 
  
														
													
														
															
																  Map < String ,  dynamic >  toMap ( )  {    Map < String ,  dynamic >  toMap ( )  {   
														
													
												
													
														
															
																
																	
																	
																	
																		
																			 
																	
																 
																@ -157,33 +178,18 @@ class Message {  
														
													
														
															
																    } ;      } ;   
														
													
														
															
																  }    }   
														
													
														
															
																
 
  
														
													
														
															
																}  
														
													
														
															
																
  
														
													
														
															
																Future < List < Message > >  getMessagesForThread ( Conversation  conversation )  async  {  
														
													
														
															
																  final  db  =  await  getDatabaseConnection ( ) ;   
														
													
														
															
																  @ override   
														
													
														
															
																  String  toString ( )  {   
														
													
														
															
																    return  '''   
														
													
														
															
																
 
  
														
													
														
															
																  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 ,   
														
													
														
															
																    ) ;   
														
													
														
															
																  } ) ;   
														
													
														
															
																      id:  $id   
														
													
														
															
																      data:  $data   
														
													
														
															
																      senderId:  $senderId   
														
													
														
															
																      senderUsername:  $senderUsername   
														
													
														
															
																      associationKey:  $associationKey   
														
													
														
															
																      createdAt:  $createdAt   
														
													
														
															
																      ''' ;   
														
													
														
															
																  }   
														
													
														
															
																
 
  
														
													
														
															
																} }