Compare commits
9 commits
main
...
old-deskto
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b759be9609 | ||
![]() |
ff78ffb2dd | ||
![]() |
9aa8f4931a | ||
![]() |
9417508d05 | ||
![]() |
5d08264dd0 | ||
![]() |
bd439cc19e | ||
![]() |
eacb043fd0 | ||
![]() |
5c54b14768 | ||
![]() |
c9e9b7a38d |
27 changed files with 379 additions and 349 deletions
39
README.md
39
README.md
|
@ -1,3 +1,15 @@
|
|||
# 🔥 Warning 🔥
|
||||
|
||||
This branch contains untested code that can potentially corrupt your data.
|
||||
|
||||
**You <u>should not</u> run this against your main acccount.**
|
||||
|
||||
If you are interested in the official release of our desktop app, please ⭐ this repo.
|
||||
|
||||
---
|
||||
|
||||
<br/>
|
||||
|
||||
# ente Authenticator
|
||||
|
||||
ente's Authenticator app helps you generate and store 2 step verification (2FA)
|
||||
|
@ -77,8 +89,31 @@ tokens has been documented [here](architecture/index.md).
|
|||
1. [Install Flutter](https://flutter.dev/docs/get-started/install)
|
||||
2. Clone this repository with `git clone git@github.com:ente-io/auth.git`
|
||||
3. Pull in all submodules with `git submodule update --init --recursive`
|
||||
4. For Android, run `flutter build apk --release --flavor independent`
|
||||
5. For iOS, run `flutter build ios`
|
||||
|
||||
### Android
|
||||
```
|
||||
flutter build apk --release --flavor independent
|
||||
```
|
||||
|
||||
### iOS
|
||||
```
|
||||
flutter build ios
|
||||
```
|
||||
|
||||
### Linux
|
||||
```
|
||||
flutter build linux
|
||||
```
|
||||
|
||||
### MacOS
|
||||
```
|
||||
fluter build macos
|
||||
```
|
||||
|
||||
### Windows
|
||||
```
|
||||
flutter build windows
|
||||
```
|
||||
|
||||
|
||||
## 🙋♂️ Support
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'dart:io' as io;
|
|||
import 'dart:typed_data';
|
||||
|
||||
import 'package:bip39/bip39.dart' as bip39;
|
||||
import 'package:convert/convert.dart';
|
||||
import 'package:ente_auth/core/constants.dart';
|
||||
import 'package:ente_auth/core/errors.dart';
|
||||
import 'package:ente_auth/core/event_bus.dart';
|
||||
|
@ -15,7 +16,6 @@ import 'package:ente_auth/models/private_key_attributes.dart';
|
|||
import 'package:ente_auth/store/authenticator_db.dart';
|
||||
import 'package:ente_auth/utils/crypto_util.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:flutter_sodium/flutter_sodium.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
@ -120,6 +120,7 @@ class Configuration {
|
|||
}
|
||||
|
||||
Future<void> logout({bool autoLogout = false}) async {
|
||||
_logger.info("Logging out");
|
||||
await _preferences.clear();
|
||||
await _secureStorage.deleteAll(iOptions: _secureStorageOptionsIOS);
|
||||
await AuthenticatorDB.instance.clearTable();
|
||||
|
@ -138,8 +139,9 @@ class Configuration {
|
|||
final recoveryKey = CryptoUtil.generateKey();
|
||||
|
||||
// Encrypt master key and recovery key with each other
|
||||
final encryptedMasterKey = CryptoUtil.encryptSync(masterKey, recoveryKey);
|
||||
final encryptedRecoveryKey = CryptoUtil.encryptSync(recoveryKey, masterKey);
|
||||
final encryptedMasterKey = await CryptoUtil.encrypt(masterKey, recoveryKey);
|
||||
final encryptedRecoveryKey =
|
||||
await CryptoUtil.encrypt(recoveryKey, masterKey);
|
||||
|
||||
// Derive a key from the password that will be used to encrypt and
|
||||
// decrypt the master key
|
||||
|
@ -151,31 +153,31 @@ class Configuration {
|
|||
|
||||
// Encrypt the key with this derived key
|
||||
final encryptedKeyData =
|
||||
CryptoUtil.encryptSync(masterKey, derivedKeyResult.key);
|
||||
await CryptoUtil.encrypt(masterKey, derivedKeyResult.key);
|
||||
|
||||
// Generate a public-private keypair and encrypt the latter
|
||||
final keyPair = await CryptoUtil.generateKeyPair();
|
||||
final encryptedSecretKeyData =
|
||||
CryptoUtil.encryptSync(keyPair.sk, masterKey);
|
||||
await CryptoUtil.encrypt(keyPair.secretKey.extractBytes(), masterKey);
|
||||
|
||||
final attributes = KeyAttributes(
|
||||
Sodium.bin2base64(kekSalt),
|
||||
Sodium.bin2base64(encryptedKeyData.encryptedData!),
|
||||
Sodium.bin2base64(encryptedKeyData.nonce!),
|
||||
Sodium.bin2base64(keyPair.pk),
|
||||
Sodium.bin2base64(encryptedSecretKeyData.encryptedData!),
|
||||
Sodium.bin2base64(encryptedSecretKeyData.nonce!),
|
||||
base64Encode(kekSalt),
|
||||
base64Encode(encryptedKeyData.encryptedData!),
|
||||
base64Encode(encryptedKeyData.nonce!),
|
||||
base64Encode(keyPair.publicKey),
|
||||
base64Encode(encryptedSecretKeyData.encryptedData!),
|
||||
base64Encode(encryptedSecretKeyData.nonce!),
|
||||
derivedKeyResult.memLimit,
|
||||
derivedKeyResult.opsLimit,
|
||||
Sodium.bin2base64(encryptedMasterKey.encryptedData!),
|
||||
Sodium.bin2base64(encryptedMasterKey.nonce!),
|
||||
Sodium.bin2base64(encryptedRecoveryKey.encryptedData!),
|
||||
Sodium.bin2base64(encryptedRecoveryKey.nonce!),
|
||||
base64Encode(encryptedMasterKey.encryptedData!),
|
||||
base64Encode(encryptedMasterKey.nonce!),
|
||||
base64Encode(encryptedRecoveryKey.encryptedData!),
|
||||
base64Encode(encryptedRecoveryKey.nonce!),
|
||||
);
|
||||
final privateAttributes = PrivateKeyAttributes(
|
||||
Sodium.bin2base64(masterKey),
|
||||
Sodium.bin2hex(recoveryKey),
|
||||
Sodium.bin2base64(keyPair.sk),
|
||||
base64Encode(masterKey),
|
||||
hex.encode(recoveryKey),
|
||||
base64Encode(keyPair.secretKey.extractBytes()),
|
||||
);
|
||||
return KeyGenResult(attributes, privateAttributes);
|
||||
}
|
||||
|
@ -194,14 +196,14 @@ class Configuration {
|
|||
|
||||
// Encrypt the key with this derived key
|
||||
final encryptedKeyData =
|
||||
CryptoUtil.encryptSync(masterKey!, derivedKeyResult.key);
|
||||
await CryptoUtil.encrypt(masterKey!, derivedKeyResult.key);
|
||||
|
||||
final existingAttributes = getKeyAttributes();
|
||||
|
||||
return existingAttributes!.copyWith(
|
||||
kekSalt: Sodium.bin2base64(kekSalt),
|
||||
encryptedKey: Sodium.bin2base64(encryptedKeyData.encryptedData!),
|
||||
keyDecryptionNonce: Sodium.bin2base64(encryptedKeyData.nonce!),
|
||||
kekSalt: base64Encode(kekSalt),
|
||||
encryptedKey: base64Encode(encryptedKeyData.encryptedData!),
|
||||
keyDecryptionNonce: base64Encode(encryptedKeyData.nonce!),
|
||||
memLimit: derivedKeyResult.memLimit,
|
||||
opsLimit: derivedKeyResult.opsLimit,
|
||||
);
|
||||
|
@ -220,7 +222,7 @@ class Configuration {
|
|||
_logger.info('state validation done');
|
||||
final kek = await CryptoUtil.deriveKey(
|
||||
utf8.encode(password) as Uint8List,
|
||||
Sodium.base642bin(attributes.kekSalt),
|
||||
base64.decode(attributes.kekSalt),
|
||||
attributes.memLimit,
|
||||
attributes.opsLimit,
|
||||
).onError((e, s) {
|
||||
|
@ -231,33 +233,31 @@ class Configuration {
|
|||
_logger.info('user-key done');
|
||||
Uint8List key;
|
||||
try {
|
||||
key = CryptoUtil.decryptSync(
|
||||
Sodium.base642bin(attributes.encryptedKey),
|
||||
key = await CryptoUtil.decrypt(
|
||||
base64.decode(attributes.encryptedKey),
|
||||
kek,
|
||||
Sodium.base642bin(attributes.keyDecryptionNonce),
|
||||
base64.decode(attributes.keyDecryptionNonce),
|
||||
);
|
||||
} catch (e) {
|
||||
_logger.severe('master-key failed, incorrect password?', e);
|
||||
throw Exception("Incorrect password");
|
||||
}
|
||||
_logger.info("master-key done");
|
||||
await setKey(Sodium.bin2base64(key));
|
||||
final secretKey = CryptoUtil.decryptSync(
|
||||
Sodium.base642bin(attributes.encryptedSecretKey),
|
||||
await setKey(base64Encode(key));
|
||||
final secretKey = await CryptoUtil.decrypt(
|
||||
base64.decode(attributes.encryptedSecretKey),
|
||||
key,
|
||||
Sodium.base642bin(attributes.secretKeyDecryptionNonce),
|
||||
base64.decode(attributes.secretKeyDecryptionNonce),
|
||||
);
|
||||
_logger.info("secret-key done");
|
||||
await setSecretKey(Sodium.bin2base64(secretKey));
|
||||
await setSecretKey(base64Encode(secretKey));
|
||||
final token = CryptoUtil.openSealSync(
|
||||
Sodium.base642bin(getEncryptedToken()!),
|
||||
Sodium.base642bin(attributes.publicKey),
|
||||
base64.decode(getEncryptedToken()!),
|
||||
base64.decode(attributes.publicKey),
|
||||
secretKey,
|
||||
);
|
||||
_logger.info('appToken done');
|
||||
await setToken(
|
||||
Sodium.bin2base64(token, variant: Sodium.base64VariantUrlsafe),
|
||||
);
|
||||
await setToken(base64Url.encode(token));
|
||||
}
|
||||
|
||||
Future<void> recover(String recoveryKey) async {
|
||||
|
@ -274,29 +274,27 @@ class Configuration {
|
|||
Uint8List masterKey;
|
||||
try {
|
||||
masterKey = await CryptoUtil.decrypt(
|
||||
Sodium.base642bin(attributes!.masterKeyEncryptedWithRecoveryKey),
|
||||
Sodium.hex2bin(recoveryKey),
|
||||
Sodium.base642bin(attributes.masterKeyDecryptionNonce),
|
||||
base64.decode(attributes!.masterKeyEncryptedWithRecoveryKey),
|
||||
Uint8List.fromList(hex.decode(recoveryKey)),
|
||||
base64.decode(attributes.masterKeyDecryptionNonce),
|
||||
);
|
||||
} catch (e) {
|
||||
_logger.severe(e);
|
||||
rethrow;
|
||||
}
|
||||
await setKey(Sodium.bin2base64(masterKey));
|
||||
final secretKey = CryptoUtil.decryptSync(
|
||||
Sodium.base642bin(attributes.encryptedSecretKey),
|
||||
await setKey(base64Encode(masterKey));
|
||||
final secretKey = await CryptoUtil.decrypt(
|
||||
base64.decode(attributes.encryptedSecretKey),
|
||||
masterKey,
|
||||
Sodium.base642bin(attributes.secretKeyDecryptionNonce),
|
||||
base64.decode(attributes.secretKeyDecryptionNonce),
|
||||
);
|
||||
await setSecretKey(Sodium.bin2base64(secretKey));
|
||||
await setSecretKey(base64Encode(secretKey));
|
||||
final token = CryptoUtil.openSealSync(
|
||||
Sodium.base642bin(getEncryptedToken()!),
|
||||
Sodium.base642bin(attributes.publicKey),
|
||||
base64.decode(getEncryptedToken()!),
|
||||
base64.decode(attributes.publicKey),
|
||||
secretKey,
|
||||
);
|
||||
await setToken(
|
||||
Sodium.bin2base64(token, variant: Sodium.base64VariantUrlsafe),
|
||||
);
|
||||
await setToken(base64Url.encode(token));
|
||||
}
|
||||
|
||||
String getHttpEndpoint() {
|
||||
|
@ -400,23 +398,23 @@ class Configuration {
|
|||
}
|
||||
|
||||
Uint8List? getKey() {
|
||||
return _key == null ? null : Sodium.base642bin(_key!);
|
||||
return _key == null ? null : base64.decode(_key!);
|
||||
}
|
||||
|
||||
Uint8List? getSecretKey() {
|
||||
return _secretKey == null ? null : Sodium.base642bin(_secretKey!);
|
||||
return _secretKey == null ? null : base64.decode(_secretKey!);
|
||||
}
|
||||
|
||||
Uint8List? getAuthSecretKey() {
|
||||
return _authSecretKey == null ? null : Sodium.base642bin(_authSecretKey!);
|
||||
return _authSecretKey == null ? null : base64.decode(_authSecretKey!);
|
||||
}
|
||||
|
||||
Uint8List getRecoveryKey() {
|
||||
Future<Uint8List> getRecoveryKey() async {
|
||||
final keyAttributes = getKeyAttributes()!;
|
||||
return CryptoUtil.decryptSync(
|
||||
Sodium.base642bin(keyAttributes.recoveryKeyEncryptedWithMasterKey),
|
||||
getKey(),
|
||||
Sodium.base642bin(keyAttributes.recoveryKeyDecryptionNonce),
|
||||
return CryptoUtil.decrypt(
|
||||
base64.decode(keyAttributes.recoveryKeyEncryptedWithMasterKey),
|
||||
getKey()!,
|
||||
base64.decode(keyAttributes.recoveryKeyDecryptionNonce),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,28 +1,15 @@
|
|||
const int thumbnailSmallSize = 256;
|
||||
const int thumbnailQuality = 50;
|
||||
const int thumbnailLargeSize = 512;
|
||||
const int compressedThumbnailResolution = 1080;
|
||||
const int thumbnailDataLimit = 100 * 1024;
|
||||
const String sentryDSN =
|
||||
"https://ed4ddd6309b847ba8849935e26e9b648@sentry.ente.io/9";
|
||||
const String sentryTunnel = "https://sentry-reporter.ente.io";
|
||||
const String roadmapURL = "https://roadmap.ente.io";
|
||||
const int microSecondsInDay = 86400000000;
|
||||
const int android11SDKINT = 30;
|
||||
const int galleryLoadStartTime = -8000000000000000; // Wednesday, March 6, 1748
|
||||
const int galleryLoadEndTime = 9223372036854775807; // 2^63 -1
|
||||
|
||||
// used to identify which ente file are available in app cache
|
||||
// todo: 6Jun22: delete old media identifier after 3 months
|
||||
const String oldSharedMediaIdentifier = 'ente-shared://';
|
||||
const String sharedMediaIdentifier = 'ente-shared-media://';
|
||||
|
||||
const int maxLivePhotoToastCount = 2;
|
||||
const String livePhotoToastCounterKey = "show_live_photo_toast";
|
||||
|
||||
const thumbnailDiskLoadDeferDuration = Duration(milliseconds: 40);
|
||||
const thumbnailServerLoadDeferDuration = Duration(milliseconds: 80);
|
||||
|
||||
// 256 bit key maps to 24 words
|
||||
// https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki#Generating_the_mnemonic
|
||||
const mnemonicKeyWordCount = 24;
|
||||
|
|
|
@ -11,13 +11,17 @@ class Network {
|
|||
late Dio _dio;
|
||||
|
||||
Future<void> init() async {
|
||||
await FkUserAgent.init();
|
||||
String userAgent = "";
|
||||
if (Platform.isAndroid || Platform.isIOS) {
|
||||
await FkUserAgent.init();
|
||||
userAgent = FkUserAgent.userAgent ?? "";
|
||||
}
|
||||
final packageInfo = await PackageInfo.fromPlatform();
|
||||
_dio = Dio(
|
||||
BaseOptions(
|
||||
connectTimeout: kConnectTimeout,
|
||||
headers: {
|
||||
HttpHeaders.userAgentHeader: FkUserAgent.userAgent,
|
||||
HttpHeaders.userAgentHeader: userAgent,
|
||||
'X-Client-Version': packageInfo.version,
|
||||
'X-Client-Package': packageInfo.packageName,
|
||||
},
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// @dart=2.9
|
||||
import 'dart:io';
|
||||
|
||||
import "package:ente_auth/app/view/app.dart";
|
||||
import 'package:ente_auth/core/configuration.dart';
|
||||
import 'package:ente_auth/core/constants.dart';
|
||||
|
@ -19,11 +21,17 @@ import 'package:ente_auth/utils/crypto_util.dart';
|
|||
import "package:flutter/material.dart";
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:window_size/window_size.dart';
|
||||
|
||||
final _logger = Logger("main");
|
||||
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
if (Platform.isWindows || Platform.isLinux || Platform.isMacOS) {
|
||||
setWindowTitle("ente Auth");
|
||||
setWindowMinSize(const Size(375, 750));
|
||||
setWindowMaxSize(const Size(375, 750));
|
||||
}
|
||||
await _runInForeground();
|
||||
}
|
||||
|
||||
|
@ -58,7 +66,7 @@ Future _runWithLogs(Function() function, {String prefix = ""}) async {
|
|||
}
|
||||
|
||||
Future<void> _init(bool bool, {String via}) async {
|
||||
CryptoUtil.init();
|
||||
await CryptoUtil.init();
|
||||
await PreferenceService.instance.init();
|
||||
await CodeStore.instance.init();
|
||||
await Configuration.instance.init();
|
||||
|
|
|
@ -16,7 +16,6 @@ import 'package:ente_auth/models/authenticator/local_auth_entity.dart';
|
|||
import 'package:ente_auth/store/authenticator_db.dart';
|
||||
import 'package:ente_auth/utils/crypto_util.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_sodium/flutter_sodium.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
|
@ -55,9 +54,9 @@ class AuthenticatorService {
|
|||
for (LocalAuthEntity e in result) {
|
||||
try {
|
||||
final decryptedValue = await CryptoUtil.decryptChaCha(
|
||||
Sodium.base642bin(e.encryptedData),
|
||||
base64.decode(e.encryptedData),
|
||||
key,
|
||||
Sodium.base642bin(e.header),
|
||||
base64.decode(e.header),
|
||||
);
|
||||
final hasSynced = !(e.id == null || e.shouldSync);
|
||||
entities.add(
|
||||
|
@ -80,8 +79,8 @@ class AuthenticatorService {
|
|||
utf8.encode(plainText) as Uint8List,
|
||||
key,
|
||||
);
|
||||
String encryptedData = Sodium.bin2base64(encryptedKeyData.encryptedData!);
|
||||
String header = Sodium.bin2base64(encryptedKeyData.header!);
|
||||
String encryptedData = base64Encode(encryptedKeyData.encryptedData!);
|
||||
String header = base64Encode(encryptedKeyData.header!);
|
||||
final insertedID = await _db.insert(encryptedData, header);
|
||||
if (shouldSync) {
|
||||
unawaited(sync());
|
||||
|
@ -99,8 +98,8 @@ class AuthenticatorService {
|
|||
utf8.encode(plainText) as Uint8List,
|
||||
key,
|
||||
);
|
||||
String encryptedData = Sodium.bin2base64(encryptedKeyData.encryptedData!);
|
||||
String header = Sodium.bin2base64(encryptedKeyData.header!);
|
||||
String encryptedData = base64Encode(encryptedKeyData.encryptedData!);
|
||||
String header = base64Encode(encryptedKeyData.header!);
|
||||
final int affectedRows =
|
||||
await _db.updateEntry(generatedID, encryptedData, header);
|
||||
assert(
|
||||
|
@ -207,22 +206,22 @@ class AuthenticatorService {
|
|||
}
|
||||
try {
|
||||
final AuthKey response = await _gateway.getKey();
|
||||
final authKey = CryptoUtil.decryptSync(
|
||||
Sodium.base642bin(response.encryptedKey),
|
||||
_config.getKey(),
|
||||
Sodium.base642bin(response.header),
|
||||
final authKey = await CryptoUtil.decrypt(
|
||||
base64.decode(response.encryptedKey),
|
||||
_config.getKey()!,
|
||||
base64.decode(response.header),
|
||||
);
|
||||
await _config.setAuthSecretKey(Sodium.bin2base64(authKey));
|
||||
await _config.setAuthSecretKey(base64Encode(authKey));
|
||||
return authKey;
|
||||
} on AuthenticatorKeyNotFound catch (e) {
|
||||
_logger.info("AuthenticatorKeyNotFound generating key ${e.stackTrace}");
|
||||
final key = CryptoUtil.generateKey();
|
||||
final encryptedKeyData = CryptoUtil.encryptSync(key, _config.getKey()!);
|
||||
final encryptedKeyData = await CryptoUtil.encrypt(key, _config.getKey()!);
|
||||
await _gateway.createKey(
|
||||
Sodium.bin2base64(encryptedKeyData.encryptedData!),
|
||||
Sodium.bin2base64(encryptedKeyData.nonce!),
|
||||
base64Encode(encryptedKeyData.encryptedData!),
|
||||
base64Encode(encryptedKeyData.nonce!),
|
||||
);
|
||||
await _config.setAuthSecretKey(Sodium.bin2base64(key));
|
||||
await _config.setAuthSecretKey(base64Encode(key));
|
||||
return key;
|
||||
} catch (e, s) {
|
||||
_logger.severe("Failed to getOrCreateAuthDataKey", e, s);
|
||||
|
|
|
@ -65,6 +65,10 @@ class LocalAuthenticationService {
|
|||
}
|
||||
|
||||
Future<bool> _isLocalAuthSupportedOnDevice() async {
|
||||
return await LocalAuthentication().isDeviceSupported();
|
||||
try {
|
||||
return await LocalAuthentication().isDeviceSupported();
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
// @dart=2.9
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:bip39/bip39.dart' as bip39;
|
||||
import 'package:convert/convert.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:ente_auth/core/configuration.dart';
|
||||
import 'package:ente_auth/core/constants.dart';
|
||||
|
@ -24,7 +27,6 @@ import 'package:ente_auth/utils/crypto_util.dart';
|
|||
import 'package:ente_auth/utils/dialog_util.dart';
|
||||
import 'package:ente_auth/utils/toast_util.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_sodium/flutter_sodium.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
class UserService {
|
||||
|
@ -630,11 +632,11 @@ class UserService {
|
|||
}
|
||||
recoveryKey = bip39.mnemonicToEntropy(recoveryKey);
|
||||
}
|
||||
secret = Sodium.bin2base64(
|
||||
secret = base64Encode(
|
||||
await CryptoUtil.decrypt(
|
||||
Sodium.base642bin(encryptedSecret),
|
||||
Sodium.hex2bin(recoveryKey.trim()),
|
||||
Sodium.base642bin(secretDecryptionNonce),
|
||||
base64.decode(encryptedSecret),
|
||||
hex.decode(recoveryKey.trim()),
|
||||
base64.decode(secretDecryptionNonce),
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
|
|
|
@ -11,7 +11,6 @@ import 'package:ente_auth/ui/common/gradient_button.dart';
|
|||
import 'package:ente_auth/utils/crypto_util.dart';
|
||||
import 'package:ente_auth/utils/email_util.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_sodium/flutter_sodium.dart';
|
||||
|
||||
class DeleteAccountPage extends StatelessWidget {
|
||||
const DeleteAccountPage({
|
||||
|
@ -165,8 +164,8 @@ class DeleteAccountPage extends StatelessWidget {
|
|||
return;
|
||||
}
|
||||
final decryptChallenge = CryptoUtil.openSealSync(
|
||||
Sodium.base642bin(response.encryptedChallenge),
|
||||
Sodium.base642bin(Configuration.instance.getKeyAttributes().publicKey),
|
||||
base64.decode(response.encryptedChallenge),
|
||||
base64.decode(Configuration.instance.getKeyAttributes().publicKey),
|
||||
Configuration.instance.getSecretKey(),
|
||||
);
|
||||
final challengeResponseStr = utf8.decode(decryptChallenge);
|
||||
|
|
|
@ -208,9 +208,9 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
|
|||
}
|
||||
|
||||
List<Widget> _saveOptions(BuildContext context, String recoveryKey) {
|
||||
final List<Widget> childrens = [];
|
||||
final List<Widget> children = [];
|
||||
if (!_hasTriedToSave) {
|
||||
childrens.add(
|
||||
children.add(
|
||||
ElevatedButton(
|
||||
style: Theme.of(context).colorScheme.optionalActionButtonStyle,
|
||||
onPressed: () async {
|
||||
|
@ -219,10 +219,10 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
|
|||
child: const Text('Do this later'),
|
||||
),
|
||||
);
|
||||
childrens.add(const SizedBox(height: 10));
|
||||
children.add(const SizedBox(height: 10));
|
||||
}
|
||||
|
||||
childrens.add(
|
||||
children.add(
|
||||
GradientButton(
|
||||
onTap: () async {
|
||||
await _shareRecoveryKey(recoveryKey);
|
||||
|
@ -231,8 +231,8 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
|
|||
),
|
||||
);
|
||||
if (_hasTriedToSave) {
|
||||
childrens.add(const SizedBox(height: 10));
|
||||
childrens.add(
|
||||
children.add(const SizedBox(height: 10));
|
||||
children.add(
|
||||
ElevatedButton(
|
||||
child: Text(widget.doneText),
|
||||
onPressed: () async {
|
||||
|
@ -241,8 +241,8 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
|
|||
),
|
||||
);
|
||||
}
|
||||
childrens.add(const SizedBox(height: 12));
|
||||
return childrens;
|
||||
children.add(const SizedBox(height: 12));
|
||||
return children;
|
||||
}
|
||||
|
||||
Future _shareRecoveryKey(String recoveryKey) async {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
import 'dart:ui';
|
||||
|
||||
import 'package:bip39/bip39.dart' as bip39;
|
||||
import 'package:convert/convert.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:ente_auth/core/configuration.dart';
|
||||
import 'package:ente_auth/core/event_bus.dart';
|
||||
|
@ -16,7 +17,6 @@ import 'package:ente_auth/ui/common/gradient_button.dart';
|
|||
import 'package:ente_auth/utils/dialog_util.dart';
|
||||
import 'package:ente_auth/utils/navigation_util.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_sodium/flutter_sodium.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
class VerifyRecoveryPage extends StatefulWidget {
|
||||
|
@ -36,7 +36,7 @@ class _VerifyRecoveryPageState extends State<VerifyRecoveryPage> {
|
|||
try {
|
||||
final String inputKey = _recoveryKey.text.trim();
|
||||
final String recoveryKey =
|
||||
Sodium.bin2hex(Configuration.instance.getRecoveryKey());
|
||||
hex.encode(await Configuration.instance.getRecoveryKey());
|
||||
final String recoveryKeyWords = bip39.entropyToMnemonic(recoveryKey);
|
||||
if (inputKey == recoveryKey || inputKey == recoveryKeyWords) {
|
||||
try {
|
||||
|
@ -97,7 +97,7 @@ class _VerifyRecoveryPageState extends State<VerifyRecoveryPage> {
|
|||
if (hasAuthenticated) {
|
||||
String recoveryKey;
|
||||
try {
|
||||
recoveryKey = Sodium.bin2hex(Configuration.instance.getRecoveryKey());
|
||||
recoveryKey = hex.encode(await Configuration.instance.getRecoveryKey());
|
||||
routeToPage(
|
||||
context,
|
||||
RecoveryKeyPage(
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// @dart=2.9
|
||||
|
||||
import 'package:convert/convert.dart';
|
||||
import 'package:ente_auth/core/configuration.dart';
|
||||
import 'package:ente_auth/services/local_authentication_service.dart';
|
||||
import 'package:ente_auth/theme/ente_theme.dart';
|
||||
|
@ -13,7 +14,6 @@ import 'package:ente_auth/ui/settings/common_settings.dart';
|
|||
import 'package:ente_auth/utils/dialog_util.dart';
|
||||
import 'package:ente_auth/utils/navigation_util.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_sodium/flutter_sodium.dart';
|
||||
|
||||
class AccountSectionWidget extends StatelessWidget {
|
||||
AccountSectionWidget({Key key}) : super(key: key);
|
||||
|
@ -48,7 +48,7 @@ class AccountSectionWidget extends StatelessWidget {
|
|||
String recoveryKey;
|
||||
try {
|
||||
recoveryKey =
|
||||
Sodium.bin2hex(Configuration.instance.getRecoveryKey());
|
||||
hex.encode(await Configuration.instance.getRecoveryKey());
|
||||
} catch (e) {
|
||||
showGenericErrorDialog(context);
|
||||
return;
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
// @dart=2.9
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:ente_auth/core/configuration.dart';
|
||||
import 'package:ente_auth/ui/settings/common_settings.dart';
|
||||
import 'package:ente_auth/ui/settings/settings_section_title.dart';
|
||||
import 'package:ente_auth/ui/settings/settings_text_item.dart';
|
||||
import 'package:expandable/expandable.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_sodium/flutter_sodium.dart';
|
||||
|
||||
class DebugSectionWidget extends StatelessWidget {
|
||||
const DebugSectionWidget({Key key}) : super(key: key);
|
||||
|
@ -48,7 +49,7 @@ class DebugSectionWidget extends StatelessWidget {
|
|||
"Key",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text(Sodium.bin2base64(Configuration.instance.getKey())),
|
||||
Text(base64Encode(Configuration.instance.getKey())),
|
||||
const Padding(padding: EdgeInsets.all(12)),
|
||||
const Text(
|
||||
"Encrypted Key",
|
||||
|
|
|
@ -1,183 +1,106 @@
|
|||
import 'dart:io' as io;
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:computer/computer.dart';
|
||||
import 'package:ente_auth/models/derived_key_result.dart';
|
||||
import 'package:ente_auth/models/encryption_result.dart';
|
||||
import 'package:flutter_sodium/flutter_sodium.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:sodium_libs/sodium_libs.dart';
|
||||
|
||||
const int encryptionChunkSize = 4 * 1024 * 1024;
|
||||
final int decryptionChunkSize =
|
||||
encryptionChunkSize + Sodium.cryptoSecretstreamXchacha20poly1305Abytes;
|
||||
|
||||
Uint8List cryptoSecretboxEasy(Map<String, dynamic> args) {
|
||||
return Sodium.cryptoSecretboxEasy(args["source"], args["nonce"], args["key"]);
|
||||
Future<Uint8List> cryptoSecretboxEasy(Map<String, dynamic> args) async {
|
||||
final sodium = await SodiumInit.init();
|
||||
return sodium.crypto.secretBox
|
||||
.easy(message: args["source"], nonce: args["nonce"], key: args["key"]);
|
||||
}
|
||||
|
||||
Uint8List cryptoSecretboxOpenEasy(Map<String, dynamic> args) {
|
||||
return Sodium.cryptoSecretboxOpenEasy(
|
||||
args["cipher"],
|
||||
args["nonce"],
|
||||
args["key"],
|
||||
Future<Uint8List> cryptoSecretboxOpenEasy(Map<String, dynamic> args) async {
|
||||
final sodium = await SodiumInit.init();
|
||||
return sodium.crypto.secretBox.openEasy(
|
||||
cipherText: args["cipher"],
|
||||
nonce: args["nonce"],
|
||||
key: SecureKey.fromList(sodium, args["key"]),
|
||||
);
|
||||
}
|
||||
|
||||
Uint8List cryptoPwHash(Map<String, dynamic> args) {
|
||||
return Sodium.cryptoPwhash(
|
||||
Sodium.cryptoSecretboxKeybytes,
|
||||
args["password"],
|
||||
args["salt"],
|
||||
args["opsLimit"],
|
||||
args["memLimit"],
|
||||
Sodium.cryptoPwhashAlgDefault,
|
||||
);
|
||||
Future<Uint8List> cryptoPwHash(Map<String, dynamic> args) async {
|
||||
final sodium = await SodiumInit.init();
|
||||
Logger("CryptoUtil").info("Sodium initialized: " + sodium.version.toString());
|
||||
return CryptoUtil.sodium.crypto.pwhash
|
||||
.call(
|
||||
outLen: CryptoUtil.sodium.crypto.secretBox.keyBytes,
|
||||
password: args["password"],
|
||||
salt: args["salt"],
|
||||
opsLimit: args["opsLimit"],
|
||||
memLimit: args["memLimit"],
|
||||
)
|
||||
.extractBytes();
|
||||
}
|
||||
|
||||
Uint8List cryptoGenericHash(Map<String, dynamic> args) {
|
||||
final sourceFile = io.File(args["sourceFilePath"]);
|
||||
final sourceFileLength = sourceFile.lengthSync();
|
||||
final inputFile = sourceFile.openSync(mode: io.FileMode.read);
|
||||
final state =
|
||||
Sodium.cryptoGenerichashInit(null, Sodium.cryptoGenerichashBytesMax);
|
||||
var bytesRead = 0;
|
||||
bool isDone = false;
|
||||
while (!isDone) {
|
||||
var chunkSize = encryptionChunkSize;
|
||||
if (bytesRead + chunkSize >= sourceFileLength) {
|
||||
chunkSize = sourceFileLength - bytesRead;
|
||||
isDone = true;
|
||||
}
|
||||
final buffer = inputFile.readSync(chunkSize);
|
||||
bytesRead += chunkSize;
|
||||
Sodium.cryptoGenerichashUpdate(state, buffer);
|
||||
Future<EncryptionResult> chachaEncryptData(Map<String, dynamic> args) async {
|
||||
final sodium = await SodiumInit.init();
|
||||
|
||||
Stream<SecretStreamPlainMessage> getStream(Uint8List data) async* {
|
||||
yield SecretStreamPlainMessage(data, tag: SecretStreamMessageTag.finalPush);
|
||||
}
|
||||
inputFile.closeSync();
|
||||
return Sodium.cryptoGenerichashFinal(state, Sodium.cryptoGenerichashBytesMax);
|
||||
}
|
||||
|
||||
EncryptionResult chachaEncryptData(Map<String, dynamic> args) {
|
||||
final initPushResult =
|
||||
Sodium.cryptoSecretstreamXchacha20poly1305InitPush(args["key"]);
|
||||
final encryptedData = Sodium.cryptoSecretstreamXchacha20poly1305Push(
|
||||
initPushResult.state,
|
||||
args["source"],
|
||||
null,
|
||||
Sodium.cryptoSecretstreamXchacha20poly1305TagFinal,
|
||||
final resultStream = sodium.crypto.secretStream.pushEx(
|
||||
key: SecureKey.fromList(sodium, args["key"]),
|
||||
messageStream: getStream(args["source"]),
|
||||
);
|
||||
return EncryptionResult(
|
||||
encryptedData: encryptedData,
|
||||
header: initPushResult.header,
|
||||
);
|
||||
}
|
||||
|
||||
Future<EncryptionResult> chachaEncryptFile(Map<String, dynamic> args) async {
|
||||
final encryptionStartTime = DateTime.now().millisecondsSinceEpoch;
|
||||
final logger = Logger("ChaChaEncrypt");
|
||||
final sourceFile = io.File(args["sourceFilePath"]);
|
||||
final destinationFile = io.File(args["destinationFilePath"]);
|
||||
final sourceFileLength = await sourceFile.length();
|
||||
logger.info("Encrypting file of size " + sourceFileLength.toString());
|
||||
|
||||
final inputFile = sourceFile.openSync(mode: io.FileMode.read);
|
||||
final key = args["key"] ?? Sodium.cryptoSecretstreamXchacha20poly1305Keygen();
|
||||
final initPushResult =
|
||||
Sodium.cryptoSecretstreamXchacha20poly1305InitPush(key);
|
||||
var bytesRead = 0;
|
||||
var tag = Sodium.cryptoSecretstreamXchacha20poly1305TagMessage;
|
||||
while (tag != Sodium.cryptoSecretstreamXchacha20poly1305TagFinal) {
|
||||
var chunkSize = encryptionChunkSize;
|
||||
if (bytesRead + chunkSize >= sourceFileLength) {
|
||||
chunkSize = sourceFileLength - bytesRead;
|
||||
tag = Sodium.cryptoSecretstreamXchacha20poly1305TagFinal;
|
||||
Uint8List? header, encryptedData;
|
||||
await for (final value in resultStream) {
|
||||
if (header == null) {
|
||||
header = value.message;
|
||||
continue;
|
||||
} else {
|
||||
encryptedData = value.message;
|
||||
}
|
||||
final buffer = inputFile.readSync(chunkSize);
|
||||
bytesRead += chunkSize;
|
||||
final encryptedData = Sodium.cryptoSecretstreamXchacha20poly1305Push(
|
||||
initPushResult.state,
|
||||
buffer,
|
||||
null,
|
||||
tag,
|
||||
);
|
||||
await destinationFile.writeAsBytes(encryptedData, mode: io.FileMode.append);
|
||||
}
|
||||
inputFile.closeSync();
|
||||
|
||||
logger.info(
|
||||
"Encryption time: " +
|
||||
(DateTime.now().millisecondsSinceEpoch - encryptionStartTime)
|
||||
.toString(),
|
||||
);
|
||||
|
||||
return EncryptionResult(key: key, header: initPushResult.header);
|
||||
return EncryptionResult(encryptedData: encryptedData, header: header);
|
||||
}
|
||||
|
||||
Future<void> chachaDecryptFile(Map<String, dynamic> args) async {
|
||||
final logger = Logger("ChaChaDecrypt");
|
||||
final decryptionStartTime = DateTime.now().millisecondsSinceEpoch;
|
||||
final sourceFile = io.File(args["sourceFilePath"]);
|
||||
final destinationFile = io.File(args["destinationFilePath"]);
|
||||
final sourceFileLength = await sourceFile.length();
|
||||
logger.info("Decrypting file of size " + sourceFileLength.toString());
|
||||
Future<Uint8List> chachaDecryptData(Map<String, dynamic> args) async {
|
||||
final sodium = await SodiumInit.init();
|
||||
|
||||
final inputFile = sourceFile.openSync(mode: io.FileMode.read);
|
||||
final pullState = Sodium.cryptoSecretstreamXchacha20poly1305InitPull(
|
||||
args["header"],
|
||||
args["key"],
|
||||
);
|
||||
|
||||
var bytesRead = 0;
|
||||
var tag = Sodium.cryptoSecretstreamXchacha20poly1305TagMessage;
|
||||
while (tag != Sodium.cryptoSecretstreamXchacha20poly1305TagFinal) {
|
||||
var chunkSize = decryptionChunkSize;
|
||||
if (bytesRead + chunkSize >= sourceFileLength) {
|
||||
chunkSize = sourceFileLength - bytesRead;
|
||||
}
|
||||
final buffer = inputFile.readSync(chunkSize);
|
||||
bytesRead += chunkSize;
|
||||
final pullResult =
|
||||
Sodium.cryptoSecretstreamXchacha20poly1305Pull(pullState, buffer, null);
|
||||
await destinationFile.writeAsBytes(pullResult.m, mode: io.FileMode.append);
|
||||
tag = pullResult.tag;
|
||||
Stream<SecretStreamCipherMessage> getStream() async* {
|
||||
yield SecretStreamCipherMessage(args["header"]);
|
||||
yield SecretStreamCipherMessage(args["source"]);
|
||||
}
|
||||
inputFile.closeSync();
|
||||
|
||||
logger.info(
|
||||
"ChaCha20 Decryption time: " +
|
||||
(DateTime.now().millisecondsSinceEpoch - decryptionStartTime)
|
||||
.toString(),
|
||||
final resultStream = sodium.crypto.secretStream.pullEx(
|
||||
key: SecureKey.fromList(sodium, args["key"]),
|
||||
cipherStream: getStream(),
|
||||
);
|
||||
}
|
||||
|
||||
Uint8List chachaDecryptData(Map<String, dynamic> args) {
|
||||
final pullState = Sodium.cryptoSecretstreamXchacha20poly1305InitPull(
|
||||
args["header"],
|
||||
args["key"],
|
||||
);
|
||||
final pullResult = Sodium.cryptoSecretstreamXchacha20poly1305Pull(
|
||||
pullState,
|
||||
args["source"],
|
||||
null,
|
||||
);
|
||||
return pullResult.m;
|
||||
await for (final result in resultStream) {
|
||||
return result.message;
|
||||
}
|
||||
return Uint8List(0);
|
||||
}
|
||||
|
||||
class CryptoUtil {
|
||||
static final Computer _computer = Computer();
|
||||
static late Sodium sodium;
|
||||
|
||||
static init() {
|
||||
static init() async {
|
||||
_computer.turnOn(workersCount: 4);
|
||||
// Sodium.init();
|
||||
sodium = await SodiumInit.init();
|
||||
Logger("CryptoUtil")
|
||||
.info("Sodium initialized: " + sodium.version.toString());
|
||||
}
|
||||
|
||||
static EncryptionResult encryptSync(Uint8List source, Uint8List key) {
|
||||
final nonce = Sodium.randombytesBuf(Sodium.cryptoSecretboxNoncebytes);
|
||||
static Future<EncryptionResult> encrypt(
|
||||
Uint8List source,
|
||||
Uint8List key,
|
||||
) async {
|
||||
final nonce = sodium.randombytes.buf(sodium.crypto.secretBox.nonceBytes);
|
||||
|
||||
final args = <String, dynamic>{};
|
||||
args["source"] = source;
|
||||
args["nonce"] = nonce;
|
||||
args["key"] = key;
|
||||
final encryptedData = cryptoSecretboxEasy(args);
|
||||
final encryptedData = await cryptoSecretboxEasy(args);
|
||||
|
||||
return EncryptionResult(
|
||||
key: key,
|
||||
nonce: nonce,
|
||||
|
@ -190,24 +113,12 @@ class CryptoUtil {
|
|||
Uint8List key,
|
||||
Uint8List nonce,
|
||||
) async {
|
||||
final args = <String, dynamic>{};
|
||||
args["cipher"] = cipher;
|
||||
args["nonce"] = nonce;
|
||||
args["key"] = key;
|
||||
return _computer.compute(cryptoSecretboxOpenEasy, param: args);
|
||||
}
|
||||
|
||||
static Uint8List decryptSync(
|
||||
Uint8List cipher,
|
||||
Uint8List? key,
|
||||
Uint8List nonce,
|
||||
) {
|
||||
assert(key != null, "key can not be null");
|
||||
final args = <String, dynamic>{};
|
||||
args["cipher"] = cipher;
|
||||
args["nonce"] = nonce;
|
||||
args["key"] = key;
|
||||
return cryptoSecretboxOpenEasy(args);
|
||||
final sodium = await SodiumInit.init();
|
||||
return sodium.crypto.secretBox.openEasy(
|
||||
cipherText: cipher,
|
||||
nonce: nonce,
|
||||
key: SecureKey.fromList(sodium, key),
|
||||
);
|
||||
}
|
||||
|
||||
static Future<EncryptionResult> encryptChaCha(
|
||||
|
@ -229,45 +140,19 @@ class CryptoUtil {
|
|||
args["source"] = source;
|
||||
args["key"] = key;
|
||||
args["header"] = header;
|
||||
return _computer.compute(chachaDecryptData, param: args);
|
||||
}
|
||||
|
||||
static Future<EncryptionResult> encryptFile(
|
||||
String sourceFilePath,
|
||||
String destinationFilePath, {
|
||||
Uint8List? key,
|
||||
}) {
|
||||
final args = <String, dynamic>{};
|
||||
args["sourceFilePath"] = sourceFilePath;
|
||||
args["destinationFilePath"] = destinationFilePath;
|
||||
args["key"] = key;
|
||||
return _computer.compute(chachaEncryptFile, param: args);
|
||||
}
|
||||
|
||||
static Future<void> decryptFile(
|
||||
String sourceFilePath,
|
||||
String destinationFilePath,
|
||||
Uint8List header,
|
||||
Uint8List key,
|
||||
) {
|
||||
final args = <String, dynamic>{};
|
||||
args["sourceFilePath"] = sourceFilePath;
|
||||
args["destinationFilePath"] = destinationFilePath;
|
||||
args["header"] = header;
|
||||
args["key"] = key;
|
||||
return _computer.compute(chachaDecryptFile, param: args);
|
||||
return chachaDecryptData(args);
|
||||
}
|
||||
|
||||
static Uint8List generateKey() {
|
||||
return Sodium.cryptoSecretboxKeygen();
|
||||
return sodium.crypto.secretBox.keygen().extractBytes();
|
||||
}
|
||||
|
||||
static Uint8List getSaltToDeriveKey() {
|
||||
return Sodium.randombytesBuf(Sodium.cryptoPwhashSaltbytes);
|
||||
return sodium.randombytes.buf(sodium.crypto.pwhash.saltBytes);
|
||||
}
|
||||
|
||||
static Future<KeyPair> generateKeyPair() async {
|
||||
return Sodium.cryptoBoxKeypair();
|
||||
return sodium.crypto.box.keyPair();
|
||||
}
|
||||
|
||||
static Uint8List openSealSync(
|
||||
|
@ -275,11 +160,15 @@ class CryptoUtil {
|
|||
Uint8List publicKey,
|
||||
Uint8List secretKey,
|
||||
) {
|
||||
return Sodium.cryptoBoxSealOpen(input, publicKey, secretKey);
|
||||
return sodium.crypto.box.sealOpen(
|
||||
cipherText: input,
|
||||
publicKey: publicKey,
|
||||
secretKey: SecureKey.fromList(sodium, secretKey),
|
||||
);
|
||||
}
|
||||
|
||||
static Uint8List sealSync(Uint8List input, Uint8List publicKey) {
|
||||
return Sodium.cryptoBoxSeal(input, publicKey);
|
||||
return sodium.crypto.box.seal(message: input, publicKey: publicKey);
|
||||
}
|
||||
|
||||
static Future<DerivedKeyResult> deriveSensitiveKey(
|
||||
|
@ -287,11 +176,11 @@ class CryptoUtil {
|
|||
Uint8List salt,
|
||||
) async {
|
||||
final logger = Logger("pwhash");
|
||||
int memLimit = Sodium.cryptoPwhashMemlimitSensitive;
|
||||
int opsLimit = Sodium.cryptoPwhashOpslimitSensitive;
|
||||
int memLimit = sodium.crypto.pwhash.memLimitSensitive;
|
||||
int opsLimit = sodium.crypto.pwhash.opsLimitSensitive;
|
||||
Uint8List key;
|
||||
while (memLimit > Sodium.cryptoPwhashMemlimitMin &&
|
||||
opsLimit < Sodium.cryptoPwhashOpslimitMax) {
|
||||
while (memLimit > sodium.crypto.pwhash.memLimitMin &&
|
||||
opsLimit < sodium.crypto.pwhash.opsLimitMax) {
|
||||
try {
|
||||
key = await deriveKey(password, salt, memLimit, opsLimit);
|
||||
return DerivedKeyResult(key, memLimit, opsLimit);
|
||||
|
@ -309,24 +198,27 @@ class CryptoUtil {
|
|||
Uint8List salt,
|
||||
int memLimit,
|
||||
int opsLimit,
|
||||
) {
|
||||
return _computer.compute(
|
||||
cryptoPwHash,
|
||||
param: {
|
||||
"password": password,
|
||||
"salt": salt,
|
||||
"memLimit": memLimit,
|
||||
"opsLimit": opsLimit,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
static Future<Uint8List> getHash(io.File source) {
|
||||
return _computer.compute(
|
||||
cryptoGenericHash,
|
||||
param: {
|
||||
"sourceFilePath": source.path,
|
||||
},
|
||||
);
|
||||
) async {
|
||||
final sodium = await SodiumInit.init();
|
||||
Logger("CryptoUtil")
|
||||
.info("Sodium initialized: " + sodium.version.toString());
|
||||
return sodium.crypto.pwhash
|
||||
.call(
|
||||
outLen: CryptoUtil.sodium.crypto.secretBox.keyBytes,
|
||||
password: Int8List.fromList(password),
|
||||
salt: salt,
|
||||
opsLimit: opsLimit,
|
||||
memLimit: memLimit,
|
||||
)
|
||||
.extractBytes();
|
||||
// return _computer.compute(
|
||||
// cryptoPwHash,
|
||||
// param: {
|
||||
// "password": password,
|
||||
// "salt": salt,
|
||||
// "memLimit": memLimit,
|
||||
// "opsLimit": opsLimit,
|
||||
// },
|
||||
// );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
|
||||
#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
|
||||
#include <sentry_flutter/sentry_flutter_plugin.h>
|
||||
#include <sodium_libs/sodium_libs_plugin.h>
|
||||
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||
#include <window_size/window_size_plugin.h>
|
||||
|
||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar =
|
||||
|
@ -17,7 +19,13 @@ void fl_register_plugins(FlPluginRegistry* registry) {
|
|||
g_autoptr(FlPluginRegistrar) sentry_flutter_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "SentryFlutterPlugin");
|
||||
sentry_flutter_plugin_register_with_registrar(sentry_flutter_registrar);
|
||||
g_autoptr(FlPluginRegistrar) sodium_libs_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "SodiumLibsPlugin");
|
||||
sodium_libs_plugin_register_with_registrar(sodium_libs_registrar);
|
||||
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
||||
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
||||
g_autoptr(FlPluginRegistrar) window_size_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "WindowSizePlugin");
|
||||
window_size_plugin_register_with_registrar(window_size_registrar);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
flutter_secure_storage_linux
|
||||
sentry_flutter
|
||||
sodium_libs
|
||||
url_launcher_linux
|
||||
window_size
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
|
|
|
@ -13,8 +13,10 @@ import path_provider_macos
|
|||
import sentry_flutter
|
||||
import share_plus_macos
|
||||
import shared_preferences_macos
|
||||
import sodium_libs
|
||||
import sqflite
|
||||
import url_launcher_macos
|
||||
import window_size
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin"))
|
||||
|
@ -25,6 +27,8 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||
SentryFlutterPlugin.register(with: registry.registrar(forPlugin: "SentryFlutterPlugin"))
|
||||
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
|
||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||
SodiumLibsPlugin.register(with: registry.registrar(forPlugin: "SodiumLibsPlugin"))
|
||||
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||
WindowSizePlugin.register(with: registry.registrar(forPlugin: "WindowSizePlugin"))
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ PODS:
|
|||
- connectivity_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
- Reachability
|
||||
- flutter_local_notifications (0.0.1):
|
||||
- FlutterMacOS
|
||||
- flutter_secure_storage_macos (3.3.1):
|
||||
- FlutterMacOS
|
||||
- FlutterMacOS (1.0.0)
|
||||
|
@ -13,35 +15,54 @@ PODS:
|
|||
- path_provider_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
- Reachability (3.2)
|
||||
- Sentry/HybridSDK (7.30.2)
|
||||
- sentry_flutter (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- Sentry/HybridSDK (= 7.30.2)
|
||||
- share_plus_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
- shared_preferences_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
- Sodium (0.9.1)
|
||||
- sodium_libs (1.2.0):
|
||||
- FlutterMacOS
|
||||
- Sodium
|
||||
- sqflite (0.0.2):
|
||||
- FlutterMacOS
|
||||
- FMDB (>= 2.7.5)
|
||||
- url_launcher_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
- window_size (0.0.2):
|
||||
- FlutterMacOS
|
||||
|
||||
DEPENDENCIES:
|
||||
- connectivity_macos (from `Flutter/ephemeral/.symlinks/plugins/connectivity_macos/macos`)
|
||||
- flutter_local_notifications (from `Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos`)
|
||||
- flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`)
|
||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||
- package_info_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus_macos/macos`)
|
||||
- path_provider_macos (from `Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos`)
|
||||
- sentry_flutter (from `Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos`)
|
||||
- share_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos`)
|
||||
- shared_preferences_macos (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_macos/macos`)
|
||||
- sodium_libs (from `Flutter/ephemeral/.symlinks/plugins/sodium_libs/macos`)
|
||||
- sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`)
|
||||
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
||||
- window_size (from `Flutter/ephemeral/.symlinks/plugins/window_size/macos`)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- FMDB
|
||||
- Reachability
|
||||
- Sentry
|
||||
- Sodium
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
connectivity_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/connectivity_macos/macos
|
||||
flutter_local_notifications:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos
|
||||
flutter_secure_storage_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos
|
||||
FlutterMacOS:
|
||||
|
@ -50,27 +71,39 @@ EXTERNAL SOURCES:
|
|||
:path: Flutter/ephemeral/.symlinks/plugins/package_info_plus_macos/macos
|
||||
path_provider_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos
|
||||
sentry_flutter:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos
|
||||
share_plus_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos
|
||||
shared_preferences_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_macos/macos
|
||||
sodium_libs:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/sodium_libs/macos
|
||||
sqflite:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/sqflite/macos
|
||||
url_launcher_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
|
||||
window_size:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/window_size/macos
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
connectivity_macos: 5dae6ee11d320fac7c05f0d08bd08fc32b5514d9
|
||||
flutter_local_notifications: 3805ca215b2fb7f397d78b66db91f6a747af52e4
|
||||
flutter_secure_storage_macos: 6ceee8fbc7f484553ad17f79361b556259df89aa
|
||||
FlutterMacOS: ae6af50a8ea7d6103d888583d46bd8328a7e9811
|
||||
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
||||
package_info_plus_macos: f010621b07802a241d96d01876d6705f15e77c1c
|
||||
path_provider_macos: 3c0c3b4b0d4a76d2bf989a913c2de869c5641a19
|
||||
Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
|
||||
Sentry: 9be48e341494bc976c963b05aa4a8ca48308c684
|
||||
sentry_flutter: 544e6376e35b00eef9f0864f8bb7f10a0e204993
|
||||
share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4
|
||||
shared_preferences_macos: a64dc611287ed6cbe28fd1297898db1336975727
|
||||
Sodium: 23d11554ecd556196d313cf6130d406dfe7ac6da
|
||||
sodium_libs: f6ceec5c5f48fb59fc88a8513e9d3f92a7ae92f7
|
||||
sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea
|
||||
url_launcher_macos: 597e05b8e514239626bcf4a850fcf9ef5c856ec3
|
||||
window_size: 339dafa0b27a95a62a843042038fa6c3c48de195
|
||||
|
||||
PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
/* Begin PBXFileReference section */
|
||||
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
|
||||
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
|
||||
33CC10ED2044A3C60003C045 /* authenticator.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = authenticator.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
33CC10ED2044A3C60003C045 /* auth.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = auth.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
|
||||
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||
|
@ -94,7 +94,6 @@
|
|||
4F2F733D93DB4D2D82767271 /* Pods-Runner.release.xcconfig */,
|
||||
B347CC163E4E13C897729F91 /* Pods-Runner.profile.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
|
@ -123,7 +122,7 @@
|
|||
33CC10EE2044A3C60003C045 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
33CC10ED2044A3C60003C045 /* authenticator.app */,
|
||||
33CC10ED2044A3C60003C045 /* auth.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
|
@ -193,7 +192,7 @@
|
|||
);
|
||||
name = Runner;
|
||||
productName = Runner;
|
||||
productReference = 33CC10ED2044A3C60003C045 /* authenticator.app */;
|
||||
productReference = 33CC10ED2044A3C60003C045 /* auth.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
@ -419,8 +418,10 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEVELOPMENT_TEAM = 6Z68YJY9Q2;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -545,8 +546,10 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEVELOPMENT_TEAM = 6Z68YJY9Q2;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -565,8 +568,10 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEVELOPMENT_TEAM = 6Z68YJY9Q2;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "authenticator.app"
|
||||
BuildableName = "auth.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
|
@ -31,7 +31,7 @@
|
|||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "authenticator.app"
|
||||
BuildableName = "auth.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
|
@ -54,7 +54,7 @@
|
|||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "authenticator.app"
|
||||
BuildableName = "auth.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
|
@ -71,7 +71,7 @@
|
|||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "authenticator.app"
|
||||
BuildableName = "auth.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
|
|
|
@ -6,9 +6,14 @@
|
|||
<true/>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.server</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>keychain-access-groups</key>
|
||||
<array>
|
||||
<string>$(AppIdentifierPrefix)io.ente.auth</string>
|
||||
<string>$(AppIdentifierPrefix)io.ente.photos</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -5,6 +5,11 @@
|
|||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<true/>
|
||||
<key>keychain-access-groups</key>
|
||||
<array>
|
||||
<string>$(AppIdentifierPrefix)io.ente.auth</string>
|
||||
<string>$(AppIdentifierPrefix)io.ente.photos</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
41
pubspec.lock
41
pubspec.lock
|
@ -219,12 +219,12 @@ packages:
|
|||
source: hosted
|
||||
version: "2.0.1"
|
||||
convert:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: convert
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
version: "3.1.1"
|
||||
coverage:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -501,13 +501,6 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
flutter_sodium:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_sodium
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.0"
|
||||
flutter_speed_dial:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -539,6 +532,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "8.1.1"
|
||||
freezed_annotation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: freezed_annotation
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
frontend_server_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1076,6 +1076,20 @@ packages:
|
|||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.99"
|
||||
sodium:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: sodium
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.2"
|
||||
sodium_libs:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: sodium_libs
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.3"
|
||||
source_gen:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1328,6 +1342,15 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.6.1"
|
||||
window_size:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "plugins/window_size"
|
||||
ref: a738913c8ce2c9f47515382d40827e794a334274
|
||||
resolved-ref: a738913c8ce2c9f47515382d40827e794a334274
|
||||
url: "https://github.com/google/flutter-desktop-embedding.git"
|
||||
source: git
|
||||
version: "0.1.0"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -15,6 +15,7 @@ dependencies:
|
|||
computer: ^2.0.0
|
||||
confetti: ^0.7.0
|
||||
connectivity: ^3.0.3
|
||||
convert: ^3.1.1
|
||||
cupertino_icons: ^1.0.0
|
||||
device_info: ^2.0.2
|
||||
dio: ^4.0.6
|
||||
|
@ -38,7 +39,6 @@ dependencies:
|
|||
flutter_native_splash: ^2.2.13
|
||||
flutter_secure_storage: ^6.0.0
|
||||
flutter_slidable: ^2.0.0
|
||||
flutter_sodium: ^0.2.0
|
||||
flutter_speed_dial: ^6.2.0
|
||||
flutter_windowmanager: ^0.2.0
|
||||
fluttertoast: ^8.1.1
|
||||
|
@ -60,10 +60,17 @@ dependencies:
|
|||
sentry_flutter: ^6.12.1
|
||||
share_plus: ^4.4.0
|
||||
shared_preferences: ^2.0.5
|
||||
sodium: ^1.2.2
|
||||
sodium_libs: ^1.2.3
|
||||
sqflite: ^2.1.0
|
||||
step_progress_indicator: ^1.0.2
|
||||
url_launcher: ^6.1.5
|
||||
uuid: ^3.0.4
|
||||
window_size:
|
||||
git:
|
||||
url: https://github.com/google/flutter-desktop-embedding.git
|
||||
path: plugins/window_size
|
||||
ref: a738913c8ce2c9f47515382d40827e794a334274
|
||||
|
||||
dev_dependencies:
|
||||
bloc_test: ^9.0.3
|
||||
|
|
1
web/sodium.js
Normal file
1
web/sodium.js
Normal file
File diff suppressed because one or more lines are too long
|
@ -8,13 +8,19 @@
|
|||
|
||||
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
|
||||
#include <sentry_flutter/sentry_flutter_plugin.h>
|
||||
#include <sodium_libs/sodium_libs_plugin.h>
|
||||
#include <url_launcher_windows/url_launcher_windows.h>
|
||||
#include <window_size/window_size_plugin.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
FlutterSecureStorageWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
|
||||
SentryFlutterPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("SentryFlutterPlugin"));
|
||||
SodiumLibsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("SodiumLibsPlugin"));
|
||||
UrlLauncherWindowsRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
|
||||
WindowSizePluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("WindowSizePlugin"));
|
||||
}
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
flutter_secure_storage_windows
|
||||
sentry_flutter
|
||||
sodium_libs
|
||||
url_launcher_windows
|
||||
window_size
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
|
|
Loading…
Add table
Reference in a new issue