[SSHD-673] "sendKexInit() no resolved signatures available" with key-type "EC"
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/ECCurves.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/ECCurves.java
index 34587b7..dbc2359 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/ECCurves.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/cipher/ECCurves.java
@@ -24,8 +24,11 @@
 import java.security.spec.ECParameterSpec;
 import java.security.spec.ECPoint;
 import java.security.spec.EllipticCurve;
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.EnumSet;
+import java.util.List;
 import java.util.Set;
 import java.util.TreeSet;
 
@@ -124,6 +127,25 @@
                 }
             });
 
+    public static final Comparator<ECCurves> BY_KEY_SIZE = new Comparator<ECCurves>() {
+        @Override
+        public int compare(ECCurves o1, ECCurves o2) {
+            int k1 = (o1 == null) ? Integer.MAX_VALUE : o1.getKeySize();
+            int k2 = (o2 == null) ? Integer.MAX_VALUE : o2.getKeySize();
+            return Integer.compare(k1, k2);
+        }
+    };
+
+    public static final List<ECCurves> SORTED_KEY_SIZE =
+            Collections.unmodifiableList(
+                    new ArrayList<ECCurves>(VALUES) {
+                        // Not serializing it
+                        private static final long serialVersionUID = 1L;
+
+                        {
+                            Collections.sort(this, BY_KEY_SIZE);
+                        }
+                    });
     private final String name;
     private final String keyType;
     private final ECParameterSpec params;
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java b/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java
index ba9f417..345c0b3 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java
@@ -45,6 +45,7 @@
 import org.apache.sshd.common.PropertyResolverUtils;
 import org.apache.sshd.common.ServiceFactory;
 import org.apache.sshd.common.config.SshConfigFileReader;
+import org.apache.sshd.common.config.keys.KeyUtils;
 import org.apache.sshd.common.helpers.AbstractFactoryManager;
 import org.apache.sshd.common.io.IoAcceptor;
 import org.apache.sshd.common.io.IoServiceFactory;
@@ -423,6 +424,7 @@
         String provider;
         boolean error = false;
         String hostKeyType = AbstractGeneratorHostKeyProvider.DEFAULT_ALGORITHM;
+        int hostKeySize = 0;
         Map<String, String> options = new LinkedHashMap<>();
 
         int numArgs = GenericUtils.length(args);
@@ -440,6 +442,13 @@
                     break;
                 }
                 hostKeyType = args[++i].toUpperCase();
+            } else if ("-key-size".equals(argName)) {
+                if (i + 1 >= numArgs) {
+                    System.err.println("option requires an argument: " + argName);
+                    break;
+                }
+
+                hostKeySize = Integer.parseInt(args[++i]);
             } else if ("-io".equals(argName)) {
                 if (i + 1 >= numArgs) {
                     System.err.println("option requires an argument: " + argName);
@@ -501,14 +510,20 @@
             hostKeyProvider = new SimpleGeneratorHostKeyProvider(hostKeyFile);
         }
         hostKeyProvider.setAlgorithm(hostKeyType);
+        if (hostKeySize != 0) {
+            hostKeyProvider.setKeySize(hostKeySize);
+        }
 
         List<KeyPair> keys = ValidateUtils.checkNotNullAndNotEmpty(hostKeyProvider.loadKeys(),
                 "Failed to load keys from %s", hostKeyFile);
         KeyPair kp = keys.get(0);
         PublicKey pubKey = kp.getPublic();
         String keyAlgorithm = pubKey.getAlgorithm();
+        if ("ECDSA".equalsIgnoreCase(keyAlgorithm)) {
+            keyAlgorithm = KeyUtils.EC_ALGORITHM;
+        }
         // force re-generation of host key if not same algorithm
-        if (!Objects.equals(keyAlgorithm, hostKeyProvider.getAlgorithm())) {
+        if (!Objects.equals(keyAlgorithm, hostKeyType)) {
             Files.deleteIfExists(hostKeyFile);
             hostKeyProvider.clearLoadedKeys();
         }
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java b/sshd-core/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java
index 6a57763..d3b653b 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java
@@ -33,8 +33,10 @@
 import java.security.spec.AlgorithmParameterSpec;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.atomic.AtomicReference;
 
+import org.apache.sshd.common.cipher.ECCurves;
 import org.apache.sshd.common.config.keys.KeyUtils;
 import org.apache.sshd.common.keyprovider.AbstractKeyPairProvider;
 import org.apache.sshd.common.util.SecurityUtils;
@@ -151,32 +153,24 @@
     }
 
     protected KeyPair resolveKeyPair(Path keyPath) throws IOException, GeneralSecurityException {
+        String alg = getAlgorithm();
+        KeyPair kp;
         if (keyPath != null) {
-            LinkOption[] options = IoUtils.getLinkOptions(false);
-            if (Files.exists(keyPath, options) && Files.isRegularFile(keyPath, options)) {
-                try {
-                    KeyPair kp = readKeyPair(keyPath, IoUtils.EMPTY_OPEN_OPTIONS);
-                    if (kp != null) {
-                        if (log.isDebugEnabled()) {
-                            PublicKey key = kp.getPublic();
-                            log.debug("resolveKeyPair({}) loaded key={}-{}",
-                                      keyPath, KeyUtils.getKeyType(key), KeyUtils.getFingerPrint(key));
-                        }
-                        return kp;
-                    }
-                } catch (Throwable e) {
-                    log.warn("resolveKeyPair({}) Failed ({}) to load: {}",
-                            keyPath, e.getClass().getSimpleName(), e.getMessage());
-                    if (log.isDebugEnabled()) {
-                        log.debug("resolveKeyPair(" + keyPath + ") load failure details", e);
-                    }
+            try {
+                kp = loadFromFile(alg, keyPath);
+                if (kp != null) {
+                    return kp;
+                }
+            } catch (Throwable e) {
+                log.warn("resolveKeyPair({}) Failed ({}) to load: {}",
+                        keyPath, e.getClass().getSimpleName(), e.getMessage());
+                if (log.isDebugEnabled()) {
+                    log.debug("resolveKeyPair(" + keyPath + ") load failure details", e);
                 }
             }
         }
 
         // either no file specified or no key in file
-        String alg = getAlgorithm();
-        KeyPair kp;
         try {
             kp = generateKeyPair(alg);
             if (kp == null) {
@@ -213,6 +207,39 @@
         return kp;
     }
 
+    protected KeyPair loadFromFile(String alg, Path keyPath) throws IOException, GeneralSecurityException {
+        LinkOption[] options = IoUtils.getLinkOptions(false);
+        if ((!Files.exists(keyPath, options)) || (!Files.isRegularFile(keyPath, options))) {
+            return null;
+        }
+
+        KeyPair kp = readKeyPair(keyPath, IoUtils.EMPTY_OPEN_OPTIONS);
+        if (kp == null) {
+            return null;
+        }
+        PublicKey key = kp.getPublic();
+        String keyAlgorithm = key.getAlgorithm();
+        if ("ECDSA".equalsIgnoreCase(keyAlgorithm)) {
+            keyAlgorithm = KeyUtils.EC_ALGORITHM;
+        }
+
+        if (Objects.equals(alg, keyAlgorithm)) {
+            if (log.isDebugEnabled()) {
+                log.debug("resolveKeyPair({}) loaded key={}-{}",
+                          keyPath, KeyUtils.getKeyType(key), KeyUtils.getFingerPrint(key));
+            }
+            return kp;
+        }
+
+        // Not same algorithm - start again
+        if (log.isDebugEnabled()) {
+            log.debug("resolveKeyPair({}) mismatched loaded key algorithm: expected={}, loaded={}",
+                      keyPath, alg, keyAlgorithm);
+        }
+        Files.deleteIfExists(keyPath);
+        return null;
+    }
+
     protected KeyPair readKeyPair(Path keyPath, OpenOption... options) throws IOException, GeneralSecurityException {
         try (InputStream inputStream = Files.newInputStream(keyPath, options)) {
             return doReadKeyPair(keyPath.toString(), inputStream);
@@ -248,6 +275,11 @@
         } else if (keySize != 0) {
             generator.initialize(keySize);
             log.info("generateKeyPair(" + algorithm + ") generating host key - size=" + keySize);
+        } else if (KeyUtils.EC_ALGORITHM.equals(algorithm)) {
+            // If left to our own devices choose the biggest key size possible
+            int numCurves = ECCurves.SORTED_KEY_SIZE.size();
+            ECCurves curve = ECCurves.SORTED_KEY_SIZE.get(numCurves - 1);
+            generator.initialize(curve.getParameters());
         }
 
         return generator.generateKeyPair();