import 'dart:typed_data'; import 'package:cryptography/cryptography.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'dart:convert'; class CryptoService { final _storage = const FlutterSecureStorage(); final algorithm = X25519(); final aesGcm = AesGcm.with256bits(); Future> initAccountSecurity(String masterPassword) async { // Генерируем пару X25519 ключей final keyPair = await algorithm.newKeyPair(); final publicKey = await keyPair.extractPublicKey(); final privateKeyBytes = await keyPair.extractPrivateKeyBytes(); // Сохраняем приватный ключ в Secure Storage await _storage.write( key: 'private_key', value: base64Encode(privateKeyBytes), ); // Шифруем приватный ключ с мастер-паролем (AES-GCM) final masterKey = await _deriveKeyFromPassword(masterPassword); final nonce = aesGcm.newNonce(); final encrypted = await aesGcm.encrypt( privateKeyBytes, secretKey: masterKey, nonce: nonce, ); // Комбинируем nonce и зашифрованные данные final encryptedData = nonce + encrypted.mac.bytes + encrypted.cipherText; final encryptedPrivateKey = base64Encode(encryptedData); final publicKeyBase64 = base64Encode(publicKey.bytes); return { 'public_key': publicKeyBase64, 'encrypted_private_key': encryptedPrivateKey, }; } Future decryptPrivateKey( String encryptedPrivateKey, String masterPassword, ) async { try { final encryptedData = base64Decode(encryptedPrivateKey); // Разделяем nonce и зашифрованные данные final nonce = encryptedData.sublist(0, 12); // GCM nonce = 12 bytes final macBytes = encryptedData.sublist(12, 28); final cipherText = encryptedData.sublist(28); final masterKey = await _deriveKeyFromPassword(masterPassword); final decrypted = await aesGcm.decrypt( SecretBox(cipherText, nonce: nonce, mac: Mac(macBytes)), secretKey: masterKey, ); return base64Encode(decrypted); } catch (e) { throw Exception('Неверный мастер-пароль или поврежденные данные'); } } Future encryptPrivateKeyWithPassword( String privateKeyBase64, String masterPassword, ) async { final privateKeyBytes = base64Decode(privateKeyBase64); final masterKey = await _deriveKeyFromPassword(masterPassword); final nonce = aesGcm.newNonce(); final encrypted = await aesGcm.encrypt( privateKeyBytes, secretKey: masterKey, nonce: nonce, ); final encryptedData = nonce + encrypted.mac.bytes + encrypted.cipherText; return base64Encode(encryptedData); } Future _deriveKeyFromPassword(String password) async { final pbkdf2 = Pbkdf2( macAlgorithm: Hmac.sha256(), iterations: 10000, bits: 256, ); final salt = utf8.encode('chepuhagram_salt'); return await pbkdf2.deriveKeyFromPassword(password: password, nonce: salt); } Future deriveSharedSecret( String myPrivateKeyBase64, String theirPublicKeyBase64, ) async { final myKeyPair = await algorithm.newKeyPairFromSeed( base64Decode(myPrivateKeyBase64), ); final theirPublicKey = SimplePublicKey( base64Decode(theirPublicKeyBase64), type: KeyPairType.x25519, ); return await algorithm.sharedSecretKey( keyPair: myKeyPair, remotePublicKey: theirPublicKey, ); } Future encryptMessage(String text, SecretKey sharedKey) async { final nonce = aesGcm.newNonce(); final encrypted = await aesGcm.encrypt( utf8.encode(text), secretKey: sharedKey, nonce: nonce, ); // Сохраняем Nonce + MAC + CipherText для передачи return base64Encode(nonce + encrypted.mac.bytes + encrypted.cipherText); } Future<(List, String)?> encryptImage( List fileBytes, SecretKey sharedKey, ) async { try { final SecretKey fileSecretKey = await aesGcm.newSecretKey(); final List fileSecretKeyBytes = await fileSecretKey.extractBytes(); final SecretBox secretBox = await aesGcm.encrypt( fileBytes, secretKey: fileSecretKey, ); final List dataToUpload = secretBox.concatenation(); final encryptedKeyBox = await aesGcm.encrypt( fileSecretKeyBytes, secretKey: sharedKey, ); final String encryptedKeyForServer = base64Encode( encryptedKeyBox.concatenation(), ); return (dataToUpload, encryptedKeyForServer); } catch (e) { print("Ошибка шифрования медиа: $e"); return null; } } Future decryptMessage(String base64Data, SecretKey sharedKey) async { final data = base64Decode(base64Data); final nonce = data.sublist(0, 12); final mac = data.sublist(12, 28); final cipherText = data.sublist(28); final decrypted = await aesGcm.decrypt( SecretBox(cipherText, nonce: nonce, mac: Mac(mac)), secretKey: sharedKey, ); return utf8.decode(decrypted); } Future getPrivateKey() async { return await _storage.read(key: 'private_key'); } Future hasPrivateKey() async { final key = await _storage.read(key: 'private_key'); return key != null; } Future savePrivateKey(String privateKey) async { await _storage.write(key: 'private_key', value: privateKey); } Future deletePrivateKey() async { await _storage.delete(key: 'private_key'); } }