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.

140 lines
3.5 KiB

  1. import 'dart:convert';
  2. import 'dart:typed_data';
  3. import 'package:pointycastle/export.dart';
  4. import '/utils/encryption/aes_helper.dart';
  5. import '/utils/encryption/crypto_utils.dart';
  6. import '/utils/storage/database.dart';
  7. // TODO: Find good place for this to live
  8. Friend findFriendByFriendId(List<Friend> friends, String id) {
  9. for (var friend in friends) {
  10. if (friend.friendId == id) {
  11. return friend;
  12. }
  13. }
  14. // Or return `null`.
  15. throw ArgumentError.value(id, 'id', 'No element with that id');
  16. }
  17. class Friend{
  18. String id;
  19. String userId;
  20. String username;
  21. String friendId;
  22. String friendSymmetricKey;
  23. RSAPublicKey publicKey;
  24. DateTime? acceptedAt;
  25. bool? selected;
  26. Friend({
  27. required this.id,
  28. required this.userId,
  29. required this.username,
  30. required this.friendId,
  31. required this.friendSymmetricKey,
  32. required this.publicKey,
  33. required this.acceptedAt,
  34. this.selected,
  35. });
  36. factory Friend.fromJson(Map<String, dynamic> json, RSAPrivateKey privKey) {
  37. Uint8List idDecrypted = CryptoUtils.rsaDecrypt(
  38. base64.decode(json['friend_id']),
  39. privKey,
  40. );
  41. Uint8List username = CryptoUtils.rsaDecrypt(
  42. base64.decode(json['friend_username']),
  43. privKey,
  44. );
  45. Uint8List symmetricKeyDecrypted = CryptoUtils.rsaDecrypt(
  46. base64.decode(json['symmetric_key']),
  47. privKey,
  48. );
  49. String publicKeyString = AesHelper.aesDecrypt(
  50. symmetricKeyDecrypted,
  51. base64.decode(json['asymmetric_public_key'])
  52. );
  53. RSAPublicKey publicKey = CryptoUtils.rsaPublicKeyFromPem(publicKeyString);
  54. return Friend(
  55. id: json['id'],
  56. userId: json['user_id'],
  57. username: String.fromCharCodes(username),
  58. friendId: String.fromCharCodes(idDecrypted),
  59. friendSymmetricKey: base64.encode(symmetricKeyDecrypted),
  60. publicKey: publicKey,
  61. acceptedAt: json['accepted_at']['Valid'] ?
  62. DateTime.parse(json['accepted_at']['Time']) :
  63. null,
  64. );
  65. }
  66. Map<String, dynamic> payloadJson() {
  67. Uint8List friendIdEncrypted = CryptoUtils.rsaEncrypt(
  68. Uint8List.fromList(friendId.codeUnits),
  69. publicKey,
  70. );
  71. Uint8List usernameEncrypted = CryptoUtils.rsaEncrypt(
  72. Uint8List.fromList(username.codeUnits),
  73. publicKey,
  74. );
  75. Uint8List symmetricKeyEncrypted = CryptoUtils.rsaEncrypt(
  76. Uint8List.fromList(
  77. base64.decode(friendSymmetricKey),
  78. ),
  79. publicKey,
  80. );
  81. var publicKeyEncrypted = AesHelper.aesEncrypt(
  82. base64.decode(friendSymmetricKey),
  83. Uint8List.fromList(CryptoUtils.encodeRSAPublicKeyToPem(publicKey).codeUnits),
  84. );
  85. return {
  86. 'id': id,
  87. 'user_id': userId,
  88. 'friend_id': base64.encode(friendIdEncrypted),
  89. 'friend_username': base64.encode(usernameEncrypted),
  90. 'symmetric_key': base64.encode(symmetricKeyEncrypted),
  91. 'asymmetric_public_key': publicKeyEncrypted,
  92. 'accepted_at': null,
  93. };
  94. }
  95. String publicKeyPem() {
  96. return CryptoUtils.encodeRSAPublicKeyToPem(publicKey);
  97. }
  98. Map<String, dynamic> toMap() {
  99. return {
  100. 'id': id,
  101. 'user_id': userId,
  102. 'username': username,
  103. 'friend_id': friendId,
  104. 'symmetric_key': base64.encode(friendSymmetricKey.codeUnits),
  105. 'asymmetric_public_key': publicKeyPem(),
  106. 'accepted_at': acceptedAt?.toIso8601String(),
  107. };
  108. }
  109. @override
  110. String toString() {
  111. return '''
  112. id: $id
  113. userId: $userId
  114. username: $username
  115. friendId: $friendId
  116. accepted_at: $acceptedAt''';
  117. }
  118. }