Compare commits

...

9 commits

Author SHA1 Message Date
Vishnu Mohandas b759be9609 Merge remote-tracking branch 'origin/main' into desktop 2022-12-09 21:43:40 +05:30
Vishnu Mohandas ff78ffb2dd Update README 2022-12-09 14:49:20 +05:30
Vishnu Mohandas 9aa8f4931a Merge branch 'main' into desktop 2022-12-09 14:47:44 +05:30
Vishnu Mohandas 9417508d05 Merge branch 'main' into desktop 2022-12-09 14:40:55 +05:30
Vishnu Mohandas 5d08264dd0 Remove extra newline 2022-12-09 14:40:32 +05:30
Vishnu Mohandas bd439cc19e Add warning to README 2022-12-09 14:39:48 +05:30
vishnukvmd eacb043fd0 Add screenshots 2022-12-09 14:29:50 +05:30
vishnukvmd 5c54b14768 Add links to both stores 2022-12-09 14:29:50 +05:30
vishnukvmd c9e9b7a38d WiP 2022-12-02 14:04:27 +05:30
27 changed files with 379 additions and 349 deletions

View file

@ -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

View file

@ -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),
);
}

View file

@ -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;

View file

@ -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,
},

View file

@ -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();

View file

@ -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);

View file

@ -65,6 +65,10 @@ class LocalAuthenticationService {
}
Future<bool> _isLocalAuthSupportedOnDevice() async {
return await LocalAuthentication().isDeviceSupported();
try {
return await LocalAuthentication().isDeviceSupported();
} catch (e) {
return false;
}
}
}

View file

@ -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) {

View file

@ -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);

View file

@ -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 {

View file

@ -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(

View file

@ -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;

View file

@ -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",

View file

@ -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,
// },
// );
}
}

View file

@ -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);
}

View file

@ -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

View file

@ -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"))
}

View file

@ -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

View file

@ -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)",

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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:

View file

@ -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

File diff suppressed because one or more lines are too long

View file

@ -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"));
}

View file

@ -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