From 3db002684696cbab0ddf6c9b3b7873ded492f422 Mon Sep 17 00:00:00 2001 From: lemoer Date: Fri, 20 Jun 2025 14:31:37 +0200 Subject: [PATCH] Generate key on startup or load from keystore. --- lib/main.dart | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 0755d93..019a644 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,4 @@ import 'dart:convert'; -import 'dart:io'; import 'package:dartssh2/dartssh2.dart'; import 'package:flutter/material.dart'; @@ -67,7 +66,6 @@ class _MyHomePageState extends State { OpenSSHEd25519KeyPair? keyPair; String _output = ''; String key = ''; - Future doSSH() async { SSHSocket? socket; @@ -96,14 +94,36 @@ class _MyHomePageState extends State { } } - Future generateKey() async { + Future obtainKeyPair({bool regenerate = false}) async { // Generate a key pair + final storage = const FlutterSecureStorage(); + final storedKey = await storage.read(key: 'ssh_key_pair'); + + // Restore the key if we have one stored and regeneration is not requested + if (storedKey != null && !regenerate) { + // If we have a stored key, use it + final keyPairsFromStorage = SSHKeyPair.fromPem(storedKey); + assert(keyPairsFromStorage.length == 1); + assert(keyPairsFromStorage[0] is OpenSSHEd25519KeyPair); + + final keyPairFromStorage = + keyPairsFromStorage[0] as OpenSSHEd25519KeyPair; + + setState(() { + keyPair = keyPairFromStorage; + key = encodePublicKey(keyPairFromStorage, comment: "leinelab-app-key"); + }); + return; + } + final generatedKeyPair = await generateKeyPair(); // local variable avoids downcast to ? ptr - keyPair = generatedKeyPair; + + await storage.write(key: 'ssh_key_pair', value: generatedKeyPair.toPem()); setState(() { + keyPair = generatedKeyPair; key = encodePublicKey(generatedKeyPair, comment: "leinelab-app-key"); }); @@ -113,6 +133,14 @@ class _MyHomePageState extends State { ); } + @override + void initState() { + super.initState(); + + // we do not await generateKey() here, as this is the intended way + obtainKeyPair(); + } + @override Widget build(BuildContext context) { final String outputText = _output.isNotEmpty @@ -143,7 +171,7 @@ class _MyHomePageState extends State { ); final actionButtonInfo = FloatingActionButton( - onPressed: generateKey, + onPressed: () => obtainKeyPair(regenerate: true), tooltip: 'Regenerate Key', child: const Icon(Icons.refresh), );