@ -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
''' ;
}
}
}