import 'dart:convert'; import 'package:drift/drift.dart'; import 'package:hashlib/hashlib.dart'; import 'package:http/http.dart' as http; import 'package:twonly/src/model/json/userdata.dart'; import 'package:twonly/src/services/api/media_upload.dart'; import 'package:twonly/src/services/twonly_safe/create_backup.twonly_safe.dart'; import 'package:twonly/src/utils/log.dart'; import 'package:twonly/src/utils/storage.dart'; Future enableTwonlySafe(String password) async { final user = await getUser(); if (user == null) return; final (backupId, encryptionKey) = await getMasterKey(password, user.username); await updateUserdata((user) { user.twonlySafeBackup = TwonlySafeBackup( encryptionKey: encryptionKey, backupId: backupId, ); return user; }); performTwonlySafeBackup(force: true); } Future disableTwonlySafe() async { final serverUrl = await getTwonlySafeBackupUrl(); if (serverUrl != null) { try { final response = await http.delete( Uri.parse(serverUrl), headers: { 'Content-Type': 'application/json', // Set the content type if needed // Add any other headers if required }, ); Log.info("Download deleted with: ${response.statusCode}"); } catch (e) { Log.error("Could not connect to the server."); } } await updateUserdata((user) { user.twonlySafeBackup = null; return user; }); } Future<(Uint8List, Uint8List)> getMasterKey( String password, String username, ) async { List passwordBytes = utf8.encode(password); List saltBytes = utf8.encode(username); // Values are derived from the Threema Whitepaper // https://threema.com/assets/documents/cryptography_whitepaper.pdf final scrypt = Scrypt( cost: 65536, blockSize: 8, parallelism: 1, derivedKeyLength: 64, salt: saltBytes, ); final key = (scrypt.convert(passwordBytes)).bytes; return (key.sublist(0, 32), key.sublist(32, 64)); } Future getTwonlySafeBackupUrl() async { final user = await getUser(); if (user == null || user.twonlySafeBackup == null) return null; return getTwonlySafeBackupUrlFromServer( user.twonlySafeBackup!.backupId, user.backupServer, ); } Future getTwonlySafeBackupUrlFromServer( List backupId, BackupServer? backupServer, ) async { String backupServerUrl = "https://safe.twonly.eu/"; if (backupServer != null) { backupServerUrl = backupServer.serverUrl; } String backupIdHex = uint8ListToHex(backupId).toLowerCase(); return "${backupServerUrl}backups/$backupIdHex"; }