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

  1. import 'dart:convert';
  2. import 'package:flutter_dotenv/flutter_dotenv.dart';
  3. import 'package:pointycastle/impl.dart';
  4. import 'package:shared_preferences/shared_preferences.dart';
  5. import '/utils/encryption/aes_helper.dart';
  6. import '/utils/encryption/crypto_utils.dart';
  7. // TODO: Replace this with the prod url when server is deployed
  8. String defaultServerUrl = dotenv.env['SERVER_URL'] ?? 'http://192.168.1.5:8080';
  9. class MyProfile {
  10. String id;
  11. String username;
  12. String? friendId;
  13. RSAPrivateKey? privateKey;
  14. RSAPublicKey? publicKey;
  15. DateTime? loggedInAt;
  16. MyProfile({
  17. required this.id,
  18. required this.username,
  19. this.friendId,
  20. this.privateKey,
  21. this.publicKey,
  22. this.loggedInAt,
  23. });
  24. factory MyProfile._fromJson(Map<String, dynamic> json) {
  25. DateTime loggedInAt = DateTime.now();
  26. if (json.containsKey('logged_in_at')) {
  27. loggedInAt = DateTime.parse(json['logged_in_at']);
  28. }
  29. RSAPrivateKey privateKey = CryptoUtils.rsaPrivateKeyFromPem(json['asymmetric_private_key']);
  30. RSAPublicKey publicKey = CryptoUtils.rsaPublicKeyFromPem(json['asymmetric_public_key']);
  31. return MyProfile(
  32. id: json['user_id'],
  33. username: json['username'],
  34. privateKey: privateKey,
  35. publicKey: publicKey,
  36. loggedInAt: loggedInAt,
  37. );
  38. }
  39. @override
  40. String toString() {
  41. return '''
  42. user_id: $id
  43. username: $username
  44. logged_in_at: $loggedInAt
  45. public_key: $publicKey
  46. private_key: $privateKey
  47. ''';
  48. }
  49. String toJson() {
  50. return jsonEncode(<String, dynamic>{
  51. 'user_id': id,
  52. 'username': username,
  53. 'asymmetric_private_key': privateKey != null ?
  54. CryptoUtils.encodeRSAPrivateKeyToPem(privateKey!) :
  55. null,
  56. 'asymmetric_public_key': publicKey != null ?
  57. CryptoUtils.encodeRSAPublicKeyToPem(publicKey!) :
  58. null,
  59. 'logged_in_at': loggedInAt?.toIso8601String(),
  60. });
  61. }
  62. static Future<MyProfile> login(Map<String, dynamic> json, String password) async {
  63. json['asymmetric_private_key'] = AesHelper.aesDecrypt(
  64. password,
  65. base64.decode(json['asymmetric_private_key'])
  66. );
  67. MyProfile profile = MyProfile._fromJson(json);
  68. final preferences = await SharedPreferences.getInstance();
  69. preferences.setString('profile', profile.toJson());
  70. return profile;
  71. }
  72. static Future<void> logout() async {
  73. final preferences = await SharedPreferences.getInstance();
  74. preferences.remove('profile');
  75. }
  76. static Future<MyProfile> getProfile() async {
  77. final preferences = await SharedPreferences.getInstance();
  78. String? profileJson = preferences.getString('profile');
  79. if (profileJson == null) {
  80. throw Exception('No profile');
  81. }
  82. return MyProfile._fromJson(json.decode(profileJson));
  83. }
  84. static Future<bool> isLoggedIn() async {
  85. MyProfile profile = await MyProfile.getProfile();
  86. if (profile.loggedInAt == null) {
  87. return false;
  88. }
  89. return profile.loggedInAt!.add(const Duration(hours: 12)).isAfter(
  90. (DateTime.now())
  91. );
  92. }
  93. static Future<RSAPrivateKey> getPrivateKey() async {
  94. MyProfile profile = await MyProfile.getProfile();
  95. if (profile.privateKey == null) {
  96. throw Exception('Could not get privateKey');
  97. }
  98. return profile.privateKey!;
  99. }
  100. static setServerUrl(String url) async {
  101. final preferences = await SharedPreferences.getInstance();
  102. preferences.setString('server_url', url);
  103. }
  104. static Future<Uri> getServerUrl(String path) async {
  105. final preferences = await SharedPreferences.getInstance();
  106. String? baseUrl = preferences.getString('server_url');
  107. if (baseUrl == null) {
  108. setServerUrl(defaultServerUrl);
  109. return Uri.parse('$defaultServerUrl$path');
  110. }
  111. return Uri.parse('$baseUrl$path');
  112. }
  113. }