You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by lg...@apache.org on 2018/09/06 16:03:33 UTC

[23/51] [abbrv] mina-sshd git commit: [SSHD-842] Split common utilities code from sshd-core into sshd-common (new artifact)

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/SshConfigFileReader.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/SshConfigFileReader.java b/sshd-core/src/main/java/org/apache/sshd/common/config/SshConfigFileReader.java
index c26a2d1..46f34a1 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/config/SshConfigFileReader.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/config/SshConfigFileReader.java
@@ -19,25 +19,11 @@
 
 package org.apache.sshd.common.config;
 
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.StreamCorruptedException;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.OpenOption;
-import java.nio.file.Path;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 import java.util.Properties;
-import java.util.concurrent.TimeUnit;
 import java.util.function.Function;
 
 import org.apache.sshd.common.BuiltinFactory;
@@ -52,17 +38,12 @@ import org.apache.sshd.common.helpers.AbstractFactoryManager;
 import org.apache.sshd.common.kex.BuiltinDHFactories;
 import org.apache.sshd.common.kex.DHFactory;
 import org.apache.sshd.common.kex.KeyExchange;
-import org.apache.sshd.common.keyprovider.KeyPairProvider;
 import org.apache.sshd.common.mac.BuiltinMacs;
 import org.apache.sshd.common.mac.Mac;
 import org.apache.sshd.common.signature.BuiltinSignatures;
 import org.apache.sshd.common.signature.Signature;
 import org.apache.sshd.common.util.GenericUtils;
 import org.apache.sshd.common.util.ValidateUtils;
-import org.apache.sshd.common.util.io.IoUtils;
-import org.apache.sshd.common.util.io.NoCloseInputStream;
-import org.apache.sshd.common.util.io.NoCloseReader;
-import org.apache.sshd.common.util.net.SshdSocketAddress;
 
 /**
  * Reads and interprets some useful configurations from an OpenSSH
@@ -72,187 +53,10 @@ import org.apache.sshd.common.util.net.SshdSocketAddress;
  * @see <a href="https://www.freebsd.org/cgi/man.cgi?query=ssh_config&sektion=5">ssh_config(5)</a>
  */
 public final class SshConfigFileReader {
-
-    public static final char COMMENT_CHAR = '#';
-
-    public static final String COMPRESSION_PROP = "Compression";
-    public static final String DEFAULT_COMPRESSION = CompressionConfigValue.NO.getName();
-    public static final String MAX_SESSIONS_CONFIG_PROP = "MaxSessions";
-    public static final int DEFAULT_MAX_SESSIONS = 10;
-    public static final String PASSWORD_AUTH_CONFIG_PROP = "PasswordAuthentication";
-    public static final String DEFAULT_PASSWORD_AUTH = "no";
-    public static final boolean DEFAULT_PASSWORD_AUTH_VALUE = parseBooleanValue(DEFAULT_PASSWORD_AUTH);
-    public static final String LISTEN_ADDRESS_CONFIG_PROP = "ListenAddress";
-    public static final String DEFAULT_BIND_ADDRESS = SshdSocketAddress.IPV4_ANYADDR;
-    public static final String PORT_CONFIG_PROP = "Port";
-    public static final int DEFAULT_PORT = 22;
-    public static final String KEEP_ALIVE_CONFIG_PROP = "TCPKeepAlive";
-    public static final boolean DEFAULT_KEEP_ALIVE = true;
-    public static final String USE_DNS_CONFIG_PROP = "UseDNS";
-    // NOTE: the usual default is TRUE
-    public static final boolean DEFAULT_USE_DNS = true;
-    public static final String PUBKEY_AUTH_CONFIG_PROP = "PubkeyAuthentication";
-    public static final String DEFAULT_PUBKEY_AUTH = "yes";
-    public static final boolean DEFAULT_PUBKEY_AUTH_VALUE = parseBooleanValue(DEFAULT_PUBKEY_AUTH);
-    public static final String AUTH_KEYS_FILE_CONFIG_PROP = "AuthorizedKeysFile";
-    public static final String MAX_AUTH_TRIES_CONFIG_PROP = "MaxAuthTries";
-    public static final int DEFAULT_MAX_AUTH_TRIES = 6;
-    public static final String MAX_STARTUPS_CONFIG_PROP = "MaxStartups";
-    public static final int DEFAULT_MAX_STARTUPS = 10;
-    public static final String LOGIN_GRACE_TIME_CONFIG_PROP = "LoginGraceTime";
-    public static final long DEFAULT_LOGIN_GRACE_TIME = TimeUnit.SECONDS.toMillis(120);
-    public static final String KEY_REGENERATE_INTERVAL_CONFIG_PROP = "KeyRegenerationInterval";
-    public static final long DEFAULT_REKEY_TIME_LIMIT = TimeUnit.HOURS.toMillis(1L);
-    // see http://manpages.ubuntu.com/manpages/precise/en/man5/sshd_config.5.html
-    public static final String CIPHERS_CONFIG_PROP = "Ciphers";
-    public static final String DEFAULT_CIPHERS =
-            "aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour";
-    // see http://manpages.ubuntu.com/manpages/precise/en/man5/sshd_config.5.html
-    public static final String MACS_CONFIG_PROP = "MACs";
-    public static final String DEFAULT_MACS =
-            "hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160,hmac-sha1-96,hmac-md5-96,hmac-sha2-256,hmac-sha2-256-96,hmac-sha2-512,hmac-sha2-512-96";
-    // see http://manpages.ubuntu.com/manpages/precise/en/man5/sshd_config.5.html
-    public static final String KEX_ALGORITHMS_CONFIG_PROP = "KexAlgorithms";
-    public static final String DEFAULT_KEX_ALGORITHMS =
-            "ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521"
-                    + "," + "diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1"
-                    // RFC-8268 groups
-                    + "," + "diffie-hellman-group18-sha512,diffie-hellman-group17-sha512"
-                    + "," + "diffie-hellman-group16-sha512,diffie-hellman-group15-sha512"
-                    + "," + "diffie-hellman-group14-sha256"
-                    // Legacy groups
-                    + "," + "diffie-hellman-group14-sha1,diffie-hellman-group1-sha1";
-    // see http://linux.die.net/man/5/ssh_config
-    public static final String HOST_KEY_ALGORITHMS_CONFIG_PROP = "HostKeyAlgorithms";
-    // see https://tools.ietf.org/html/rfc5656
-    public static final String DEFAULT_HOST_KEY_ALGORITHMS =
-            KeyPairProvider.SSH_RSA + "," + KeyPairProvider.SSH_DSS;
-    // see http://manpages.ubuntu.com/manpages/precise/en/man5/sshd_config.5.html
-    public static final String LOG_LEVEL_CONFIG_PROP = "LogLevel";
-    public static final LogLevelValue DEFAULT_LOG_LEVEL = LogLevelValue.INFO;
-    // see https://www.freebsd.org/cgi/man.cgi?query=sshd_config&sektion=5
-    public static final String SYSLOG_FACILITY_CONFIG_PROP = "SyslogFacility";
-    public static final SyslogFacilityValue DEFAULT_SYSLOG_FACILITY = SyslogFacilityValue.AUTH;
-    public static final String SUBSYSTEM_CONFIG_PROP = "Subsystem";
-
     private SshConfigFileReader() {
         throw new UnsupportedOperationException("No instance allowed");
     }
 
-    public static Properties readConfigFile(File file) throws IOException {
-        return readConfigFile(file.toPath(), IoUtils.EMPTY_OPEN_OPTIONS);
-    }
-
-    public static Properties readConfigFile(Path path, OpenOption... options) throws IOException {
-        try (InputStream input = Files.newInputStream(path, options)) {
-            return readConfigFile(input, true);
-        }
-    }
-
-    public static Properties readConfigFile(URL url) throws IOException {
-        try (InputStream input = url.openStream()) {
-            return readConfigFile(input, true);
-        }
-    }
-
-    public static Properties readConfigFile(String path) throws IOException {
-        try (InputStream input = new FileInputStream(path)) {
-            return readConfigFile(input, true);
-        }
-    }
-
-    public static Properties readConfigFile(InputStream input, boolean okToClose) throws IOException {
-        try (Reader reader = new InputStreamReader(NoCloseInputStream.resolveInputStream(input, okToClose), StandardCharsets.UTF_8)) {
-            return readConfigFile(reader, true);
-        }
-    }
-
-    public static Properties readConfigFile(Reader reader, boolean okToClose) throws IOException {
-        try (BufferedReader buf = new BufferedReader(NoCloseReader.resolveReader(reader, okToClose))) {
-            return readConfigFile(buf);
-        }
-    }
-
-    /**
-     * Reads the configuration file contents into a {@link Properties} instance.
-     * <B>Note:</B> multiple keys value are concatenated using a comma - it is up to
-     * the caller to know which keys are expected to have multiple values and handle
-     * the split accordingly
-     *
-     * @param rdr The {@link BufferedReader} for reading the file
-     * @return The read properties
-     * @throws IOException If failed to read or malformed content
-     */
-    public static Properties readConfigFile(BufferedReader rdr) throws IOException {
-        Properties props = new Properties();
-        int lineNumber = 1;
-        for (String line = rdr.readLine(); line != null; line = rdr.readLine(), lineNumber++) {
-            line = GenericUtils.replaceWhitespaceAndTrim(line);
-            if (GenericUtils.isEmpty(line)) {
-                continue;
-            }
-
-            int pos = line.indexOf(COMMENT_CHAR);
-            if (pos == 0) {
-                continue;
-            }
-
-            if (pos > 0) {
-                line = line.substring(0, pos);
-                line = line.trim();
-            }
-
-            /*
-             * Some options use '=', others use ' ' - try both
-             * NOTE: we do not validate the format for each option separately
-             */
-            pos = line.indexOf(' ');
-            if (pos < 0) {
-                pos = line.indexOf('=');
-            }
-
-            if (pos < 0) {
-                throw new StreamCorruptedException("No delimiter at line " + lineNumber + ": " + line);
-            }
-
-            String key = line.substring(0, pos);
-            String value = line.substring(pos + 1).trim();
-            // see if need to concatenate multi-valued keys
-            String prev = props.getProperty(key);
-            if (!GenericUtils.isEmpty(prev)) {
-                value = prev + "," + value;
-            }
-
-            props.setProperty(key, value);
-        }
-
-        return props;
-    }
-
-    /**
-     * @param v Checks if the value is &quot;yes&quot;, &quot;y&quot;
-     *          or &quot;on&quot; or &quot;true&quot;.
-     * @return The result - <B>Note:</B> {@code null}/empty values are
-     * interpreted as {@code false}
-     */
-    public static boolean parseBooleanValue(String v) {
-        return "yes".equalsIgnoreCase(v)
-                || "y".equalsIgnoreCase(v)
-                || "on".equalsIgnoreCase(v)
-                || "true".equalsIgnoreCase(v);
-    }
-
-    /**
-     * Returns a &quot;yes&quot; or &quot;no&quot; value based on the input
-     * parameter
-     *
-     * @param flag The required state
-     * @return &quot;yes&quot; if {@code true}, &quot;no&quot; otherwise
-     */
-    public static String yesNoValueOf(boolean flag) {
-        return flag ? "yes" : "no";
-    }
-
     /**
      * @param props The {@link PropertyResolver} - ignored if {@code null}/empty
      * @return A {@code ParseResult} of all the {@link NamedFactory}-ies
@@ -261,11 +65,12 @@ public final class SshConfigFileReader {
      * is the same as the original order - bar the unknown ciphers.
      * <B>Note:</B> it is up to caller to ensure that the lists do not
      * contain duplicates
-     * @see #CIPHERS_CONFIG_PROP
+     * @see ConfigFileReaderSupport#CIPHERS_CONFIG_PROP CIPHERS_CONFIG_PROP
      * @see BuiltinCiphers#parseCiphersList(String)
      */
     public static BuiltinCiphers.ParseResult getCiphers(PropertyResolver props) {
-        return BuiltinCiphers.parseCiphersList((props == null) ? null : props.getString(CIPHERS_CONFIG_PROP));
+        return BuiltinCiphers.parseCiphersList(
+            (props == null) ? null : props.getString(ConfigFileReaderSupport.CIPHERS_CONFIG_PROP));
     }
 
     /**
@@ -276,11 +81,12 @@ public final class SshConfigFileReader {
      * is the same as the original order - bar the unknown MACs.
      * <B>Note:</B> it is up to caller to ensure that the list does not
      * contain duplicates
-     * @see #MACS_CONFIG_PROP
+     * @see ConfigFileReaderSupport#MACS_CONFIG_PROP MACS_CONFIG_PROP
      * @see BuiltinMacs#parseMacsList(String)
      */
     public static BuiltinMacs.ParseResult getMacs(PropertyResolver props) {
-        return BuiltinMacs.parseMacsList((props == null) ? null : props.getString(MACS_CONFIG_PROP));
+        return BuiltinMacs.parseMacsList(
+            (props == null) ? null : props.getString(ConfigFileReaderSupport.MACS_CONFIG_PROP));
     }
 
     /**
@@ -290,11 +96,12 @@ public final class SshConfigFileReader {
      * unknown name is <U>ignored</U>. The order of the returned result is the
      * same as the original order - bar the unknown signatures. <B>Note:</B> it
      * is up to caller to ensure that the list does not contain duplicates
-     * @see #HOST_KEY_ALGORITHMS_CONFIG_PROP
+     * @see ConfigFileReaderSupport#HOST_KEY_ALGORITHMS_CONFIG_PROP HOST_KEY_ALGORITHMS_CONFIG_PROP
      * @see BuiltinSignatures#parseSignatureList(String)
      */
     public static BuiltinSignatures.ParseResult getSignatures(PropertyResolver props) {
-        return BuiltinSignatures.parseSignatureList((props == null) ? null : props.getString(HOST_KEY_ALGORITHMS_CONFIG_PROP));
+        return BuiltinSignatures.parseSignatureList(
+            (props == null) ? null : props.getString(ConfigFileReaderSupport.HOST_KEY_ALGORITHMS_CONFIG_PROP));
     }
 
     /**
@@ -304,30 +111,33 @@ public final class SshConfigFileReader {
      * unknown name is <U>ignored</U>. The order of the returned result is the
      * same as the original order - bar the unknown ones. <B>Note:</B> it is
      * up to caller to ensure that the list does not contain duplicates
-     * @see #KEX_ALGORITHMS_CONFIG_PROP
+     * @see ConfigFileReaderSupport#KEX_ALGORITHMS_CONFIG_PROP KEX_ALGORITHMS_CONFIG_PROP
      * @see BuiltinDHFactories#parseDHFactoriesList(String)
      */
     public static BuiltinDHFactories.ParseResult getKexFactories(PropertyResolver props) {
-        return BuiltinDHFactories.parseDHFactoriesList((props == null) ? null : props.getString(KEX_ALGORITHMS_CONFIG_PROP));
+        return BuiltinDHFactories.parseDHFactoriesList(
+            (props == null) ? null : props.getString(ConfigFileReaderSupport.KEX_ALGORITHMS_CONFIG_PROP));
     }
 
     /**
      * @param props The {@link PropertyResolver} - ignored if {@code null}/empty
      * @return The matching {@link NamedFactory} for the configured value.
      * {@code null} if no configuration or unknown name specified
+     * @see ConfigFileReaderSupport#COMPRESSION_PROP COMPRESSION_PROP
      */
     public static CompressionFactory getCompression(PropertyResolver props) {
-        return CompressionConfigValue.fromName((props == null) ? null : props.getString(COMPRESSION_PROP));
+        return CompressionConfigValue.fromName(
+            (props == null) ? null : props.getString(ConfigFileReaderSupport.COMPRESSION_PROP));
     }
 
     /**
      * <P>Configures an {@link AbstractFactoryManager} with the values read from
      * some configuration. Currently it configures:</P>
      * <UL>
-     * <LI>The {@link Cipher}s - via the {@link #CIPHERS_CONFIG_PROP}</LI>
-     * <LI>The {@link Mac}s - via the {@link #MACS_CONFIG_PROP}</LI>
-     * <LI>The {@link Signature}s - via the {@link #HOST_KEY_ALGORITHMS_CONFIG_PROP}</LI>
-     * <LI>The {@link Compression} - via the {@link #COMPRESSION_PROP}</LI>
+     * <LI>The {@link Cipher}s - via the {@link ConfigFileReaderSupport#CIPHERS_CONFIG_PROP}</LI>
+     * <LI>The {@link Mac}s - via the {@link ConfigFileReaderSupport#MACS_CONFIG_PROP}</LI>
+     * <LI>The {@link Signature}s - via the {@link ConfigFileReaderSupport#HOST_KEY_ALGORITHMS_CONFIG_PROP}</LI>
+     * <LI>The {@link Compression} - via the {@link ConfigFileReaderSupport#COMPRESSION_PROP}</LI>
      * </UL>
      *
      * @param <M>               The generic factory manager
@@ -342,7 +152,8 @@ public final class SshConfigFileReader {
      *                          or unsupported values there is an empty configuration exception is thrown
      * @return The configured manager
      */
-    public static <M extends AbstractFactoryManager> M configure(M manager, PropertyResolver props, boolean lenient, boolean ignoreUnsupported) {
+    public static <M extends AbstractFactoryManager> M configure(
+            M manager, PropertyResolver props, boolean lenient, boolean ignoreUnsupported) {
         configureCiphers(manager, props, lenient, ignoreUnsupported);
         configureSignatures(manager, props, lenient, ignoreUnsupported);
         configureMacs(manager, props, lenient, ignoreUnsupported);
@@ -353,10 +164,13 @@ public final class SshConfigFileReader {
 
     public static <M extends AbstractFactoryManager> M configureCiphers(M manager, PropertyResolver props, boolean lenient, boolean ignoreUnsupported) {
         Objects.requireNonNull(props, "No properties to configure");
-        return configureCiphers(manager, props.getStringProperty(CIPHERS_CONFIG_PROP, DEFAULT_CIPHERS), lenient, ignoreUnsupported);
+        return configureCiphers(manager,
+            props.getStringProperty(ConfigFileReaderSupport.CIPHERS_CONFIG_PROP, ConfigFileReaderSupport.DEFAULT_CIPHERS),
+                lenient, ignoreUnsupported);
     }
 
-    public static <M extends AbstractFactoryManager> M configureCiphers(M manager, String value, boolean lenient, boolean ignoreUnsupported) {
+    public static <M extends AbstractFactoryManager> M configureCiphers(
+            M manager, String value, boolean lenient, boolean ignoreUnsupported) {
         Objects.requireNonNull(manager, "No manager to configure");
 
         BuiltinCiphers.ParseResult result = BuiltinCiphers.parseCiphersList(value);
@@ -371,10 +185,13 @@ public final class SshConfigFileReader {
 
     public static <M extends AbstractFactoryManager> M configureSignatures(M manager, PropertyResolver props, boolean lenient, boolean ignoreUnsupported) {
         Objects.requireNonNull(props, "No properties to configure");
-        return configureSignatures(manager, props.getStringProperty(HOST_KEY_ALGORITHMS_CONFIG_PROP, DEFAULT_HOST_KEY_ALGORITHMS), lenient, ignoreUnsupported);
+        return configureSignatures(manager,
+            props.getStringProperty(ConfigFileReaderSupport.HOST_KEY_ALGORITHMS_CONFIG_PROP, ConfigFileReaderSupport.DEFAULT_HOST_KEY_ALGORITHMS),
+            lenient, ignoreUnsupported);
     }
 
-    public static <M extends AbstractFactoryManager> M configureSignatures(M manager, String value, boolean lenient, boolean ignoreUnsupported) {
+    public static <M extends AbstractFactoryManager> M configureSignatures(
+            M manager, String value, boolean lenient, boolean ignoreUnsupported) {
         Objects.requireNonNull(manager, "No manager to configure");
 
         BuiltinSignatures.ParseResult result = BuiltinSignatures.parseSignatureList(value);
@@ -387,12 +204,16 @@ public final class SshConfigFileReader {
         return manager;
     }
 
-    public static <M extends AbstractFactoryManager> M configureMacs(M manager, PropertyResolver resolver, boolean lenient, boolean ignoreUnsupported) {
+    public static <M extends AbstractFactoryManager> M configureMacs(
+            M manager, PropertyResolver resolver, boolean lenient, boolean ignoreUnsupported) {
         Objects.requireNonNull(resolver, "No properties to configure");
-        return configureMacs(manager, resolver.getStringProperty(MACS_CONFIG_PROP, DEFAULT_MACS), lenient, ignoreUnsupported);
+        return configureMacs(manager,
+            resolver.getStringProperty(ConfigFileReaderSupport.MACS_CONFIG_PROP, ConfigFileReaderSupport.DEFAULT_MACS),
+            lenient, ignoreUnsupported);
     }
 
-    public static <M extends AbstractFactoryManager> M configureMacs(M manager, String value, boolean lenient, boolean ignoreUnsupported) {
+    public static <M extends AbstractFactoryManager> M configureMacs(
+            M manager, String value, boolean lenient, boolean ignoreUnsupported) {
         Objects.requireNonNull(manager, "No manager to configure");
 
         BuiltinMacs.ParseResult result = BuiltinMacs.parseMacsList(value);
@@ -417,13 +238,15 @@ public final class SshConfigFileReader {
      *                          if after ignoring the unknown and un-supported values the result is an empty
      *                          list of factories and exception is thrown
      * @return The configured manager
-     * @see #KEX_ALGORITHMS_CONFIG_PROP
-     * @see #DEFAULT_KEX_ALGORITHMS
+     * @see ConfigFileReaderSupport#KEX_ALGORITHMS_CONFIG_PROP KEX_ALGORITHMS_CONFIG_PROP
+     * @see ConfigFileReaderSupport#DEFAULT_KEX_ALGORITHMS DEFAULT_KEX_ALGORITHMS
      */
     public static <M extends AbstractFactoryManager> M configureKeyExchanges(
             M manager, PropertyResolver props, boolean lenient, Function<? super DHFactory, ? extends NamedFactory<KeyExchange>> xformer, boolean ignoreUnsupported) {
         Objects.requireNonNull(props, "No properties to configure");
-        return configureKeyExchanges(manager, props.getStringProperty(KEX_ALGORITHMS_CONFIG_PROP, DEFAULT_KEX_ALGORITHMS), lenient, xformer, ignoreUnsupported);
+        return configureKeyExchanges(manager,
+            props.getStringProperty(ConfigFileReaderSupport.KEX_ALGORITHMS_CONFIG_PROP, ConfigFileReaderSupport.DEFAULT_KEX_ALGORITHMS),
+            lenient, xformer, ignoreUnsupported);
     }
 
     public static <M extends AbstractFactoryManager> M configureKeyExchanges(
@@ -454,11 +277,12 @@ public final class SshConfigFileReader {
      * @return The configured manager - <B>Note:</B> if the result of filtering due
      * to lenient mode or ignored unsupported value is empty then no factories are set
      */
-    public static <M extends AbstractFactoryManager> M configureCompression(M manager, PropertyResolver props, boolean lenient, boolean ignoreUnsupported) {
+    public static <M extends AbstractFactoryManager> M configureCompression(
+            M manager, PropertyResolver props, boolean lenient, boolean ignoreUnsupported) {
         Objects.requireNonNull(manager, "No manager to configure");
         Objects.requireNonNull(props, "No properties to configure");
 
-        String value = props.getStringProperty(COMPRESSION_PROP, DEFAULT_COMPRESSION);
+        String value = props.getStringProperty(ConfigFileReaderSupport.COMPRESSION_PROP, ConfigFileReaderSupport.DEFAULT_COMPRESSION);
         CompressionFactory factory = CompressionConfigValue.fromName(value);
         ValidateUtils.checkTrue(lenient || (factory != null), "Unsupported compression value: %s", value);
         if ((factory != null) && factory.isSupported()) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/SyslogFacilityValue.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/SyslogFacilityValue.java b/sshd-core/src/main/java/org/apache/sshd/common/config/SyslogFacilityValue.java
deleted file mode 100644
index f52ae36..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/config/SyslogFacilityValue.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.sshd.common.config;
-
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.Set;
-
-import org.apache.sshd.common.util.GenericUtils;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- * @see <A HREF="https://www.freebsd.org/cgi/man.cgi?query=sshd_config&sektion=5"><I>SyslogFacility</I> configuration value</A>
- */
-public enum SyslogFacilityValue {
-    DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7;
-
-    public static final Set<SyslogFacilityValue> VALUES =
-            Collections.unmodifiableSet(EnumSet.allOf(SyslogFacilityValue.class));
-
-    public static SyslogFacilityValue fromName(String n) {
-        if (GenericUtils.isEmpty(n)) {
-            return null;
-        }
-
-        for (SyslogFacilityValue f : VALUES) {
-            if (n.equalsIgnoreCase(f.name())) {
-                return f;
-            }
-        }
-
-        return null;
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/TimeValueConfig.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/TimeValueConfig.java b/sshd-core/src/main/java/org/apache/sshd/common/config/TimeValueConfig.java
deleted file mode 100644
index 222cf84..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/config/TimeValueConfig.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.sshd.common.config;
-
-import java.util.Collections;
-import java.util.EnumMap;
-import java.util.EnumSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.sshd.common.util.GenericUtils;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- * @see <A HREF="http://unixhelp.ed.ac.uk/CGI/man-cgi?sshd_config+5">Time formats for SSH configuration values</A>
- */
-public enum TimeValueConfig {
-    SECONDS('s', 'S', TimeUnit.SECONDS.toMillis(1L)),
-    MINUTES('m', 'M', TimeUnit.MINUTES.toMillis(1L)),
-    HOURS('h', 'H', TimeUnit.HOURS.toMillis(1L)),
-    DAYS('d', 'D', TimeUnit.DAYS.toMillis(1L)),
-    WEEKS('w', 'W', TimeUnit.DAYS.toMillis(7L));
-
-    public static final Set<TimeValueConfig> VALUES =
-            Collections.unmodifiableSet(EnumSet.allOf(TimeValueConfig.class));
-
-    private final char loChar;
-    private final char hiChar;
-    private final long interval;
-
-    TimeValueConfig(char lo, char hi, long interval) {
-        loChar = lo;
-        hiChar = hi;
-        this.interval = interval;
-    }
-
-    public final char getLowerCaseValue() {
-        return loChar;
-    }
-
-    public final char getUpperCaseValue() {
-        return hiChar;
-    }
-
-    public final long getInterval() {
-        return interval;
-    }
-
-    public static TimeValueConfig fromValueChar(char ch) {
-        if ((ch <= ' ') || (ch >= 0x7F)) {
-            return null;
-        }
-
-        for (TimeValueConfig v : VALUES) {
-            if ((v.getLowerCaseValue() == ch) || (v.getUpperCaseValue() == ch)) {
-                return v;
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * @param s A time specification
-     * @return The specified duration in milliseconds
-     * @see #parse(String)
-     * @see #durationOf(Map)
-     */
-    public static long durationOf(String s) {
-        Map<TimeValueConfig, Long> spec = parse(s);
-        return durationOf(spec);
-    }
-
-    /**
-     * @param s An input time specification containing possibly mixed numbers
-     *          and units - e.g., {@code 3h10m} to indicate 3 hours and 10 minutes
-     * @return A {@link Map} specifying for each time unit its count
-     * @throws NumberFormatException    If bad numbers found - e.g., negative counts
-     * @throws IllegalArgumentException If bad format - e.g., unknown unit
-     */
-    public static Map<TimeValueConfig, Long> parse(String s) throws IllegalArgumentException {
-        if (GenericUtils.isEmpty(s)) {
-            return Collections.emptyMap();
-        }
-
-        int lastPos = 0;
-        Map<TimeValueConfig, Long> spec = new EnumMap<>(TimeValueConfig.class);
-        for (int curPos = 0; curPos < s.length(); curPos++) {
-            char ch = s.charAt(curPos);
-            if ((ch >= '0') && (ch <= '9')) {
-                continue;
-            }
-
-            if (curPos <= lastPos) {
-                throw new IllegalArgumentException("parse(" + s + ") missing count value at index=" + curPos);
-            }
-
-            TimeValueConfig c = fromValueChar(ch);
-            if (c == null) {
-                throw new IllegalArgumentException("parse(" + s + ") unknown time value character: '" + ch + "'");
-            }
-
-            String v = s.substring(lastPos, curPos);
-            long count = Long.parseLong(v);
-            if (count < 0L) {
-                throw new IllegalArgumentException("parse(" + s + ") negative count (" + v + ") for " + c.name());
-            }
-
-            Long prev = spec.put(c, count);
-            if (prev != null) {
-                throw new IllegalArgumentException("parse(" + s + ") " + c.name() + " value re-specified: current=" + count + ", previous=" + prev);
-            }
-
-            lastPos = curPos + 1;
-            if (lastPos >= s.length()) {
-                break;
-            }
-        }
-
-        if (lastPos < s.length()) {
-            String v = s.substring(lastPos);
-            long count = Long.parseLong(v);
-            if (count < 0L) {
-                throw new IllegalArgumentException("parse(" + s + ") negative count (" + v + ") for last component");
-            }
-
-            Long prev = spec.put(SECONDS, count);
-            if (prev != null) {
-                throw new IllegalArgumentException("parse(" + s + ") last component (" + SECONDS.name() + ") value re-specified: current=" + count + ", previous=" + prev);
-            }
-        }
-
-        return spec;
-    }
-
-    /**
-     * @param spec The {@link Map} specifying the count for each {@link TimeValueConfig}
-     * @return The total duration in milliseconds
-     * @throws IllegalArgumentException If negative count for a time unit
-     */
-    public static long durationOf(Map<TimeValueConfig, ? extends Number> spec) throws IllegalArgumentException {
-        if (GenericUtils.isEmpty(spec)) {
-            return -1L;
-        }
-
-        long total = 0L;
-        // Cannot use forEach because the total value is not effectively final
-        for (Map.Entry<TimeValueConfig, ? extends Number> se : spec.entrySet()) {
-            TimeValueConfig v = se.getKey();
-            Number c = se.getValue();
-            long factor = c.longValue();
-            if (factor < 0L) {
-                throw new IllegalArgumentException("valueOf(" + spec + ") bad factor (" + c + ") for " + v.name());
-            }
-
-            long added = v.getInterval() * factor;
-            total += added;
-        }
-
-        return total;
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/VersionProperties.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/VersionProperties.java b/sshd-core/src/main/java/org/apache/sshd/common/config/VersionProperties.java
deleted file mode 100644
index 0e351a8..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/config/VersionProperties.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.sshd.common.config;
-
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.util.Collections;
-import java.util.NavigableMap;
-import java.util.Properties;
-import java.util.TreeMap;
-
-import org.apache.sshd.common.util.GenericUtils;
-import org.apache.sshd.common.util.threads.ThreadUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public final class VersionProperties {
-    private static final class LazyVersionPropertiesHolder {
-        private static final NavigableMap<String, String> PROPERTIES =
-            Collections.unmodifiableNavigableMap(loadVersionProperties(LazyVersionPropertiesHolder.class));
-
-        private LazyVersionPropertiesHolder() {
-            throw new UnsupportedOperationException("No instance allowed");
-        }
-
-        private static NavigableMap<String, String> loadVersionProperties(Class<?> anchor) {
-            return loadVersionProperties(anchor, ThreadUtils.resolveDefaultClassLoader(anchor));
-        }
-
-        private static NavigableMap<String, String> loadVersionProperties(Class<?> anchor, ClassLoader loader) {
-            NavigableMap<String, String> result = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
-            try {
-                InputStream input = loader.getResourceAsStream("org/apache/sshd/sshd-version.properties");
-                if (input == null) {
-                    throw new FileNotFoundException("Version resource does not exist");
-                }
-
-                Properties props = new Properties();
-                try {
-                    props.load(input);
-                } finally {
-                    input.close();
-                }
-
-                for (String key : props.stringPropertyNames()) {
-                    String propValue = props.getProperty(key);
-                    String value = GenericUtils.trimToEmpty(propValue);
-                    if (GenericUtils.isEmpty(value)) {
-                        continue;   // we have no need for empty values
-                    }
-
-                    String prev = result.put(key, value);
-                    if (prev != null) {
-                        Logger log = LoggerFactory.getLogger(anchor);
-                        log.warn("Multiple values for key=" + key + ": current=" + value + ", previous=" + prev);
-                    }
-                }
-            } catch (Exception e) {
-                Logger log = LoggerFactory.getLogger(anchor);
-                log.warn("Failed (" + e.getClass().getSimpleName() + ") to load version properties: " + e.getMessage());
-            }
-
-            return result;
-        }
-    }
-
-    private VersionProperties() {
-        throw new UnsupportedOperationException("No instance");
-    }
-
-    /**
-     * @return A case <u>insensitive</u> un-modifiable {@link NavigableMap} of the {@code sshd-version.properties} data
-     */
-    @SuppressWarnings("synthetic-access")
-    public static NavigableMap<String, String> getVersionProperties() {
-        return LazyVersionPropertiesHolder.PROPERTIES;
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/AuthorizedKeyEntry.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/AuthorizedKeyEntry.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/AuthorizedKeyEntry.java
deleted file mode 100644
index a763903..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/AuthorizedKeyEntry.java
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.sshd.common.config.keys;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.StreamCorruptedException;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.OpenOption;
-import java.nio.file.Path;
-import java.security.GeneralSecurityException;
-import java.security.PublicKey;
-import java.util.AbstractMap.SimpleImmutableEntry;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.NavigableMap;
-import java.util.TreeMap;
-
-import org.apache.sshd.common.util.GenericUtils;
-import org.apache.sshd.common.util.ValidateUtils;
-import org.apache.sshd.common.util.io.NoCloseInputStream;
-import org.apache.sshd.common.util.io.NoCloseReader;
-import org.apache.sshd.server.auth.pubkey.KeySetPublickeyAuthenticator;
-import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator;
-import org.apache.sshd.server.auth.pubkey.RejectAllPublickeyAuthenticator;
-
-/**
- * Represents an entry in the user's {@code authorized_keys} file according
- * to the <A HREF="http://en.wikibooks.org/wiki/OpenSSH/Client_Configuration_Files#.7E.2F.ssh.2Fauthorized_keys">OpenSSH format</A>.
- * <B>Note:</B> {@code equals/hashCode} check only the key type and data - the
- * comment and/or login options are not considered part of equality
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- * @see <A HREF="http://man.openbsd.org/sshd.8#AUTHORIZED_KEYS_FILE_FORMAT">sshd(8) - AUTHORIZED_KEYS_FILE_FORMAT</A>
- */
-public class AuthorizedKeyEntry extends PublicKeyEntry {
-    public static final char BOOLEAN_OPTION_NEGATION_INDICATOR = '!';
-
-    private static final long serialVersionUID = -9007505285002809156L;
-
-    private String comment;
-    // for options that have no value, "true" is used
-    private Map<String, String> loginOptions = Collections.emptyMap();
-
-    public AuthorizedKeyEntry() {
-        super();
-    }
-
-    public String getComment() {
-        return comment;
-    }
-
-    public void setComment(String value) {
-        this.comment = value;
-    }
-
-    public Map<String, String> getLoginOptions() {
-        return loginOptions;
-    }
-
-    public void setLoginOptions(Map<String, String> value) {
-        if (value == null) {
-            this.loginOptions = Collections.emptyMap();
-        } else {
-            this.loginOptions = value;
-        }
-    }
-
-    @Override
-    public PublicKey appendPublicKey(Appendable sb, PublicKeyEntryResolver fallbackResolver) throws IOException, GeneralSecurityException {
-        Map<String, String> options = getLoginOptions();
-        if (!GenericUtils.isEmpty(options)) {
-            int index = 0;
-            // Cannot use forEach because the index value is not effectively final
-            for (Map.Entry<String, String> oe : options.entrySet()) {
-                String key = oe.getKey();
-                String value = oe.getValue();
-                if (index > 0) {
-                    sb.append(',');
-                }
-                sb.append(key);
-                // TODO figure out a way to remember which options where quoted
-                // TODO figure out a way to remember which options had no value
-                if (!Boolean.TRUE.toString().equals(value)) {
-                    sb.append('=').append(value);
-                }
-                index++;
-            }
-
-            if (index > 0) {
-                sb.append(' ');
-            }
-        }
-
-        PublicKey key = super.appendPublicKey(sb, fallbackResolver);
-        String kc = getComment();
-        if (!GenericUtils.isEmpty(kc)) {
-            sb.append(' ').append(kc);
-        }
-
-        return key;
-    }
-
-    @Override   // to avoid Findbugs[EQ_DOESNT_OVERRIDE_EQUALS]
-    public int hashCode() {
-        return super.hashCode();
-    }
-
-    @Override   // to avoid Findbugs[EQ_DOESNT_OVERRIDE_EQUALS]
-    public boolean equals(Object obj) {
-        return super.equals(obj);
-    }
-
-    @Override
-    public String toString() {
-        String entry = super.toString();
-        String kc = getComment();
-        Map<?, ?> ko = getLoginOptions();
-        return (GenericUtils.isEmpty(ko) ? "" : ko.toString() + " ")
-                + entry
-                + (GenericUtils.isEmpty(kc) ? "" : " " + kc);
-    }
-
-    public static PublickeyAuthenticator fromAuthorizedEntries(PublicKeyEntryResolver fallbackResolver, Collection<? extends AuthorizedKeyEntry> entries)
-            throws IOException, GeneralSecurityException {
-        Collection<PublicKey> keys = resolveAuthorizedKeys(fallbackResolver, entries);
-        if (GenericUtils.isEmpty(keys)) {
-            return RejectAllPublickeyAuthenticator.INSTANCE;
-        } else {
-            return new KeySetPublickeyAuthenticator(keys);
-        }
-    }
-
-    public static List<PublicKey> resolveAuthorizedKeys(PublicKeyEntryResolver fallbackResolver, Collection<? extends AuthorizedKeyEntry> entries)
-            throws IOException, GeneralSecurityException {
-        if (GenericUtils.isEmpty(entries)) {
-            return Collections.emptyList();
-        }
-
-        List<PublicKey> keys = new ArrayList<>(entries.size());
-        for (AuthorizedKeyEntry e : entries) {
-            PublicKey k = e.resolvePublicKey(fallbackResolver);
-            if (k != null) {
-                keys.add(k);
-            }
-        }
-
-        return keys;
-    }
-
-    /**
-     * Reads read the contents of an <code>authorized_keys</code> file
-     *
-     * @param url The {@link URL} to read from
-     * @return A {@link List} of all the {@link AuthorizedKeyEntry}-ies found there
-     * @throws IOException If failed to read or parse the entries
-     * @see #readAuthorizedKeys(InputStream, boolean)
-     */
-    public static List<AuthorizedKeyEntry> readAuthorizedKeys(URL url) throws IOException {
-        try (InputStream in = url.openStream()) {
-            return readAuthorizedKeys(in, true);
-        }
-    }
-
-    /**
-     * Reads read the contents of an <code>authorized_keys</code> file
-     *
-     * @param file The {@link File} to read from
-     * @return A {@link List} of all the {@link AuthorizedKeyEntry}-ies found there
-     * @throws IOException If failed to read or parse the entries
-     * @see #readAuthorizedKeys(InputStream, boolean)
-     */
-    public static List<AuthorizedKeyEntry> readAuthorizedKeys(File file) throws IOException {
-        try (InputStream in = new FileInputStream(file)) {
-            return readAuthorizedKeys(in, true);
-        }
-    }
-
-    /**
-     * Reads read the contents of an <code>authorized_keys</code> file
-     *
-     * @param path    {@link Path} to read from
-     * @param options The {@link OpenOption}s to use - if unspecified then appropriate
-     *                defaults assumed
-     * @return A {@link List} of all the {@link AuthorizedKeyEntry}-ies found there
-     * @throws IOException If failed to read or parse the entries
-     * @see #readAuthorizedKeys(InputStream, boolean)
-     * @see Files#newInputStream(Path, OpenOption...)
-     */
-    public static List<AuthorizedKeyEntry> readAuthorizedKeys(Path path, OpenOption... options) throws IOException {
-        try (InputStream in = Files.newInputStream(path, options)) {
-            return readAuthorizedKeys(in, true);
-        }
-    }
-
-    /**
-     * Reads read the contents of an <code>authorized_keys</code> file
-     *
-     * @param filePath The file path to read from
-     * @return A {@link List} of all the {@link AuthorizedKeyEntry}-ies found there
-     * @throws IOException If failed to read or parse the entries
-     * @see #readAuthorizedKeys(InputStream, boolean)
-     */
-    public static List<AuthorizedKeyEntry> readAuthorizedKeys(String filePath) throws IOException {
-        try (InputStream in = new FileInputStream(filePath)) {
-            return readAuthorizedKeys(in, true);
-        }
-    }
-
-    /**
-     * Reads read the contents of an <code>authorized_keys</code> file
-     *
-     * @param in        The {@link InputStream}
-     * @param okToClose <code>true</code> if method may close the input stream
-     *                  regardless of whether successful or failed
-     * @return A {@link List} of all the {@link AuthorizedKeyEntry}-ies found there
-     * @throws IOException If failed to read or parse the entries
-     * @see #readAuthorizedKeys(Reader, boolean)
-     */
-    public static List<AuthorizedKeyEntry> readAuthorizedKeys(InputStream in, boolean okToClose) throws IOException {
-        try (Reader rdr = new InputStreamReader(NoCloseInputStream.resolveInputStream(in, okToClose), StandardCharsets.UTF_8)) {
-            return readAuthorizedKeys(rdr, true);
-        }
-    }
-
-    /**
-     * Reads read the contents of an <code>authorized_keys</code> file
-     *
-     * @param rdr       The {@link Reader}
-     * @param okToClose <code>true</code> if method may close the input stream
-     *                  regardless of whether successful or failed
-     * @return A {@link List} of all the {@link AuthorizedKeyEntry}-ies found there
-     * @throws IOException If failed to read or parse the entries
-     * @see #readAuthorizedKeys(BufferedReader)
-     */
-    public static List<AuthorizedKeyEntry> readAuthorizedKeys(Reader rdr, boolean okToClose) throws IOException {
-        try (BufferedReader buf = new BufferedReader(NoCloseReader.resolveReader(rdr, okToClose))) {
-            return readAuthorizedKeys(buf);
-        }
-    }
-
-    /**
-     * @param rdr The {@link BufferedReader} to use to read the contents of
-     *            an <code>authorized_keys</code> file
-     * @return A {@link List} of all the {@link AuthorizedKeyEntry}-ies found there
-     * @throws IOException If failed to read or parse the entries
-     * @see #parseAuthorizedKeyEntry(String)
-     */
-    public static List<AuthorizedKeyEntry> readAuthorizedKeys(BufferedReader rdr) throws IOException {
-        List<AuthorizedKeyEntry> entries = null;
-
-        for (String line = rdr.readLine(); line != null; line = rdr.readLine()) {
-            AuthorizedKeyEntry entry;
-            try {
-                entry = parseAuthorizedKeyEntry(line);
-                if (entry == null) {    // null, empty or comment line
-                    continue;
-                }
-            } catch (RuntimeException | Error e) {
-                throw new StreamCorruptedException("Failed (" + e.getClass().getSimpleName() + ")"
-                        + " to parse key entry=" + line + ": " + e.getMessage());
-            }
-
-            if (entries == null) {
-                entries = new ArrayList<>();
-            }
-
-            entries.add(entry);
-        }
-
-        if (entries == null) {
-            return Collections.emptyList();
-        } else {
-            return entries;
-        }
-    }
-
-    /**
-     * @param value Original line from an <code>authorized_keys</code> file
-     * @return {@link AuthorizedKeyEntry} or {@code null} if the line is
-     * {@code null}/empty or a comment line
-     * @throws IllegalArgumentException If failed to parse/decode the line
-     * @see #COMMENT_CHAR
-     */
-    public static AuthorizedKeyEntry parseAuthorizedKeyEntry(String value) throws IllegalArgumentException {
-        String line = GenericUtils.replaceWhitespaceAndTrim(value);
-        if (GenericUtils.isEmpty(line) || (line.charAt(0) == COMMENT_CHAR) /* comment ? */) {
-            return null;
-        }
-
-        int startPos = line.indexOf(' ');
-        if (startPos <= 0) {
-            throw new IllegalArgumentException("Bad format (no key data delimiter): " + line);
-        }
-
-        int endPos = line.indexOf(' ', startPos + 1);
-        if (endPos <= startPos) {
-            endPos = line.length();
-        }
-
-        String keyType = line.substring(0, startPos);
-        PublicKeyEntryDecoder<?, ?> decoder = KeyUtils.getPublicKeyEntryDecoder(keyType);
-        AuthorizedKeyEntry entry;
-        // assume this is due to the fact that it starts with login options
-        if (decoder == null) {
-            Map.Entry<String, String> comps = resolveEntryComponents(line);
-            entry = parseAuthorizedKeyEntry(comps.getValue());
-            ValidateUtils.checkTrue(entry != null, "Bad format (no key data after login options): %s", line);
-            entry.setLoginOptions(parseLoginOptions(comps.getKey()));
-        } else {
-            String encData = (endPos < (line.length() - 1)) ? line.substring(0, endPos).trim() : line;
-            String comment = (endPos < (line.length() - 1)) ? line.substring(endPos + 1).trim() : null;
-            entry = parsePublicKeyEntry(new AuthorizedKeyEntry(), encData);
-            entry.setComment(comment);
-        }
-
-        return entry;
-    }
-
-    /**
-     * Parses a single line from an <code>authorized_keys</code> file that is <U>known</U>
-     * to contain login options and separates it to the options and the rest of the line.
-     *
-     * @param entryLine The line to be parsed
-     * @return A {@link SimpleImmutableEntry} representing the parsed data where key=login options part
-     * and value=rest of the data - {@code null} if no data in line or line starts with comment character
-     * @see <A HREF="http://man.openbsd.org/sshd.8#AUTHORIZED_KEYS_FILE_FORMAT">sshd(8) - AUTHORIZED_KEYS_FILE_FORMAT</A>
-     */
-    public static SimpleImmutableEntry<String, String> resolveEntryComponents(String entryLine) {
-        String line = GenericUtils.replaceWhitespaceAndTrim(entryLine);
-        if (GenericUtils.isEmpty(line) || (line.charAt(0) == COMMENT_CHAR) /* comment ? */) {
-            return null;
-        }
-
-        for (int lastPos = 0; lastPos < line.length();) {
-            int startPos = line.indexOf(' ', lastPos);
-            if (startPos < lastPos) {
-                throw new IllegalArgumentException("Bad format (no key data delimiter): " + line);
-            }
-
-            int quotePos = line.indexOf('"', startPos + 1);
-            // If found quotes after the space then assume part of a login option
-            if (quotePos > startPos) {
-                lastPos = quotePos + 1;
-                continue;
-            }
-
-            String loginOptions = line.substring(0, startPos).trim();
-            String remainder = line.substring(startPos + 1).trim();
-            return new SimpleImmutableEntry<>(loginOptions, remainder);
-        }
-
-        throw new IllegalArgumentException("Bad format (no key data contents): " + line);
-    }
-
-    /**
-     * <P>
-     * Parses login options line according to
-     * <A HREF="http://man.openbsd.org/sshd.8#AUTHORIZED_KEYS_FILE_FORMAT">sshd(8) - AUTHORIZED_KEYS_FILE_FORMAT</A>
-     * guidelines. <B>Note:</B>
-     * </P>
-     *
-     * <UL>
-     *      <P><LI>
-     *      Options that have a value are automatically stripped of any surrounding double quotes./
-     *      </LI></P>
-     *
-     *      <P><LI>
-     *      Options that have no value are marked as {@code true/false} - according
-     *      to the {@link #BOOLEAN_OPTION_NEGATION_INDICATOR}.
-     *      </LI></P>
-     *
-     *      <P><LI>
-     *      Options that appear multiple times are simply concatenated using comma as separator.
-     *      </LI></P>
-     * </UL>
-     *
-     * @param options The options line to parse - ignored if {@code null}/empty/blank
-     * @return A {@link NavigableMap} where key=case <U>insensitive</U> option name and value=the parsed value.
-     * @see #addLoginOption(Map, String) addLoginOption
-     */
-    public static NavigableMap<String, String> parseLoginOptions(String options) {
-        String line = GenericUtils.replaceWhitespaceAndTrim(options);
-        int len = GenericUtils.length(line);
-        if (len <= 0) {
-            return Collections.emptyNavigableMap();
-        }
-
-        NavigableMap<String, String> optsMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
-        int lastPos = 0;
-        for (int curPos = 0; curPos < len; curPos++) {
-            int nextPos = line.indexOf(',', curPos);
-            if (nextPos < curPos) {
-                break;
-            }
-
-            // check if "true" comma or one inside quotes
-            int quotePos = line.indexOf('"', curPos);
-            if ((quotePos >= lastPos) && (quotePos < nextPos)) {
-                nextPos = line.indexOf('"', quotePos + 1);
-                if (nextPos <= quotePos) {
-                    throw new IllegalArgumentException("Bad format (imbalanced quoted command): " + line);
-                }
-
-                // Make sure either comma or no more options follow the 2nd quote
-                for (nextPos++; nextPos < len; nextPos++) {
-                    char ch = line.charAt(nextPos);
-                    if (ch == ',') {
-                        break;
-                    }
-
-                    if (ch != ' ') {
-                        throw new IllegalArgumentException("Bad format (incorrect list format): " + line);
-                    }
-                }
-            }
-
-            addLoginOption(optsMap, line.substring(lastPos, nextPos));
-            lastPos = nextPos + 1;
-            curPos = lastPos;
-        }
-
-        // Any leftovers at end of line ?
-        if (lastPos < len) {
-            addLoginOption(optsMap, line.substring(lastPos));
-        }
-
-        return optsMap;
-    }
-
-    /**
-     * Parses and adds a new option to the options map. If a valued option is re-specified then
-     * its value(s) are concatenated using comma as separator.
-     *
-     * @param optsMap Options map to add to
-     * @param option The option data to parse - ignored if {@code null}/empty/blank
-     * @return The updated entry - {@code null} if no option updated in the map
-     * @throws IllegalStateException If a boolean option is re-specified
-     */
-    public static SimpleImmutableEntry<String, String> addLoginOption(Map<String, String> optsMap, String option) {
-        String p = GenericUtils.trimToEmpty(option);
-        if (GenericUtils.isEmpty(p)) {
-            return null;
-        }
-
-        int pos = p.indexOf('=');
-        String name = (pos < 0) ? p : GenericUtils.trimToEmpty(p.substring(0, pos));
-        CharSequence value = (pos < 0) ? null : GenericUtils.trimToEmpty(p.substring(pos + 1));
-        value = GenericUtils.stripQuotes(value);
-        if (value == null) {
-            value = Boolean.toString(name.charAt(0) != BOOLEAN_OPTION_NEGATION_INDICATOR);
-        }
-
-        SimpleImmutableEntry<String, String> entry = new SimpleImmutableEntry<>(name, value.toString());
-        String prev = optsMap.put(entry.getKey(), entry.getValue());
-        if (prev != null) {
-            if (pos < 0) {
-                throw new IllegalStateException("Bad format (boolean option (" + name + ") re-specified): " + p);
-            }
-            optsMap.put(entry.getKey(), prev + "," + entry.getValue());
-        }
-
-        return entry;
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/BuiltinIdentities.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/BuiltinIdentities.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/BuiltinIdentities.java
deleted file mode 100644
index 53b6b44..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/BuiltinIdentities.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.sshd.common.config.keys;
-
-import java.security.Key;
-import java.security.KeyPair;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.interfaces.DSAPrivateKey;
-import java.security.interfaces.DSAPublicKey;
-import java.security.interfaces.ECPrivateKey;
-import java.security.interfaces.ECPublicKey;
-import java.security.interfaces.RSAPrivateKey;
-import java.security.interfaces.RSAPublicKey;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.Objects;
-import java.util.Set;
-
-import org.apache.sshd.common.NamedResource;
-import org.apache.sshd.common.util.GenericUtils;
-import org.apache.sshd.common.util.security.SecurityUtils;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public enum BuiltinIdentities implements Identity {
-    RSA(Constants.RSA, RSAPublicKey.class, RSAPrivateKey.class),
-    DSA(Constants.DSA, DSAPublicKey.class, DSAPrivateKey.class),
-    ECDSA(Constants.ECDSA, KeyUtils.EC_ALGORITHM, ECPublicKey.class, ECPrivateKey.class) {
-        @Override
-        public boolean isSupported() {
-            return SecurityUtils.isECCSupported();
-        }
-    },
-    ED25119(Constants.ED25519, SecurityUtils.EDDSA, SecurityUtils.getEDDSAPublicKeyType(), SecurityUtils.getEDDSAPrivateKeyType()) {
-        @Override
-        public boolean isSupported() {
-            return SecurityUtils.isEDDSACurveSupported();
-        }
-    };
-
-    public static final Set<BuiltinIdentities> VALUES =
-            Collections.unmodifiableSet(EnumSet.allOf(BuiltinIdentities.class));
-
-    public static final Set<String> NAMES =
-            Collections.unmodifiableSet(
-                    GenericUtils.asSortedSet(
-                            String.CASE_INSENSITIVE_ORDER, NamedResource.getNameList(VALUES)));
-
-    private final String name;
-    private final String algorithm;
-    private final Class<? extends PublicKey> pubType;
-    private final Class<? extends PrivateKey> prvType;
-
-    BuiltinIdentities(String type, Class<? extends PublicKey> pubType, Class<? extends PrivateKey> prvType) {
-        this(type, type, pubType, prvType);
-    }
-
-    BuiltinIdentities(String name, String algorithm, Class<? extends PublicKey> pubType, Class<? extends PrivateKey> prvType) {
-        this.name = name.toLowerCase();
-        this.algorithm = algorithm.toUpperCase();
-        this.pubType = pubType;
-        this.prvType = prvType;
-    }
-
-    @Override
-    public final String getName() {
-        return name;
-    }
-
-    @Override
-    public boolean isSupported() {
-        return true;
-    }
-
-    @Override
-    public String getAlgorithm() {
-        return algorithm;
-    }
-
-    @Override
-    public final Class<? extends PublicKey> getPublicKeyType() {
-        return pubType;
-    }
-
-    @Override
-    public final Class<? extends PrivateKey> getPrivateKeyType() {
-        return prvType;
-    }
-
-    /**
-     * @param name The identity name - ignored if {@code null}/empty
-     * @return The matching {@link BuiltinIdentities} whose {@link #getName()}
-     * value matches case <U>insensitive</U> or {@code null} if no match found
-     */
-    public static BuiltinIdentities fromName(String name) {
-        return NamedResource.findByName(name, String.CASE_INSENSITIVE_ORDER, VALUES);
-    }
-
-    /**
-     * @param algorithm The algorithm  - ignored if {@code null}/empty
-     * @return The matching {@link BuiltinIdentities} whose {@link #getAlgorithm()}
-     * value matches case <U>insensitive</U> or {@code null} if no match found
-     */
-    public static BuiltinIdentities fromAlgorithm(String algorithm) {
-        if (GenericUtils.isEmpty(algorithm)) {
-            return null;
-        }
-
-        for (BuiltinIdentities id : VALUES) {
-            if (algorithm.equalsIgnoreCase(id.getAlgorithm())) {
-                return id;
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * @param kp The {@link KeyPair} - ignored if {@code null}
-     * @return The matching {@link BuiltinIdentities} provided <U>both</U>
-     * public and public keys are of the same type - {@code null} if no
-     * match could be found
-     * @see #fromKey(Key)
-     */
-    public static BuiltinIdentities fromKeyPair(KeyPair kp) {
-        if (kp == null) {
-            return null;
-        }
-
-        BuiltinIdentities i1 = fromKey(kp.getPublic());
-        BuiltinIdentities i2 = fromKey(kp.getPrivate());
-        if (Objects.equals(i1, i2)) {
-            return i1;
-        } else {
-            return null;    // some kind of mixed keys...
-        }
-    }
-
-    /**
-     * @param key The {@link Key} instance - ignored if {@code null}
-     * @return The matching {@link BuiltinIdentities} whose either public or
-     * private key type matches the requested one or {@code null} if no match found
-     * @see #fromKeyType(Class)
-     */
-    public static BuiltinIdentities fromKey(Key key) {
-        return fromKeyType((key == null) ? null : key.getClass());
-    }
-
-    /**
-     * @param clazz The key type - ignored if {@code null} or not
-     *              a {@link Key} class
-     * @return The matching {@link BuiltinIdentities} whose either public or
-     * private key type matches the requested one or {@code null} if no match found
-     * @see #getPublicKeyType()
-     * @see #getPrivateKeyType()
-     */
-    public static BuiltinIdentities fromKeyType(Class<?> clazz) {
-        if ((clazz == null) || (!Key.class.isAssignableFrom(clazz))) {
-            return null;
-        }
-
-        for (BuiltinIdentities id : VALUES) {
-            Class<?> pubType = id.getPublicKeyType();
-            Class<?> prvType = id.getPrivateKeyType();
-            // Ignore placeholder classes (e.g., if ed25519 is not supported)
-            if ((prvType == null) || (pubType == null)) {
-                continue;
-            }
-            if ((prvType == PrivateKey.class) || (pubType == PublicKey.class)) {
-                continue;
-            }
-            if (pubType.isAssignableFrom(clazz) || prvType.isAssignableFrom(clazz)) {
-                return id;
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Contains the names of the identities
-     */
-    public static final class Constants {
-        public static final String RSA = KeyUtils.RSA_ALGORITHM;
-        public static final String DSA = KeyUtils.DSS_ALGORITHM;
-        public static final String ECDSA = "ECDSA";
-        public static final String ED25519 = "ED25519";
-
-        private Constants() {
-            throw new UnsupportedOperationException("No instance allowed");
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/FilePasswordProvider.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/FilePasswordProvider.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/FilePasswordProvider.java
deleted file mode 100644
index 064f75c..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/FilePasswordProvider.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.sshd.common.config.keys;
-
-import java.io.IOException;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-@FunctionalInterface
-public interface FilePasswordProvider {
-    /**
-     * An &quot;empty&quot; provider that returns {@code null} - i.e., unprotected key file
-     */
-    FilePasswordProvider EMPTY = resourceKey -> null;
-
-    /**
-     * @param resourceKey The resource key representing the <U>private</U>
-     *                    file
-     * @return The password - if {@code null}/empty then no password is required
-     * @throws IOException if cannot resolve password
-     */
-    String getPassword(String resourceKey) throws IOException;
-
-    static FilePasswordProvider of(String password) {
-        return r -> password;
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/Identity.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/Identity.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/Identity.java
deleted file mode 100644
index eaec413..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/Identity.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.sshd.common.config.keys;
-
-import java.security.PrivateKey;
-import java.security.PublicKey;
-
-import org.apache.sshd.common.NamedResource;
-import org.apache.sshd.common.OptionalFeature;
-
-/**
- * Represents an SSH key type
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public interface Identity extends NamedResource, OptionalFeature {
-    /**
-     * @return The key algorithm - e.g., RSA, DSA, EC
-     */
-    String getAlgorithm();
-
-    Class<? extends PublicKey> getPublicKeyType();
-
-    Class<? extends PrivateKey> getPrivateKeyType();
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/IdentityResourceLoader.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/IdentityResourceLoader.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/IdentityResourceLoader.java
deleted file mode 100644
index d826821..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/IdentityResourceLoader.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.sshd.common.config.keys;
-
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.util.Collection;
-
-/**
- * @param <PUB> Type of {@link PublicKey}
- * @param <PRV> Type of {@link PrivateKey}
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public interface IdentityResourceLoader<PUB extends PublicKey, PRV extends PrivateKey> {
-    /**
-     * @return The {@link Class} of the {@link PublicKey} that is the result
-     * of decoding
-     */
-    Class<PUB> getPublicKeyType();
-
-    /**
-     * @return The {@link Class} of the {@link PrivateKey} that matches the
-     * public one
-     */
-    Class<PRV> getPrivateKeyType();
-
-    /**
-     * @return The {@link Collection} of {@code OpenSSH} key type names that
-     * are supported by this decoder - e.g., ECDSA keys have several curve names.
-     * <B>Caveat:</B> this collection may be un-modifiable...
-     */
-    Collection<String> getSupportedTypeNames();
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java
deleted file mode 100644
index fbc3ce7..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.sshd.common.config.keys;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
-import java.nio.file.OpenOption;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.security.GeneralSecurityException;
-import java.security.KeyPair;
-import java.util.Collections;
-import java.util.Map;
-import java.util.TreeMap;
-
-import org.apache.sshd.common.keyprovider.KeyPairProvider;
-import org.apache.sshd.common.keyprovider.MappedKeyPairProvider;
-import org.apache.sshd.common.util.GenericUtils;
-import org.apache.sshd.common.util.ValidateUtils;
-import org.apache.sshd.common.util.security.SecurityUtils;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public final class IdentityUtils {
-    private IdentityUtils() {
-        throw new UnsupportedOperationException("No instance");
-    }
-
-    private static final class LazyDefaultUserHomeFolderHolder {
-        private static final Path PATH =
-            Paths.get(ValidateUtils.checkNotNullAndNotEmpty(System.getProperty("user.home"), "No user home"))
-                .toAbsolutePath()
-                .normalize();
-
-        private LazyDefaultUserHomeFolderHolder() {
-            throw new UnsupportedOperationException("No instance allowed");
-        }
-    }
-
-    /**
-     * @return The {@link Path} to the currently running user home
-     */
-    @SuppressWarnings("synthetic-access")
-    public static Path getUserHomeFolder() {
-        return LazyDefaultUserHomeFolderHolder.PATH;
-    }
-
-    /**
-     * @param prefix The file name prefix - ignored if {@code null}/empty
-     * @param type   The identity type - ignored if {@code null}/empty
-     * @param suffix The file name suffix - ignored if {@code null}/empty
-     * @return The identity file name or {@code null} if no name
-     */
-    public static String getIdentityFileName(String prefix, String type, String suffix) {
-        if (GenericUtils.isEmpty(type)) {
-            return null;
-        } else {
-            return GenericUtils.trimToEmpty(prefix)
-                    + type.toLowerCase() + GenericUtils.trimToEmpty(suffix);
-        }
-    }
-
-    /**
-     * @param ids           A {@link Map} of the loaded identities where key=the identity type,
-     *                      value=the matching {@link KeyPair} - ignored if {@code null}/empty
-     * @param supportedOnly If {@code true} then ignore identities that are not
-     *                      supported internally
-     * @return A {@link KeyPair} for the identities - {@code null} if no identities
-     * available (e.g., after filtering unsupported ones)
-     * @see BuiltinIdentities
-     */
-    public static KeyPairProvider createKeyPairProvider(Map<String, KeyPair> ids, boolean supportedOnly) {
-        if (GenericUtils.isEmpty(ids)) {
-            return null;
-        }
-
-        Map<String, KeyPair> pairsMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
-        ids.forEach((type, kp) -> {
-            BuiltinIdentities id = BuiltinIdentities.fromName(type);
-            if (id == null) {
-                id = BuiltinIdentities.fromKeyPair(kp);
-            }
-
-            if (supportedOnly && ((id == null) || (!id.isSupported()))) {
-                return;
-            }
-
-            String keyType = KeyUtils.getKeyType(kp);
-            if (GenericUtils.isEmpty(keyType)) {
-                return;
-            }
-
-            KeyPair prev = pairsMap.put(keyType, kp);
-            if (prev != null) {
-                return;   // less of an offense if 2 pairs mapped to same key type
-            }
-        });
-
-        if (GenericUtils.isEmpty(pairsMap)) {
-            return null;
-        } else {
-            return new MappedKeyPairProvider(pairsMap);
-        }
-    }
-
-    /**
-     * @param paths    A {@link Map} of the identities where key=identity type (case
-     *                 <U>insensitive</U>), value=the {@link Path} of file with the identity key
-     * @param provider A {@link FilePasswordProvider} - may be {@code null}
-     *                 if the loaded keys are <U>guaranteed</U> not to be encrypted. The argument
-     *                 to {@link FilePasswordProvider#getPassword(String)} is the path of the
-     *                 file whose key is to be loaded
-     * @param options  The {@link OpenOption}s to use when reading the key data
-     * @return A {@link Map} of the identities where key=identity type (case
-     * <U>insensitive</U>), value=the {@link KeyPair} of the identity
-     * @throws IOException              If failed to access the file system
-     * @throws GeneralSecurityException If failed to load the keys
-     * @see SecurityUtils#loadKeyPairIdentity(String, InputStream, FilePasswordProvider)
-     */
-    public static Map<String, KeyPair> loadIdentities(Map<String, ? extends Path> paths, FilePasswordProvider provider, OpenOption... options)
-            throws IOException, GeneralSecurityException {
-        if (GenericUtils.isEmpty(paths)) {
-            return Collections.emptyMap();
-        }
-
-        Map<String, KeyPair> ids = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
-        // Cannot use forEach because the potential for IOExceptions being thrown
-        for (Map.Entry<String, ? extends Path> pe : paths.entrySet()) {
-            String type = pe.getKey();
-            Path path = pe.getValue();
-            try (InputStream inputStream = Files.newInputStream(path, options)) {
-                KeyPair kp = SecurityUtils.loadKeyPairIdentity(path.toString(), inputStream, provider);
-                KeyPair prev = ids.put(type, kp);
-                ValidateUtils.checkTrue(prev == null, "Multiple keys for type=%s", type);
-            }
-        }
-
-        return ids;
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/KeyEntryResolver.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/KeyEntryResolver.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/KeyEntryResolver.java
deleted file mode 100644
index 4bfbea0..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/KeyEntryResolver.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.sshd.common.config.keys;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.math.BigInteger;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import java.security.GeneralSecurityException;
-import java.security.InvalidKeyException;
-import java.security.KeyFactory;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-
-import org.apache.sshd.common.util.io.IoUtils;
-
-/**
- * @param <PUB> Type of {@link PublicKey}
- * @param <PRV> Type of {@link PrivateKey}
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public interface KeyEntryResolver<PUB extends PublicKey, PRV extends PrivateKey> extends IdentityResourceLoader<PUB, PRV> {
-    /**
-     * @param keySize Key size in bits
-     * @return A {@link KeyPair} with the specified key size
-     * @throws GeneralSecurityException if unable to generate the pair
-     */
-    default KeyPair generateKeyPair(int keySize) throws GeneralSecurityException {
-        KeyPairGenerator gen = getKeyPairGenerator();
-        gen.initialize(keySize);
-        return gen.generateKeyPair();
-    }
-
-    /**
-     * @param kp The {@link KeyPair} to be cloned - ignored if {@code null}
-     * @return A cloned pair (or {@code null} if no original pair)
-     * @throws GeneralSecurityException If failed to clone - e.g., provided key
-     *                                  pair does not contain keys of the expected type
-     * @see #getPublicKeyType()
-     * @see #getPrivateKeyType()
-     */
-    default KeyPair cloneKeyPair(KeyPair kp) throws GeneralSecurityException {
-        if (kp == null) {
-            return null;
-        }
-
-        PUB pubCloned = null;
-        PublicKey pubOriginal = kp.getPublic();
-        Class<PUB> pubExpected = getPublicKeyType();
-        if (pubOriginal != null) {
-            Class<?> orgType = pubOriginal.getClass();
-            if (!pubExpected.isAssignableFrom(orgType)) {
-                throw new InvalidKeyException("Mismatched public key types: expected=" + pubExpected.getSimpleName() + ", actual=" + orgType.getSimpleName());
-            }
-
-            pubCloned = clonePublicKey(pubExpected.cast(pubOriginal));
-        }
-
-        PRV prvCloned = null;
-        PrivateKey prvOriginal = kp.getPrivate();
-        Class<PRV> prvExpected = getPrivateKeyType();
-        if (prvOriginal != null) {
-            Class<?> orgType = prvOriginal.getClass();
-            if (!prvExpected.isAssignableFrom(orgType)) {
-                throw new InvalidKeyException("Mismatched private key types: expected=" + prvExpected.getSimpleName() + ", actual=" + orgType.getSimpleName());
-            }
-
-            prvCloned = clonePrivateKey(prvExpected.cast(prvOriginal));
-        }
-
-        return new KeyPair(pubCloned, prvCloned);
-    }
-
-    /**
-     * @param key The {@link PublicKey} to clone - ignored if {@code null}
-     * @return The cloned key (or {@code null} if no original key)
-     * @throws GeneralSecurityException If failed to clone the key
-     */
-    PUB clonePublicKey(PUB key) throws GeneralSecurityException;
-
-    /**
-     * @param key The {@link PrivateKey} to clone - ignored if {@code null}
-     * @return The cloned key (or {@code null} if no original key)
-     * @throws GeneralSecurityException If failed to clone the key
-     */
-    PRV clonePrivateKey(PRV key) throws GeneralSecurityException;
-
-    /**
-     * @return A {@link KeyPairGenerator} suitable for this decoder
-     * @throws GeneralSecurityException If failed to create the generator
-     */
-    KeyPairGenerator getKeyPairGenerator() throws GeneralSecurityException;
-
-    /**
-     * @return A {@link KeyFactory} suitable for the specific decoder type
-     * @throws GeneralSecurityException If failed to create one
-     */
-    KeyFactory getKeyFactoryInstance() throws GeneralSecurityException;
-
-    static int encodeString(OutputStream s, String v) throws IOException {
-        return encodeString(s, v, StandardCharsets.UTF_8);
-    }
-
-    static int encodeString(OutputStream s, String v, String charset) throws IOException {
-        return encodeString(s, v, Charset.forName(charset));
-    }
-
-    static int encodeString(OutputStream s, String v, Charset cs) throws IOException {
-        return writeRLEBytes(s, v.getBytes(cs));
-    }
-
-    static int encodeBigInt(OutputStream s, BigInteger v) throws IOException {
-        return writeRLEBytes(s, v.toByteArray());
-    }
-
-    static int writeRLEBytes(OutputStream s, byte... bytes) throws IOException {
-        return writeRLEBytes(s, bytes, 0, bytes.length);
-    }
-
-    static int writeRLEBytes(OutputStream s, byte[] bytes, int off, int len) throws IOException {
-        byte[] lenBytes = encodeInt(s, len);
-        s.write(bytes, off, len);
-        return lenBytes.length + len;
-    }
-
-    static byte[] encodeInt(OutputStream s, int v) throws IOException {
-        byte[] bytes = {
-            (byte) ((v >> 24) & 0xFF),
-            (byte) ((v >> 16) & 0xFF),
-            (byte) ((v >> 8) & 0xFF),
-            (byte) (v & 0xFF)
-        };
-        s.write(bytes);
-        return bytes;
-    }
-
-    static String decodeString(InputStream s) throws IOException {
-        return decodeString(s, StandardCharsets.UTF_8);
-    }
-
-    static String decodeString(InputStream s, String charset) throws IOException {
-        return decodeString(s, Charset.forName(charset));
-    }
-
-    static String decodeString(InputStream s, Charset cs) throws IOException {
-        byte[] bytes = readRLEBytes(s);
-        return new String(bytes, cs);
-    }
-
-    static BigInteger decodeBigInt(InputStream s) throws IOException {
-        return new BigInteger(readRLEBytes(s));
-    }
-
-    static byte[] readRLEBytes(InputStream s) throws IOException {
-        int len = decodeInt(s);
-        byte[] bytes = new byte[len];
-        IoUtils.readFully(s, bytes);
-        return bytes;
-    }
-
-    static int decodeInt(InputStream s) throws IOException {
-        byte[] bytes = {0, 0, 0, 0};
-        IoUtils.readFully(s, bytes);
-        return ((bytes[0] & 0xFF) << 24)
-                | ((bytes[1] & 0xFF) << 16)
-                | ((bytes[2] & 0xFF) << 8)
-                | (bytes[3] & 0xFF);
-    }
-}