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

fix: encript env, decrypt when app run #1600

Merged
merged 11 commits into from
Mar 29, 2024
11 changes: 11 additions & 0 deletions .env.secret.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FERAL_FILE_SECRET_KEY_TESTNET=
FERAL_FILE_SECRET_KEY_MAINNET=
CHAT_SERVER_HMAC_KEY=
AU_CLAIM_SECRET_KEY=
MIXPANEL_KEY=
METRIC_SECRET_KEY=
BRANCH_KEY=
SENTRY_DSN=
ONESIGNAL_APP_ID=
METRIC_ENDPOINT=
WEB3_RPC_MAINNET_URL=
12 changes: 12 additions & 0 deletions .github/workflows/android-release-appcenter.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,22 @@ jobs:
${{ inputs.testnet == true }} && echo -e "${{ secrets.DEV_ENV }}" | sed 's/\\n/\n/g' >> .env || echo -e "${{ secrets.STAGING_ENV }}" | sed 's/\\n/\n/g' >> .env
cat .env

- name: Create env secret file
run: |
touch .env.secret
${{ inputs.testnet == true }} && echo -e "${{ secrets.DEV_ENV_SECRET }}" | sed 's/\\n/\n/g' >> .env.secret || echo -e "${{ secrets.STAGING_ENV_SECRET }}" | sed 's/\\n/\n/g' >> .env.secret
cat .env.secret

- name: Submoudles update
run: git -c submodule.auto-test.update=none submodule update --init --recursive
- run: flutter pub cache repair
- run: flutter pub get

# Encrypt secrets before use
- name: Encrypt Secrets
run: |
./script/encrypt_secrets.sh ${{ secrets.ENTROPY }}

- run: flutter build apk --flavor inhouse
- run: mv build/app/outputs/flutter-apk/app-inhouse-release.apk build/app/outputs/flutter-apk/app-inhouse-release-${{ env.NAME_SUFFIX }}.apk
- name: Distribute apk to App Center
Expand Down
16 changes: 14 additions & 2 deletions .github/workflows/bmvn_build_appcenter_android.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,22 @@ jobs:
${{ inputs.testnet == true }} && echo -e "${{ secrets.DEV_ENV }}" | sed 's/\\n/\n/g' >> .env || echo -e "${{ secrets.STAGING_ENV }}" | sed 's/\\n/\n/g' >> .env
cat .env

- name: Create env secret file
run: |
touch .env.secret
${{ inputs.testnet == true }} && echo -e "${{ secrets.DEV_ENV_SECRET }}" | sed 's/\\n/\n/g' >> .env.secret || echo -e "${{ secrets.STAGING_ENV_SECRET }}" | sed 's/\\n/\n/g' >> .env.secret
cat .env

- name: Submoudles update
run: git -c submodule.auto-test.update=none submodule update --init --recursive
- run: flutter pub cache repair
- run: flutter pub get

# Encrypt secrets before use
- name: Encrypt Secrets
run: |
./script/encrypt_secrets.sh ${{ secrets.ENTROPY }}

- run: flutter build apk --flavor inhouse
- run: mv build/app/outputs/flutter-apk/app-inhouse-release.apk build/app/outputs/flutter-apk/app-inhouse-release-${{ env.NAME_SUFFIX }}.apk
- name: Distribute apk to App Center
Expand All @@ -95,7 +107,7 @@ jobs:
release_notes: ${{ inputs.message }}

- name: Upload Sentry debug symbols
env:
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH }}
run: |
flutter packages pub run sentry_dart_plugin
flutter packages pub run sentry_dart_plugin
13 changes: 12 additions & 1 deletion .github/workflows/bmvn_build_appcenter_ios.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ jobs:
${{ inputs.testnet == true }} && echo -e "${{ secrets.DEV_ENV }}" | sed 's/\\n/\n/g' >> .env || echo -e "${{ secrets.STAGING_ENV }}" | sed 's/\\n/\n/g' >> .env
cat .env

- name: Create env secret file
run: |
touch .env.secret
${{ inputs.testnet == true }} && echo -e "${{ secrets.DEV_ENV_SECRET }}" | sed 's/\\n/\n/g' >> .env.secret || echo -e "${{ secrets.STAGING_ENV_SECRET }}" | sed 's/\\n/\n/g' >> .env.secret
cat .env

- name: Flutter doctor
run: flutter doctor
- name: Submoudles update
Expand All @@ -96,6 +102,11 @@ jobs:
cd ios/
pod install

# Encrypt secrets before use
- name: Encrypt Secrets
run: |
./script/encrypt_secrets.sh ${{ secrets.ENTROPY }}

- uses: mathieu-bour/setup-sentry-cli@main

# Build and deploy with Fastlane (by default, to ciappcenter track) 🚀.
Expand All @@ -120,7 +131,7 @@ jobs:
working-directory: ios

- name: Upload Sentry debug symbols
env:
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH }}
run: |
flutter packages pub run sentry_dart_plugin
11 changes: 11 additions & 0 deletions .github/workflows/ios-release-testflight.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ jobs:
echo -e "${{ secrets.PRODUCTION_ENV }}" | sed 's/\\n/\n/g' >> .env
cat .env

- name: Create env secret file
run: |
touch .env.secret
echo -e "${{ secrets.PRODUCTION_ENV_SECRET }}" | sed 's/\\n/\n/g' >> .env.secret
cat .env.secret

- name: Flutter doctor
run: flutter doctor
- name: Submoudles update
Expand All @@ -76,6 +82,11 @@ jobs:
cd ios/
pod install

# Encrypt secrets before use
- name: Encrypt Secrets
run: |
./script/encrypt_secrets.sh ${{ secrets.ENTROPY }}

- uses: mathieu-bour/setup-sentry-cli@main

# Build and deploy with Fastlane (by default, to ciappcenter track) 🚀.
Expand Down
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,7 @@ app.*.map.json
# app environment variables
.env
.env.development
.env.production
.env.production
.env.secret

lib/encrypt_env/secrets.g.dart
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,13 @@ Autonomy is the world’s first and only digital art wallet. It gives you one ea
3. Initialize submodule by running; `git submodule update --init --recursive`
- If you don't want to clone the auto-test package, simply run: `git -c submodule.auto-test.update=none submodule update --init --recursive`
4. Initialize the config file. `cp .env.example .env`
- Contact with Feral File app development team for development env.
5. Run `flutter run --flavor inhouse` to run Feral File app development on the connected device.
- Contact with Feral File app development team for development env.
5. Initialize the secret config file. `cp .env.secret.example .env.secret`
- There are credentials information. You may need to provide your own credentials.Contact with Feral File app development team for consultation.
6. Run ./script/encrypt_secrets.sh <-entropy-> to generate the encrypted secrets file.
- <-entropy-> is a random string. You can type a random string like akhrdsgl4893tynk3iu4y8hf
- You only need to run this script again when you want to update .env.secret.
7. Run `flutter run --flavor inhouse` to run Feral File app development on the connected device.

A few resources to get you started if this is your first Flutter project:

Expand Down
59 changes: 31 additions & 28 deletions lib/common/environment.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// that can be found in the LICENSE file.
//

import 'package:autonomy_flutter/encrypt_env/secrets.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';

class Environment {
Expand Down Expand Up @@ -42,8 +43,6 @@ class Environment {
? connectWebsocketTestnetURL
: connectWebsocketMainnetURL;

static String get auClaimSecretKey => dotenv.env['AU_CLAIM_SECRET_KEY'] ?? '';

static String get tokenWebviewPrefix =>
dotenv.env['TOKEN_WEBVIEW_PREFIX'] ?? '';

Expand All @@ -53,9 +52,6 @@ class Environment {
static String get indexerTestnetURL =>
dotenv.env['INDEXER_TESTNET_API_URL'] ?? '';

static String get web3RpcMainnetURL =>
dotenv.env['WEB3_RPC_MAINNET_URL'] ?? '';

static int get web3MainnetChainId =>
int.tryParse(dotenv.env['WEB3_MAINNET_CHAIN_ID'] ?? '1') ?? 1;

Expand All @@ -80,21 +76,15 @@ class Environment {
static String get feralFileAPIMainnetURL =>
dotenv.env['FERAL_FILE_API_MAINNET_URL'] ?? '';

static String get feralFileSecretKeyMainnet =>
dotenv.env['FERAL_FILE_SECRET_KEY_MAINNET'] ?? '';

static String get feralFileAPITestnetURL =>
dotenv.env['FERAL_FILE_API_TESTNET_URL'] ?? '';

static String get feralFileSecretKeyTestnet =>
dotenv.env['FERAL_FILE_SECRET_KEY_TESTNET'] ?? '';
static String get feralFileAssetURLTestnet =>
dotenv.env['FERAL_FILE_ASSET_URL_TESTNET'] ?? '';

static String get feralFileAssetURLMainnet =>
dotenv.env['FERAL_FILE_ASSET_URL_MAINNET'] ?? '';

static String get feralFileAssetURLTestnet =>
dotenv.env['FERAL_FILE_ASSET_URL_TESTNET'] ?? '';

static String get extensionSupportMainnetURL =>
dotenv.env['EXTENSION_SUPPORT_MAINNET_URL'] ?? '';

Expand All @@ -119,10 +109,6 @@ class Environment {

static String get pubdocURL => dotenv.env['AUTONOMY_PUBDOC_URL'] ?? '';

static String get sentryDSN => dotenv.env['SENTRY_DSN'] ?? '';

static String get onesignalAppID => dotenv.env['ONESIGNAL_APP_ID'] ?? '';

static String get awsIdentityPoolId =>
dotenv.env['AWS_IDENTITY_POOL_ID'] ?? '';

Expand All @@ -138,14 +124,6 @@ class Environment {
static bool get appTestnetConfig =>
dotenv.env['APP_TESTNET_CONFIG']?.toUpperCase() == 'TRUE';

static String get metricEndpoint => dotenv.env['METRIC_ENDPOINT'] ?? '';

static String get metricSecretKey => dotenv.env['METRIC_SECRET_KEY'] ?? '';

static String get branchKey => dotenv.env['BRANCH_KEY'] ?? '';

static String get mixpanelKey => dotenv.env['MIXPANEL_KEY'] ?? '';

static String get auClaimAPIURL => dotenv.env['AU_CLAIM_API_URL'] ?? '';

static List<String> get irlWhitelistUrls =>
Expand All @@ -166,9 +144,6 @@ class Environment {
static String get payToMintBaseUrl =>
dotenv.env['PAY_TO_MINT_BASE_URL'] ?? '';

static String get chatServerHmacKey =>
dotenv.env['CHAT_SERVER_HMAC_KEY'] ?? '';

static String get postcardChatServerUrl =>
dotenv.env['CHAT_SERVER_URL'] ?? '';

Expand All @@ -184,6 +159,34 @@ class Environment {

static String get autonomyActivationURL =>
dotenv.env['AUTONOMY_ACTIVATION_URL'] ?? '';

static String get chatServerHmacKey =>
cachedSecretEnv['CHAT_SERVER_HMAC_KEY'] ?? '';

static String get metricEndpoint => cachedSecretEnv['METRIC_ENDPOINT'] ?? '';

static String get metricSecretKey =>
cachedSecretEnv['METRIC_SECRET_KEY'] ?? '';

static String get branchKey => cachedSecretEnv['BRANCH_KEY'] ?? '';

static String get mixpanelKey => cachedSecretEnv['MIXPANEL_KEY'] ?? '';

static String get auClaimSecretKey =>
cachedSecretEnv['AU_CLAIM_SECRET_KEY'] ?? '';

static String get feralFileSecretKeyTestnet =>
cachedSecretEnv['FERAL_FILE_SECRET_KEY_TESTNET'] ?? '';

static String get feralFileSecretKeyMainnet =>
cachedSecretEnv['FERAL_FILE_SECRET_KEY_MAINNET'] ?? '';

static String get web3RpcMainnetURL =>
cachedSecretEnv['WEB3_RPC_MAINNET_URL'] ?? '';

static String get sentryDSN => cachedSecretEnv['SENTRY_DSN'] ?? '';

static String get onesignalAppID => cachedSecretEnv['ONESIGNAL_APP_ID'] ?? '';
}

class Secret {
Expand Down
1 change: 1 addition & 0 deletions lib/encrypt_env/secrets.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
late dynamic cachedSecretEnv;
5 changes: 5 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@
// ignore_for_file: avoid_annotating_with_dynamic

import 'dart:async';
import 'dart:convert';
import 'dart:isolate';
import 'dart:ui';

import 'package:autonomy_flutter/common/environment.dart';
import 'package:autonomy_flutter/common/injector.dart';
import 'package:autonomy_flutter/encrypt_env/secrets.dart';
import 'package:autonomy_flutter/encrypt_env/secrets.g.dart';
import 'package:autonomy_flutter/model/eth_pending_tx_amount.dart';
import 'package:autonomy_flutter/screen/app_router.dart';
import 'package:autonomy_flutter/service/configuration_service.dart';
Expand Down Expand Up @@ -47,6 +50,8 @@ import 'package:sentry_flutter/sentry_flutter.dart';

void main() async {
unawaited(runZonedGuarded(() async {
final json = await getSecretEnv();
cachedSecretEnv = jsonDecode(json);
await dotenv.load();
await SentryFlutter.init(
(options) {
Expand Down
24 changes: 20 additions & 4 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.3"
cryptography:
dependency: "direct main"
description:
name: cryptography
sha256: d146b76d33d94548cf035233fbc2f4338c1242fa119013bead807d033fc4ae05
url: "https://pub.dev"
source: hosted
version: "2.7.0"
cryptography_flutter:
dependency: "direct main"
description:
name: cryptography_flutter
sha256: a7fc3f0de42fb0947cbf213257aa3a69c89df561d104723ede8050658621f292
url: "https://pub.dev"
source: hosted
version: "2.3.2"
csslib:
dependency: transitive
description:
Expand Down Expand Up @@ -568,10 +584,10 @@ packages:
dependency: transitive
description:
name: ffi
sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99
sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21"
url: "https://pub.dev"
source: hosted
version: "2.0.2"
version: "2.1.2"
file:
dependency: transitive
description:
Expand Down Expand Up @@ -2979,5 +2995,5 @@ packages:
source: hosted
version: "3.1.2"
sdks:
dart: ">=3.2.0-0 <4.0.0"
flutter: ">=3.10.0"
dart: ">=3.3.0-279.1.beta <4.0.0"
flutter: ">=3.13.0"
2 changes: 2 additions & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ dependencies:
image_gallery_saver: ^2.0.3
hand_signature: ^3.0.1
flutter_pdfview: ^1.3.2
cryptography: ^2.7.0
cryptography_flutter: ^2.3.2
dependency_overrides:
intl: 0.18.0

Expand Down
40 changes: 40 additions & 0 deletions script/encrypt.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// ignore_for_file: avoid_print

import 'dart:convert';
import 'dart:math';
import 'package:cryptography/cryptography.dart';

// Example function for encryption
Future<List<dynamic>> _encryptText(String text, String key) async {
final algorithm = Chacha20.poly1305Aead();
final bytes = utf8.encode(key);
final secretKey = await algorithm.newSecretKeyFromBytes(bytes);
final secretBox = await algorithm.encryptString(text, secretKey: secretKey);
final encryptText = secretBox.concatenation();
return [
base64Encode(encryptText),
secretBox.nonce.length,
secretBox.mac.bytes.length
];
}

String _generateKeyFromEntropy(String entropy, int length) {
final random = Random(entropy.hashCode); // Use entropy's hash code as seed
final entropyLength = entropy.length;
return String.fromCharCodes(Iterable.generate(
length, (_) => entropy.codeUnitAt(random.nextInt(entropyLength))));
}

void main(List<String> arguments) async {
if (arguments.length < 2) {
print('Usage: dart encrypt.dart <text_to_encrypt> <entropy>');
return;
}

String textToEncrypt = arguments[0];
String entropy = arguments[1];

final encryptedText =
await _encryptText(textToEncrypt, _generateKeyFromEntropy(entropy, 32));
print(encryptedText.join(' '));
}
Loading
Loading