Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keys and encryption #2027

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/apptheme.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// ignore_for_file: talawa_api_doc
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
// import 'package:flutter_screenutil/flutter_screenutil.dart';
Expand Down
1 change: 1 addition & 0 deletions lib/router.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// ignore_for_file: talawa_good_doc_comments
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:talawa/constants/routing_constants.dart';
Expand Down
125 changes: 125 additions & 0 deletions lib/utils/encryptor.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import 'dart:convert';
import 'dart:typed_data';

import 'package:crypto/crypto.dart';
import 'package:hive/hive.dart';
import 'package:pointycastle/asymmetric/oaep.dart';
import 'package:pointycastle/asymmetric/rsa.dart';
import 'package:pointycastle/pointycastle.dart';
import 'package:pointycastle/random/fortuna_random.dart';

/// Handles all of the encryption tasks in the codebase.
class Encryptor {
Expand All @@ -22,4 +29,122 @@ class Encryptor {
if (!shouldEncrypt) return data;
return sha256.convert(utf8.encode(data)).toString();
}

/// Generates RSA Key Pairs (Public/Private).
///
/// Should be called only during app's first initialization,
/// and any future usage should be done by getting the keys
/// from the local storage.
///
/// **params**:
/// None
///
/// **returns**:
/// * `AsymmetricKeyPair<PublicKey, PrivateKey>`: The generated
/// public and private keys.
AsymmetricKeyPair<PublicKey, PrivateKey> generateRSAKeyPair() {
final keyGen = RSAKeyGeneratorParameters(BigInt.parse('65537'), 2048, 64);
final secureRandom = FortunaRandom();
final random = SecureRandom('Fortuna')
..seed(secureRandom as CipherParameters);
final keyGenParams = ParametersWithRandom(keyGen, random);

final keyGenerator = KeyGenerator('RSA');
keyGenerator.init(keyGenParams);

return keyGenerator.generateKeyPair();
}

/// Saves the generated key pair to local storage.
///
/// Any future usage of the keys must be initiated from here.
///
/// **params**:
/// * `keyPair`: [AsymmetricKeyPair] to save.
///
/// **returns**:
/// * `Future<void>`: None
Future<void> saveKeyPair(
AsymmetricKeyPair<PublicKey, PrivateKey> keyPair,
) async {
// TODO: Implement secure storage here

await Hive.openBox<AsymmetricKeyPair<PublicKey, PrivateKey>>('user_keys');
final keysBox = await Hive.openBox('user_keys');

keysBox.put('key_pair', keyPair);
}

/// Loads secret keys from the Hive db.
///
/// **params**:
/// None
///
/// **returns**:
/// * `Future<AsymmetricKeyPair<PublicKey, PrivateKey>>`: The public and
/// private key pair
Future<AsymmetricKeyPair<PublicKey, PrivateKey>> loadKeyPair() async {
await Hive.openBox<AsymmetricKeyPair<PublicKey, PrivateKey>>('user_keys');
final keysBox = await Hive.openBox('user_keys');

return (await keysBox.get('key_pair'))
as AsymmetricKeyPair<PublicKey, PrivateKey>;
}

/// Encrypts the given string data with Recipient's Public Key.
///
/// **params**:
/// * `data`: The string to encrypt
/// * `recipientPublicKey`: Key to be used to encrypt. Recipient's public
/// key in our case.
///
/// **returns**:
/// * `String`: Encrypted string
String assymetricEncryptString(String data, RSAPublicKey recipientPublicKey) {
final cipher = OAEPEncoding(RSAEngine())
..init(true, PublicKeyParameter<RSAPublicKey>(recipientPublicKey));

final encryptedBytes = cipher.process(Uint8List.fromList(data.codeUnits));
return base64Encode(encryptedBytes);
}

/// Encrypts the given string data with user's Private Key.
///
/// **params**:
/// * `data`: The string to decrypt
/// * `privateKey`: Key to be used to decrypt. User's private key in our case.
///
/// **returns**:
/// * `String`: Decrypted string
String assymetricDecryptString(String data, RSAPrivateKey privateKey) {
final cipher = OAEPEncoding(RSAEngine())
..init(false, PrivateKeyParameter<RSAPrivateKey>(privateKey));

final decryptedBytes = cipher.process(base64Decode(data));
return String.fromCharCodes(decryptedBytes);
}

/// Helper function to decrypt the message.
///
/// Internally uses the [loadKeyPair] function to get private key and
/// [assymetricDecryptString] to decrypt the given message.
///
/// **params**:
/// * `message`: Message object containing a field named [encryptedMessage]
/// which is supposed to contained user's message in encrypted format.
///
/// **returns**:
/// * `Future<void>`: None
/// TODO: Use this somewhere
Future<void> receiveMessage(Map<String, dynamic> message) async {
final privateKey = (await loadKeyPair()).privateKey;

final encryptedMessage = message['encryptedMessage'] as String;
final decryptedMessage = assymetricDecryptString(
encryptedMessage,
privateKey as RSAPrivateKey,
);

print('Decrypted Message: $decryptedMessage');
}
}
1 change: 1 addition & 0 deletions lib/view_model/access_request_view_model.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// ignore_for_file: talawa_api_doc
import 'package:flutter/cupertino.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:talawa/constants/routing_constants.dart';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// ignore_for_file: talawa_good_doc_comments, talawa_api_doc
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
Expand Down
1 change: 1 addition & 0 deletions lib/views/after_auth_screens/feed/organization_feed.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// ignore_for_file: talawa_api_doc
import 'package:flutter/material.dart';
import 'package:talawa/view_model/after_auth_view_models/feed_view_models/organization_feed_view_model.dart';
import 'package:talawa/view_model/main_screen_view_model.dart';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// ignore_for_file: talawa_good_doc_comments, talawa_api_doc
import 'package:flutter/material.dart';
import 'package:talawa/apptheme.dart';
import 'package:talawa/models/organization/org_info.dart';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// ignore_for_file: talawa_api_doc, talawa_good_doc_comments
import 'package:flutter/material.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';
import 'package:talawa/enums/enums.dart';
Expand Down
1 change: 1 addition & 0 deletions lib/views/after_auth_screens/profile/profile_page.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// ignore_for_file: talawa_api_doc
import 'package:contained_tab_bar_view/contained_tab_bar_view.dart';
import 'package:flutter/material.dart';
import 'package:flutter_braintree/flutter_braintree.dart';
Expand Down
1 change: 1 addition & 0 deletions lib/views/pre_auth_screens/login.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:talawa/widgets/raised_round_edge_button.dart';
import 'package:talawa/widgets/rich_text.dart';

/// This is the login widget.
///
/// There are two input fiels. The first one takes in the email and
/// the second one takes in the password of the user.
/// There is also a "Forgot Password" text button, which directs to
Expand Down
1 change: 1 addition & 0 deletions lib/widgets/custom_avatar.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// ignore_for_file: talawa_good_doc_comments, talawa_api_doc
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
Expand Down
1 change: 1 addition & 0 deletions lib/widgets/custom_list_tile.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// ignore_for_file: talawa_good_doc_comments, talawa_api_doc
import 'package:flutter/material.dart';
import 'package:talawa/enums/enums.dart';
import 'package:talawa/models/options/options.dart';
Expand Down
1 change: 1 addition & 0 deletions lib/widgets/post_container.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// ignore_for_file: talawa_api_doc
import 'package:flutter/material.dart';
import 'package:visibility_detector/visibility_detector.dart';

Expand Down
1 change: 1 addition & 0 deletions lib/widgets/post_detailed_page.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// ignore_for_file: talawa_good_doc_comments, talawa_api_doc
import 'package:flutter/material.dart';
import 'package:talawa/utils/app_localization.dart';

Expand Down
1 change: 1 addition & 0 deletions lib/widgets/post_list_widget.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// ignore_for_file: talawa_api_doc
import 'package:flutter/material.dart';
import 'package:talawa/models/post/post_model.dart';
import 'package:talawa/widgets/post_widget.dart';
Expand Down
1 change: 1 addition & 0 deletions lib/widgets/post_widget.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// ignore_for_file: talawa_api_doc
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:talawa/models/post/post_model.dart';
Expand Down
34 changes: 21 additions & 13 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ packages:
dependency: transitive
description:
name: _fe_analyzer_shared
sha256: "405666cd3cf0ee0a48d21ec67e65406aad2c726d9fa58840d3375e7bdcd32a07"
sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a
url: "https://pub.dev"
source: hosted
version: "60.0.0"
version: "61.0.0"
_flutterfire_internals:
dependency: transitive
description:
Expand All @@ -21,10 +21,10 @@ packages:
dependency: transitive
description:
name: analyzer
sha256: "1952250bd005bacb895a01bf1b4dc00e3ba1c526cf47dca54dfe24979c65f5b3"
sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562
url: "https://pub.dev"
source: hosted
version: "5.12.0"
version: "5.13.0"
analyzer_plugin:
dependency: transitive
description:
Expand Down Expand Up @@ -266,7 +266,7 @@ packages:
source: hosted
version: "0.3.3+4"
crypto:
dependency: transitive
dependency: "direct main"
description:
name: crypto
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
Expand Down Expand Up @@ -301,26 +301,26 @@ packages:
dependency: "direct dev"
description:
name: custom_lint
sha256: "3ce36c04d30c60cde295588c6185b3f9800e6c18f6670a7ffdb3d5eab39bb942"
sha256: "837821e4619c167fd5a547b03bb2fc6be7e65b800ec75528848429705c31ceba"
url: "https://pub.dev"
source: hosted
version: "0.4.0"
version: "0.5.3"
custom_lint_builder:
dependency: transitive
description:
name: custom_lint_builder
sha256: "73d09c9848e9f6d5c3e0a1809eac841a8d7ea123d0849feefa040e1ad60b6d06"
sha256: "3537d50202568994a6f42b1f2953aed6292fc5ecf83e45237af73f64aff2be72"
url: "https://pub.dev"
source: hosted
version: "0.4.0"
version: "0.5.3"
custom_lint_core:
dependency: transitive
description:
name: custom_lint_core
sha256: "9170d9db2daf774aa2251a3bc98e4ba903c7702ab07aa438bc83bd3c9a0de57f"
sha256: "3bdebdd52a42b4d6e5be9cd833ad1ecfbbc23e1020ca537060e54085497aea9c"
url: "https://pub.dev"
source: hosted
version: "0.4.0"
version: "0.5.3"
dart_style:
dependency: transitive
description:
Expand Down Expand Up @@ -1261,6 +1261,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.6"
pointycastle:
dependency: "direct main"
description:
name: pointycastle
sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c"
url: "https://pub.dev"
source: hosted
version: "3.7.3"
pool:
dependency: transitive
description:
Expand Down Expand Up @@ -1813,10 +1821,10 @@ packages:
dependency: transitive
description:
name: watcher
sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0"
sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
url: "https://pub.dev"
source: hosted
version: "1.0.2"
version: "1.1.0"
web:
dependency: transitive
description:
Expand Down
4 changes: 3 additions & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ dependencies:
connectivity_plus: ^4.0.2
contained_tab_bar_view: ^0.8.0

crypto: ^3.0.3
cupertino_icons: ^1.0.3
currency_picker: ^2.0.16

Expand Down Expand Up @@ -58,14 +59,15 @@ dependencies:
http: ^1.1.0
image_cropper: ^5.0.0

intl: ^0.18.0
image_picker: ^1.0.4
intl: ^0.18.0
json_annotation: ^4.7.0
mockito: ^5.4.2
network_image_mock: ^2.1.1
path_provider: ^2.1.1
permission_handler: ^11.0.0
plugin_platform_interface: ^2.1.6
pointycastle: ^3.7.3
provider: ^6.0.3
qr_code_scanner: ^1.0.0
qr_flutter: 4.0.0
Expand Down
Loading