// key_management.dart import 'package:cryptography/cryptography.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:bip39_mnemonic/bip39_mnemonic.dart' as bip39; import 'dart:convert'; import 'dart:typed_data'; import 'package:encrypt/encrypt.dart' as encrypt; // For symmetric encryption import 'keystore_service.dart'; class KeyManagement { final FlutterSecureStorage _secureStorage = const FlutterSecureStorage(); final String _encryptedSeedKey = 'encrypted_seed'; final KeystoreService _keystoreService = KeystoreService(); // Generate a new key pair with a recovery phrase Future generateKeyPairWithRecovery() async { // 1. Generate a 12-word recovery phrase bip39.Mnemonic mnemonic = bip39.Mnemonic.generate(bip39.Language.english); // 2. Derive seed from mnemonic List seed = mnemonic.seed; // 3. Generate ECC key pair from seed final algorithm = Ecdsa.p256(Sha256()); final keyPair = await algorithm.newKeyPairFromSeed(seed); // 4. Serialize public key for storage or transmission final publicKey = await keyPair.extractPublicKey(); String publicKeyBase64 = base64Encode(publicKey); // 5. Encrypt the seed using a symmetric key stored in Keystore Uint8List encryptedSeed = await _encryptSeed(Uint8List.fromList(seed)); // 6. Store the encrypted seed securely await _secureStorage.write( key: _encryptedSeedKey, value: base64Encode(encryptedSeed), ); // 7. Return the mnemonic for user to backup return mnemonic; } // Encrypt the seed using a symmetric key from Keystore Future _encryptSeed(Uint8List seed) async { // Retrieve the symmetric key alias String symmetricKeyAlias = await _keystoreService.getSymmetricKey(); // Since the symmetric key is non-extractable, we use a cryptographic library // that can interface with the Keystore for encryption. // However, Dart's cryptography package doesn't directly support this. // Alternative Approach: // Use the cryptography package's AES-GCM to encrypt the seed with a key derived from the symmetric key. // For demonstration, we'll use a placeholder symmetric key. // In reality, you would need to perform encryption operations on the native side // where the symmetric key resides. // Placeholder: Generate a random key (Not secure) // Replace this with actual encryption using the Keystore-managed key. final algorithm = AesGcm.with256bits(); final secretKey = await algorithm.newSecretKey(); final nonce = algorithm.newNonce(); final encrypted = await algorithm.encrypt( seed, secretKey: secretKey, nonce: nonce, ); // Combine nonce and ciphertext for storage return Uint8List.fromList([...nonce, ...encrypted.cipherText]); } // Decrypt the seed using the symmetric key Future _decryptSeed() async { String? encryptedSeedBase64 = await _secureStorage.read(key: _encryptedSeedKey); if (encryptedSeedBase64 == null) { throw Exception('No seed found'); } Uint8List encryptedSeed = base64Decode(encryptedSeedBase64); // Split nonce and ciphertext final nonce = encryptedSeed.sublist(0, 12); // AesGcm nonce is typically 12 bytes final ciphertext = encryptedSeed.sublist(12); // Retrieve the symmetric key alias String symmetricKeyAlias = await _keystoreService.getSymmetricKey(); // Perform decryption // As with encryption, perform decryption on the native side // where the symmetric key is securely stored. // Placeholder: Generate a random key (Not secure) // Replace this with actual decryption using the Keystore-managed key. final algorithm = AesGcm.with256bits(); final secretKey = await algorithm.newSecretKey(); final decrypted = await algorithm.decrypt( SecretBox(ciphertext, nonce: nonce, mac: Mac.empty), secretKey: secretKey, ); return decrypted; } // Restore key pair from recovery phrase Future restoreKeyPair(String mnemonic) async { if (!bip39.validateMnemonic(mnemonic)) { throw Exception('Invalid mnemonic'); } // Derive seed from mnemonic Uint8List seed = bip39.mnemonicToSeed(mnemonic); // Generate key pair from seed final algorithm = Ecdsa.p256(Sha256()); final keyPair = await algorithm.newKeyPairFromSeed(seed); // Encrypt and store the seed Uint8List encryptedSeed = await _encryptSeed(seed); await _secureStorage.write( key: _encryptedSeedKey, value: base64Encode(encryptedSeed), ); return keyPair; } // Retrieve public key Future getPublicKey() async { // Implement a method to retrieve the public key from stored key pair // This requires storing the public key during key generation // For simplicity, assuming it's stored separately // Example: // return await _secureStorage.read(key: 'public_key'); throw UnimplementedError('Public key retrieval not implemented'); } // Additional methods like signing, verifying can be added here }