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.

135 lines
3.7 KiB

import 'dart:convert';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:pointycastle/impl.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '/utils/encryption/aes_helper.dart';
import '/utils/encryption/crypto_utils.dart';
// TODO: Replace this with the prod url when server is deployed
String defaultServerUrl = dotenv.env['SERVER_URL'] ?? 'http://192.168.1.5:8080';
class MyProfile {
String id;
String username;
String? friendId;
RSAPrivateKey? privateKey;
RSAPublicKey? publicKey;
DateTime? loggedInAt;
MyProfile({
required this.id,
required this.username,
this.friendId,
this.privateKey,
this.publicKey,
this.loggedInAt,
});
factory MyProfile._fromJson(Map<String, dynamic> json) {
DateTime loggedInAt = DateTime.now();
if (json.containsKey('logged_in_at')) {
loggedInAt = DateTime.parse(json['logged_in_at']);
}
RSAPrivateKey privateKey = CryptoUtils.rsaPrivateKeyFromPem(json['asymmetric_private_key']);
RSAPublicKey publicKey = CryptoUtils.rsaPublicKeyFromPem(json['asymmetric_public_key']);
return MyProfile(
id: json['user_id'],
username: json['username'],
privateKey: privateKey,
publicKey: publicKey,
loggedInAt: loggedInAt,
);
}
@override
String toString() {
return '''
user_id: $id
username: $username
logged_in_at: $loggedInAt
public_key: $publicKey
private_key: $privateKey
''';
}
String toJson() {
return jsonEncode(<String, dynamic>{
'user_id': id,
'username': username,
'asymmetric_private_key': privateKey != null ?
CryptoUtils.encodeRSAPrivateKeyToPem(privateKey!) :
null,
'asymmetric_public_key': publicKey != null ?
CryptoUtils.encodeRSAPublicKeyToPem(publicKey!) :
null,
'logged_in_at': loggedInAt?.toIso8601String(),
});
}
static Future<MyProfile> login(Map<String, dynamic> json, String password) async {
json['asymmetric_private_key'] = AesHelper.aesDecrypt(
password,
base64.decode(json['asymmetric_private_key'])
);
MyProfile profile = MyProfile._fromJson(json);
final preferences = await SharedPreferences.getInstance();
preferences.setString('profile', profile.toJson());
return profile;
}
static Future<void> logout() async {
final preferences = await SharedPreferences.getInstance();
preferences.remove('profile');
}
static Future<MyProfile> getProfile() async {
final preferences = await SharedPreferences.getInstance();
String? profileJson = preferences.getString('profile');
if (profileJson == null) {
throw Exception('No profile');
}
return MyProfile._fromJson(json.decode(profileJson));
}
static Future<bool> isLoggedIn() async {
MyProfile profile = await MyProfile.getProfile();
if (profile.loggedInAt == null) {
return false;
}
return profile.loggedInAt!.add(const Duration(hours: 12)).isAfter(
(DateTime.now())
);
}
static Future<RSAPrivateKey> getPrivateKey() async {
MyProfile profile = await MyProfile.getProfile();
if (profile.privateKey == null) {
throw Exception('Could not get privateKey');
}
return profile.privateKey!;
}
static setServerUrl(String url) async {
final preferences = await SharedPreferences.getInstance();
preferences.setString('server_url', url);
}
static Future<Uri> getServerUrl(String path) async {
final preferences = await SharedPreferences.getInstance();
String? baseUrl = preferences.getString('server_url');
if (baseUrl == null) {
setServerUrl(defaultServerUrl);
return Uri.parse('$defaultServerUrl$path');
}
return Uri.parse('$baseUrl$path');
}
}