import 'dart:convert'; import 'dart:typed_data'; import 'package:pointycastle/export.dart'; import '/utils/encryption/aes_helper.dart'; import '/utils/encryption/crypto_utils.dart'; import '/utils/storage/database.dart'; Friend findFriendByFriendId(List friends, String id) { for (var friend in friends) { if (friend.friendId == id) { return friend; } } // Or return `null`. throw ArgumentError.value(id, 'id', 'No element with that id'); } Future getFriendByFriendId(String userId) async { final db = await getDatabaseConnection(); final List> maps = await db.query( 'friends', where: 'friend_id = ?', whereArgs: [userId], ); if (maps.length != 1) { throw ArgumentError('Invalid user id'); } return Friend( id: maps[0]['id'], userId: maps[0]['user_id'], friendId: maps[0]['friend_id'], friendSymmetricKey: maps[0]['symmetric_key'], publicKey: CryptoUtils.rsaPublicKeyFromPem(maps[0]['asymmetric_public_key']), acceptedAt: maps[0]['accepted_at'] != null ? DateTime.parse(maps[0]['accepted_at']) : null, username: maps[0]['username'], ); } Future> getFriends({bool? accepted}) async { final db = await getDatabaseConnection(); String? where; if (accepted == true) { where = 'accepted_at IS NOT NULL'; } if (accepted == false) { where = 'accepted_at IS NULL'; } final List> maps = await db.query( 'friends', where: where, ); return List.generate(maps.length, (i) { return Friend( id: maps[i]['id'], userId: maps[i]['user_id'], friendId: maps[i]['friend_id'], friendSymmetricKey: maps[i]['symmetric_key'], publicKey: CryptoUtils.rsaPublicKeyFromPem(maps[i]['asymmetric_public_key']), acceptedAt: maps[i]['accepted_at'] != null ? DateTime.parse(maps[i]['accepted_at']) : null, username: maps[i]['username'], ); }); } class Friend{ String id; String userId; String username; String friendId; String friendSymmetricKey; RSAPublicKey publicKey; DateTime? acceptedAt; bool? selected; Friend({ required this.id, required this.userId, required this.username, required this.friendId, required this.friendSymmetricKey, required this.publicKey, required this.acceptedAt, this.selected, }); factory Friend.fromJson(Map json, RSAPrivateKey privKey) { Uint8List idDecrypted = CryptoUtils.rsaDecrypt( base64.decode(json['friend_id']), privKey, ); Uint8List username = CryptoUtils.rsaDecrypt( base64.decode(json['friend_username']), privKey, ); Uint8List symmetricKeyDecrypted = CryptoUtils.rsaDecrypt( base64.decode(json['symmetric_key']), privKey, ); String publicKeyString = AesHelper.aesDecrypt( symmetricKeyDecrypted, base64.decode(json['asymmetric_public_key']) ); RSAPublicKey publicKey = CryptoUtils.rsaPublicKeyFromPem(publicKeyString); return Friend( id: json['id'], userId: json['user_id'], username: String.fromCharCodes(username), friendId: String.fromCharCodes(idDecrypted), friendSymmetricKey: base64.encode(symmetricKeyDecrypted), publicKey: publicKey, acceptedAt: json['accepted_at']['Valid'] ? DateTime.parse(json['accepted_at']['Time']) : null, ); } Map payloadJson() { Uint8List friendIdEncrypted = CryptoUtils.rsaEncrypt( Uint8List.fromList(friendId.codeUnits), publicKey, ); Uint8List usernameEncrypted = CryptoUtils.rsaEncrypt( Uint8List.fromList(username.codeUnits), publicKey, ); Uint8List symmetricKeyEncrypted = CryptoUtils.rsaEncrypt( Uint8List.fromList( base64.decode(friendSymmetricKey), ), publicKey, ); var publicKeyEncrypted = AesHelper.aesEncrypt( base64.decode(friendSymmetricKey), Uint8List.fromList(CryptoUtils.encodeRSAPublicKeyToPem(publicKey).codeUnits), ); return { 'id': id, 'user_id': userId, 'friend_id': base64.encode(friendIdEncrypted), 'friend_username': base64.encode(usernameEncrypted), 'symmetric_key': base64.encode(symmetricKeyEncrypted), 'asymmetric_public_key': publicKeyEncrypted, 'accepted_at': null, }; } String publicKeyPem() { return CryptoUtils.encodeRSAPublicKeyToPem(publicKey); } Map toMap() { return { 'id': id, 'user_id': userId, 'username': username, 'friend_id': friendId, 'symmetric_key': base64.encode(friendSymmetricKey.codeUnits), 'asymmetric_public_key': publicKeyPem(), 'accepted_at': acceptedAt?.toIso8601String(), }; } @override String toString() { return ''' id: $id userId: $userId username: $username friendId: $friendId accepted_at: $acceptedAt'''; } }