You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by gn...@apache.org on 2015/03/30 11:17:50 UTC

[1/6] mina-sshd git commit: [SSHD-437] Handle correctly SFTP root Windows drives

Repository: mina-sshd
Updated Branches:
  refs/heads/master eb4fc83d6 -> b9e1401c1


[SSHD-437] Handle correctly SFTP root Windows drives

Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/2b640b02
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/2b640b02
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/2b640b02

Branch: refs/heads/master
Commit: 2b640b02cefabbf3c28cf52965af479213638ef6
Parents: eb4fc83
Author: Guillaume Nodet <gn...@apache.org>
Authored: Mon Mar 30 10:34:47 2015 +0200
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Mon Mar 30 10:34:47 2015 +0200

----------------------------------------------------------------------
 .../apache/sshd/common/util/GenericUtils.java   |   9 ++
 .../org/apache/sshd/common/util/OsUtils.java    |   1 +
 .../apache/sshd/common/util/SelectorUtils.java  |  56 +++++++-
 .../apache/sshd/server/sftp/SftpSubsystem.java  | 138 ++++++++++++++-----
 .../java/org/apache/sshd/SshServerMain.java     |  33 +++++
 5 files changed, 201 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b640b02/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
index b02c7ec..5bc5434 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
@@ -26,6 +26,15 @@ import java.util.Map;
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
 public class GenericUtils {
+
+    public static final String trimToEmpty(String s) {
+        if (s == null) {
+            return "";
+        } else {
+            return s.trim();
+        }
+    }
+
     public static final int length(CharSequence cs) {
         if (cs == null) {
             return 0;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b640b02/sshd-core/src/main/java/org/apache/sshd/common/util/OsUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/OsUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/OsUtils.java
index 778f742..f693a8e 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/OsUtils.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/OsUtils.java
@@ -42,5 +42,6 @@ public class OsUtils {
     }
 
     private OsUtils () {
+        throw new UnsupportedOperationException("No instance allowed");
     }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b640b02/sshd-core/src/main/java/org/apache/sshd/common/util/SelectorUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/SelectorUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/SelectorUtils.java
index 6f446b1..0203eed 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/SelectorUtils.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/SelectorUtils.java
@@ -53,6 +53,7 @@ public final class SelectorUtils {
      * Private Constructor
      */
     private SelectorUtils() {
+        throw new UnsupportedOperationException("No instance allowed");
     }
 
     /**
@@ -555,16 +556,67 @@ public final class SelectorUtils {
         }
 
         // serialize
-        StringBuffer buffer = new StringBuffer(path.length());
-
+        StringBuilder buffer = new StringBuilder(path.length());
         for (int i = 0; i < tokens.size(); i++) {
             if (i > 0 || (i == 0 && startsWithSeparator)) buffer.append(separator);
             buffer.append(tokens.get(i));
         }
 
+        // for root Windows drive we need to return "C:/" or we get errors from the local file system
+        if (OsUtils.isWin32() && (buffer.length() == 2) && isWindowsDriveSpecified(buffer)) {
+            buffer.append(separator);
+        }
+
         return buffer.toString();
     }
 
+    /**
+     * Converts a possibly '/' separated path to a local path. <B>Note:</B>
+     * takes special care of Windows drive paths - e.g., {@code C:}
+     * by converting them to &quot;C:\&quot;
+     * @param path The original path
+     * @return The local path
+     */
+    public static String translateToLocalPath(String path) {
+        if (GenericUtils.isEmpty(path) || (File.separatorChar == '/')) {
+            return path;
+        }
+        
+        // this means we are running on Windows
+        String  localPath=path.replace('/', File.separatorChar);
+        if ((localPath.length() < 2) || (localPath.charAt(1) != ':')) {
+            return localPath;   // assume a relative path
+        }
+
+        /*
+         * Here we know that we have at least a "C:" string - make sure it
+         * is followed by the local file separator. Note: if all we have is
+         * just the drive, we will create a "C:\" path since this is the
+         * preferred Windows way to refer to root drives in the file system
+         */
+        if (localPath.length() == 2) {
+            return localPath + File.separator;  // all we have is "C:"
+        } else if (localPath.charAt(2) != File.separatorChar) {
+            // be nice and add the missing file separator - C:foo => C:\foo
+            return localPath.substring(0, 2) + File.separator + localPath.substring(2);
+        } else {
+            return localPath;
+        }
+    }
+
+    public static boolean isWindowsDriveSpecified(CharSequence cs) {
+        if ((GenericUtils.length(cs) < 2) || (cs.charAt(1) != ':')) {
+            return false;
+        }
+        
+        char    drive=cs.charAt(0);
+        if (((drive >= 'a') && (drive <= 'z'))
+         || ((drive >= 'A') && (drive <= 'Z'))) {
+            return true;
+        } else {
+            return false;
+        }
+    }
 
     /**
      * Returns dependency information on these two files. If src has been

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b640b02/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java b/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java
index 1e6d305..ccf2b9c 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java
@@ -63,6 +63,7 @@ import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.EnumSet;
 import java.util.GregorianCalendar;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -75,8 +76,10 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 
+import org.apache.sshd.common.FactoryManagerUtils;
 import org.apache.sshd.common.file.FileSystemAware;
 import org.apache.sshd.common.util.Buffer;
+import org.apache.sshd.common.util.GenericUtils;
 import org.apache.sshd.common.util.IoUtils;
 import org.apache.sshd.common.util.OsUtils;
 import org.apache.sshd.common.util.SelectorUtils;
@@ -226,6 +229,7 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
             case SSH_FXF_TRUNCATE_EXISTING:
                 options.add(StandardOpenOption.TRUNCATE_EXISTING);
                 break;
+            default:    // ignored
             }
             if ((flags & SSH_FXF_APPEND_DATA) != 0) {
                 options.add(StandardOpenOption.APPEND);
@@ -559,7 +563,10 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
     protected void doTextSeek(Buffer buffer, int id) throws IOException {
         String handle = buffer.getString();
         long line = buffer.getLong();
-        log.debug("Received SSH_FXP_EXTENDED(text-seek) (handle={}, line={})", handle, line);
+        if (log.isDebugEnabled()) {
+            log.debug("Received SSH_FXP_EXTENDED(text-seek) (handle={}, line={})", handle, line);
+        }
+
         // TODO : implement text-seek
         sendStatus(id, SSH_FX_OP_UNSUPPORTED, "Command SSH_FXP_EXTENDED(text-seek) is unsupported or not implemented");
     }
@@ -587,7 +594,11 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
         long offset = buffer.getLong();
         long length = buffer.getLong();
         int mask = buffer.getInt();
-        log.debug("Received SSH_FXP_BLOCK (handle={}, offset={}, length={}, mask={})", new Object[] { handle, offset, length, mask });
+        
+        if (log.isDebugEnabled()) {
+            log.debug("Received SSH_FXP_BLOCK (handle={}, offset={}, length={}, mask={})", new Object[] { handle, offset, length, "0x" + Integer.toHexString(mask) });
+        }
+
         try {
             Handle p = handles.get(handle);
             if (!(p instanceof FileHandle)) {
@@ -606,7 +617,10 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
         String handle = buffer.getString();
         long offset = buffer.getLong();
         long length = buffer.getLong();
-        log.debug("Received SSH_FXP_UNBLOCK (handle={}, offset={}, length={})", new Object[] { handle, offset, length });
+        if (log.isDebugEnabled()) {
+            log.debug("Received SSH_FXP_UNBLOCK (handle={}, offset={}, length={})", new Object[] { handle, offset, length });
+        }
+
         try {
             Handle p = handles.get(handle);
             if (!(p instanceof FileHandle)) {
@@ -625,7 +639,10 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
         String targetpath = buffer.getString();
         String linkpath = buffer.getString();
         boolean symLink = buffer.getBoolean();
-        log.debug("Received SSH_FXP_LINK (linkpath={}, targetpath={}, symlink={})", new Object[] { linkpath, targetpath, symLink });
+        if (log.isDebugEnabled()) {
+            log.debug("Received SSH_FXP_LINK (linkpath={}, targetpath={}, symlink={})", new Object[] { linkpath, targetpath, symLink });
+        }
+
         try {
             Path link = resolveFile(linkpath);
             Path target = fileSystem.getPath(targetpath);
@@ -679,7 +696,9 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
         if (version >= SFTP_V5) {
             flags = buffer.getInt();
         }
-        log.debug("Received SSH_FXP_RENAME (oldPath={}, newPath={}, flags={})", new Object[] { oldPath, newPath, flags });
+        if (log.isDebugEnabled()) {
+            log.debug("Received SSH_FXP_RENAME (oldPath={}, newPath={}, flags={})", new Object[] { oldPath, newPath, flags });
+        }
         try {
             List<CopyOption> opts = new ArrayList<>();
             if ((flags & SSH_FXP_RENAME_ATOMIC) != 0) {
@@ -703,7 +722,9 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
         if (version >= SFTP_V4) {
             flags = buffer.getInt();
         }
-        log.debug("Received SSH_FXP_STAT (path={}, flags={})", path, flags);
+        if (log.isDebugEnabled()) {
+            log.debug("Received SSH_FXP_STAT (path={}, flags={})", path, "0x" + Integer.toHexString(flags));
+        }
         try {
             Path p = resolveFile(path);
             sendAttrs(id, p, flags, true);
@@ -715,13 +736,15 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
     protected void doRealPath(Buffer buffer, int id) throws IOException {
         String path = buffer.getString();
         log.debug("Received SSH_FXP_REALPATH (path={})", path);
-        if (path.trim().length() == 0) {
+        path = GenericUtils.trimToEmpty(path);
+        if (GenericUtils.isEmpty(path)) {
             path = ".";
         }
+
         try {
             if (version < SFTP_V6) {
                 Path p = resolveFile(path).toAbsolutePath().normalize();
-                if (!Files.exists(p)) {
+                if (!Files.exists(p, IoUtils.EMPTY_OPTIONS)) {
                     throw new FileNotFoundException(p.toString());
                 }
                 sendPath(id, p, Collections.<String, Object>emptyMap());
@@ -741,6 +764,7 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
                     p = p.resolve(p2);
                 }
                 p = p.toAbsolutePath().normalize();
+
                 Map<String, Object> attrs = Collections.emptyMap();
                 if (control == SSH_FXP_REALPATH_STAT_IF) {
                     try {
@@ -913,7 +937,9 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
         if (version >= SFTP_V4) {
             flags = buffer.getInt();
         }
-        log.debug("Received SSH_FXP_FSTAT (handle={}, flags={})", handle, flags);
+        if (log.isDebugEnabled()) {
+            log.debug("Received SSH_FXP_FSTAT (handle={}, flags={})", handle, "0x" + Integer.toHexString(flags));
+        }
         try {
             Handle p = handles.get(handle);
             if (p == null) {
@@ -932,7 +958,9 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
         if (version >= SFTP_V4) {
             flags = buffer.getInt();
         }
-        log.debug("Received SSH_FXP_LSTAT (path={}, flags={})", path, flags);
+        if (log.isDebugEnabled()) {
+            log.debug("Received SSH_FXP_LSTAT (path={}, flags={})", path, "0x" + Integer.toHexString(flags));
+        }
         try {
             Path p = resolveFile(path);
             sendAttrs(id, p, flags, false);
@@ -953,7 +981,9 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
         }
         byte[] data = buffer.array();
         int doff = buffer.rpos();
-        log.debug("Received SSH_FXP_WRITE (handle={}, offset={}, data=byte[{}])", new Object[] { handle, offset, length });
+        if (log.isDebugEnabled()) {
+            log.debug("Received SSH_FXP_WRITE (handle={}, offset={}, data=byte[{}])", new Object[] { handle, offset, length });
+        }
         try {
             Handle p = handles.get(handle);
             if (!(p instanceof FileHandle)) {
@@ -972,7 +1002,9 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
         String handle = buffer.getString();
         long offset = buffer.getLong();
         int len = buffer.getInt();
-        log.debug("Received SSH_FXP_READ (handle={}, offset={}, length={})", new Object[]{handle, offset, len});
+        if (log.isDebugEnabled()) {
+            log.debug("Received SSH_FXP_READ (handle={}, offset={}, length={})", new Object[]{handle, offset, len});
+        }
         try {
             Handle p = handles.get(handle);
             if (!(p instanceof FileHandle)) {
@@ -1070,7 +1102,9 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
             }
         }
         Map<String, Object> attrs = readAttrs(buffer);
-        log.debug("Received SSH_FXP_OPEN (path={}, access={}, pflags={}, attrs={})", new Object[]{path, access, pflags, attrs});
+        if (log.isDebugEnabled()) {
+            log.debug("Received SSH_FXP_OPEN (path={}, access={}, pflags={}, attrs={})", new Object[]{path, access, pflags, attrs});
+        }
         try {
             Path file = resolveFile(path);
             String handle = UUID.randomUUID().toString();
@@ -1082,7 +1116,9 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
     }
 
     protected void doInit(Buffer buffer, int id) throws IOException {
-        log.debug("Received SSH_FXP_INIT (version={})", id);
+        if (log.isDebugEnabled()) {
+            log.debug("Received SSH_FXP_INIT (version={})", id);
+        }
         version = id;
         while (buffer.available() > 0) {
             String name = buffer.getString();
@@ -1094,13 +1130,13 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
         int hig = HIGHER_SFTP_IMPL;
         String all = ALL_SFTP_IMPL;
 
-        if (session.getFactoryManager().getProperties() != null) {
-            String sftpVersion = session.getFactoryManager().getProperties().get(SFTP_VERSION);
-            if (sftpVersion != null) {
-                low = hig = Integer.parseInt(sftpVersion);
-                all = sftpVersion;
-            }
+        // check if specific version forced
+        Integer sftpVersion = FactoryManagerUtils.getInteger(session, SFTP_VERSION);
+        if (sftpVersion != null) {
+            low = hig = sftpVersion.intValue();
+            all = sftpVersion.toString();
         }
+
         if (version >= low) {
             version = Math.min(version, hig);
             buffer.clear();
@@ -1204,17 +1240,14 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
         }
         buffer.putString(normalizedPath, StandardCharsets.UTF_8);
 
-        f = resolveFile(normalizedPath);
-        if (f.getFileName() == null) {
-            f = resolveFile(".");
-        }
         if (version == SFTP_V3) {
+            f = resolveFile(normalizedPath);
             buffer.putString(getLongName(f, attrs), StandardCharsets.UTF_8); // Format specified in the specs
             buffer.putInt(0);
         } else if (version >= SFTP_V4) {
             writeAttrs(buffer, attrs);
         } else {
-            throw new IllegalStateException();
+            throw new IllegalStateException("sendPath(" + f + ") unsupported version: " + version);
         }
         send(buffer);
     }
@@ -1240,7 +1273,7 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
         int nb = 0;
         while (files.hasNext() && buffer.wpos() < MAX_PACKET_LENGTH) {
             Path f = files.next();
-            buffer.putString(f.getFileName().toString(), StandardCharsets.UTF_8);
+            buffer.putString(getShortName(f), StandardCharsets.UTF_8);
             if (version == SFTP_V3) {
                 buffer.putString(getLongName(f), StandardCharsets.UTF_8); // Format specified in the specs
             }
@@ -1296,7 +1329,7 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
             }
         }
 
-        Long length = (Long) attributes.get("size");
+        Number length = (Number) attributes.get("size");
         if (length == null) {
             length = 0l;
         }
@@ -1304,17 +1337,17 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
 
         Boolean isDirectory = (Boolean) attributes.get("isDirectory");
         Boolean isLink = (Boolean) attributes.get("isSymbolicLink");
+        @SuppressWarnings("unchecked")
         Set<PosixFilePermission> perms = (Set<PosixFilePermission>) attributes.get("permissions");
         if (perms == null) {
-            perms = new HashSet<>();
+            perms = EnumSet.noneOf(PosixFilePermission.class);
         }
 
         StringBuilder sb = new StringBuilder();
-        sb.append((isDirectory != null && isDirectory) ? "d" : (isLink != null && isLink) ? "l" : "-");
+        sb.append((isDirectory != null && isDirectory.booleanValue()) ? "d" : (isLink != null && isLink.booleanValue()) ? "l" : "-");
         sb.append(PosixFilePermissions.toString(perms));
         sb.append("  ");
-        sb.append(attributes.containsKey("nlink")
-                ? attributes.get("nlink") : "1");
+        sb.append(attributes.containsKey("nlink") ? attributes.get("nlink") : "1");
         sb.append(" ");
         sb.append(username);
         sb.append(" ");
@@ -1324,11 +1357,38 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
         sb.append(" ");
         sb.append(getUnixDate((FileTime) attributes.get("lastModifiedTime")));
         sb.append(" ");
-        sb.append(f.getFileName().toString());
+        sb.append(getShortName(f));
 
         return sb.toString();
     }
 
+    protected String getShortName(Path f) {
+        if (OsUtils.isUNIX()) {
+            Path    name=f.getFileName();
+            if (name == null) {
+                Path    p=resolveFile(".");
+                name = p.getFileName();
+            }
+            
+            return name.toString();
+        } else {    // need special handling for Windows root drives
+            Path    abs=f.toAbsolutePath().normalize();
+            int     count=abs.getNameCount();
+            /*
+             * According to the javadoc:
+             * 
+             *      The number of elements in the path, or 0 if this path only
+             *      represents a root component
+             */
+            if (count > 0) {
+                Path    name=abs.getFileName();
+                return name.toString();
+            } else {
+                return abs.toString().replace(File.separatorChar, '/');
+            }
+        }
+    }
+
     protected int attributesToPermissions(boolean isReg, boolean isDir, boolean isLnk, Collection<PosixFilePermission> perms) {
         int pf = 0;
         if (perms != null) {
@@ -1361,6 +1421,7 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
                 case OTHERS_EXECUTE:
                     pf |= S_IXOTH;
                     break;
+                default: // ignored
                 }
             }
         }
@@ -1518,6 +1579,7 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
             case "creationTime":     view = "basic"; break;
             case "lastModifiedTime": view = "basic"; break;
             case "lastAccessTime":   view = "basic"; break;
+            default:    // ignored
             }
             if (view != null && value != null) {
                 try {
@@ -1547,6 +1609,8 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
                 break;
             case ThrowException:
                 throw new UnsupportedOperationException("Unsupported attributes: " + sb.toString());
+            default:
+                log.warn("Unknown policy for attributes=" + sb.toString() + ": " + unsupportedAttributePolicy);
             }
         }
     }
@@ -1590,6 +1654,8 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
             break;
         case ThrowException:
             throw e;
+        default:
+            log.warn("Unknown policy for principal=" + principalType.getSimpleName() + "[" + name + "]: " + unsupportedAttributePolicy);
         }
     }
 
@@ -1643,6 +1709,7 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
             case SSH_FILEXFER_TYPE_UNKNOWN:
                 attrs.put("isOther", true);
                 break;
+            default:    // ignored
             }
         }
         if ((flags & SSH_FILEXFER_ATTR_SIZE) != 0) {
@@ -1855,7 +1922,10 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
     }
 
     protected void sendStatus(int id, int substatus, String msg, String lang) throws IOException {
-        log.debug("Send SSH_FXP_STATUS (substatus={}, msg={})", substatus, msg);
+        if (log.isDebugEnabled()) {
+            log.debug("Send SSH_FXP_STATUS (substatus={}, lang={}, msg={})", new Object[] { substatus, lang, msg });
+        }
+
         Buffer buffer = new Buffer();
         buffer.putByte((byte) SSH_FXP_STATUS);
         buffer.putInt(id);
@@ -1912,7 +1982,7 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
 
     private Path resolveFile(String path) {
         //in case we are running on Windows
-        String localPath = (path == null) ? null : path.replace('/', File.separatorChar);
+        String localPath = SelectorUtils.translateToLocalPath(path);
         return defaultDir.resolve(localPath);
     }
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b640b02/sshd-core/src/test/java/org/apache/sshd/SshServerMain.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/SshServerMain.java b/sshd-core/src/test/java/org/apache/sshd/SshServerMain.java
new file mode 100644
index 0000000..63596c7
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/SshServerMain.java
@@ -0,0 +1,33 @@
+/*
+ * 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;
+
+/**
+ * Just a test class used to invoke {@link SshServer#main(String[])} in
+ * order to have logging - which is in {@code test} scope
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class SshServerMain {
+
+    public static void main(String[] args) throws Exception {
+        SshServer.main(args);
+    }
+
+}


[4/6] mina-sshd git commit: [SSHD-436] Refactor kex factories

Posted by gn...@apache.org.
[SSHD-436] Refactor kex factories


Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/73551939
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/73551939
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/73551939

Branch: refs/heads/master
Commit: 73551939d8dd6f10bbc7fecefd3abc77df42f54d
Parents: 7ea0788
Author: Guillaume Nodet <gn...@apache.org>
Authored: Thu Mar 26 16:20:26 2015 +0100
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Mon Mar 30 10:52:43 2015 +0200

----------------------------------------------------------------------
 .../main/java/org/apache/sshd/SshBuilder.java   | 152 +++++----
 .../client/kex/AbstractDHClientKeyExchange.java |  52 +++
 .../sshd/client/kex/AbstractDHGClient.java      | 144 ---------
 .../java/org/apache/sshd/client/kex/DHG1.java   |  55 ----
 .../java/org/apache/sshd/client/kex/DHG14.java  |  57 ----
 .../org/apache/sshd/client/kex/DHGClient.java   | 131 ++++++++
 .../java/org/apache/sshd/client/kex/DHGEX.java  | 195 ------------
 .../org/apache/sshd/client/kex/DHGEX256.java    |  58 ----
 .../org/apache/sshd/client/kex/DHGEXClient.java | 160 ++++++++++
 .../org/apache/sshd/client/kex/ECDHP256.java    |  53 ----
 .../org/apache/sshd/client/kex/ECDHP384.java    |  53 ----
 .../org/apache/sshd/client/kex/ECDHP521.java    |  53 ----
 .../apache/sshd/common/FactoryManagerUtils.java |  18 +-
 .../org/apache/sshd/common/NamedFactory.java    |  44 ++-
 .../org/apache/sshd/common/NamedResource.java   |  30 ++
 .../org/apache/sshd/common/ServiceFactory.java  |  26 +-
 .../org/apache/sshd/common/kex/AbstractDH.java  |  10 +-
 .../sshd/common/kex/BuiltinDHFactories.java     | 184 +++++++++++
 .../java/org/apache/sshd/common/kex/DH.java     | 118 -------
 .../org/apache/sshd/common/kex/DHFactory.java   |  34 ++
 .../java/org/apache/sshd/common/kex/DHG.java    | 119 +++++++
 .../java/org/apache/sshd/common/kex/ECDH.java   |   9 +-
 .../common/kex/dh/AbstractDHKeyExchange.java    |  67 ++++
 .../sshd/server/kex/AbstractDHGServer.java      | 151 ---------
 .../server/kex/AbstractDHServerKeyExchange.java |  50 +++
 .../java/org/apache/sshd/server/kex/DHG1.java   |  54 ----
 .../java/org/apache/sshd/server/kex/DHG14.java  |  58 ----
 .../java/org/apache/sshd/server/kex/DHGEX.java  | 314 -------------------
 .../org/apache/sshd/server/kex/DHGEX256.java    |  55 ----
 .../org/apache/sshd/server/kex/DHGEXServer.java | 283 +++++++++++++++++
 .../org/apache/sshd/server/kex/DHGServer.java   | 136 ++++++++
 .../org/apache/sshd/server/kex/ECDHP256.java    |  53 ----
 .../org/apache/sshd/server/kex/ECDHP384.java    |  53 ----
 .../org/apache/sshd/server/kex/ECDHP521.java    |  53 ----
 .../src/test/java/org/apache/sshd/KexTest.java  | 153 ---------
 .../src/test/java/org/apache/sshd/LoadTest.java |  79 ++---
 .../org/apache/sshd/client/kex/KexTest.java     | 147 +++++++++
 .../sshd/common/kex/BuiltinDHFactoriesTest.java |  44 +++
 38 files changed, 1621 insertions(+), 1884 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java b/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java
index bac6163..e441457 100644
--- a/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java
+++ b/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java
@@ -24,6 +24,8 @@ import java.util.Collections;
 import java.util.List;
 
 import org.apache.sshd.client.ServerKeyVerifier;
+import org.apache.sshd.client.kex.DHGClient;
+import org.apache.sshd.client.kex.DHGEXClient;
 import org.apache.sshd.client.keyverifier.AcceptAllServerKeyVerifier;
 import org.apache.sshd.common.AbstractFactoryManager;
 import org.apache.sshd.common.Channel;
@@ -43,12 +45,14 @@ import org.apache.sshd.common.file.FileSystemFactory;
 import org.apache.sshd.common.file.nativefs.NativeFileSystemFactory;
 import org.apache.sshd.common.forward.DefaultTcpipForwarderFactory;
 import org.apache.sshd.common.forward.TcpipServerChannel;
+import org.apache.sshd.common.kex.BuiltinDHFactories;
 import org.apache.sshd.common.mac.HMACMD5;
 import org.apache.sshd.common.mac.HMACMD596;
 import org.apache.sshd.common.mac.HMACSHA1;
 import org.apache.sshd.common.mac.HMACSHA196;
 import org.apache.sshd.common.mac.HMACSHA256;
 import org.apache.sshd.common.mac.HMACSHA512;
+import org.apache.sshd.common.kex.DHFactory;
 import org.apache.sshd.common.random.BouncyCastleRandom;
 import org.apache.sshd.common.random.JceRandom;
 import org.apache.sshd.common.random.SingletonRandomFactory;
@@ -63,6 +67,8 @@ import org.apache.sshd.server.global.CancelTcpipForwardHandler;
 import org.apache.sshd.server.global.KeepAliveHandler;
 import org.apache.sshd.server.global.NoMoreSessionsHandler;
 import org.apache.sshd.server.global.TcpipForwardHandler;
+import org.apache.sshd.server.kex.DHGEXServer;
+import org.apache.sshd.server.kex.DHGServer;
 
 /**
  * A builder object for creating SshServer instances.
@@ -287,7 +293,7 @@ public class SshBuilder {
          * ciphers according to the <tt>ignoreUnsupported</tt> parameter
          * @see BuiltinCiphers#isSupported()
          */
-        protected static List<NamedFactory<Cipher>> setUpDefaultCiphers(boolean ignoreUnsupported) {
+        public static List<NamedFactory<Cipher>> setUpDefaultCiphers(boolean ignoreUnsupported) {
             List<NamedFactory<Cipher>> avail = new ArrayList<NamedFactory<Cipher>>(DEFAULT_CIPHERS_PREFERENCE.size());
             for (BuiltinCiphers c : DEFAULT_CIPHERS_PREFERENCE) {
                 if (ignoreUnsupported || c.isSupported()) {
@@ -297,6 +303,26 @@ public class SshBuilder {
 
             return avail;
         }
+        
+        /**
+         * The default {@link BuiltinDHFactories} setup in order of preference
+         * as specified by <A HREF="https://www.freebsd.org/cgi/man.cgi?query=ssh_config&sektion=5">
+         * ssh_config(5)</A> 
+         */
+        public static final List<BuiltinDHFactories> DEFAULT_KEX_PREFERENCE=
+                Collections.unmodifiableList(
+                        Arrays.asList(
+                                BuiltinDHFactories.ecdhp521,
+                                BuiltinDHFactories.ecdhp384,
+                                BuiltinDHFactories.ecdhp256,
+                                
+                                BuiltinDHFactories.dhgex256,
+                                BuiltinDHFactories.dhgex,
+                                
+                                BuiltinDHFactories.dhg14,
+                                BuiltinDHFactories.dhg1
+                        ));
+
     }
 
     /**
@@ -314,35 +340,8 @@ public class SshBuilder {
         @Override
         protected ClientBuilder fillWithDefaultValues() {
             super.fillWithDefaultValues();
-            if (SecurityUtils.isBouncyCastleRegistered()) {
-                if (keyExchangeFactories == null) {
-                    keyExchangeFactories = Arrays.asList(
-                            new org.apache.sshd.client.kex.DHGEX256.Factory(),
-                            new org.apache.sshd.client.kex.DHGEX.Factory(),
-                            new org.apache.sshd.client.kex.ECDHP256.Factory(),
-                            new org.apache.sshd.client.kex.ECDHP384.Factory(),
-                            new org.apache.sshd.client.kex.ECDHP521.Factory(),
-                            new org.apache.sshd.client.kex.DHG14.Factory(),
-                            new org.apache.sshd.client.kex.DHG1.Factory());
-                }
-            // EC keys are not supported until OpenJDK 7
-            } else if (SecurityUtils.hasEcc()) {
-                if (keyExchangeFactories == null) {
-                    keyExchangeFactories = Arrays.asList(
-                            new org.apache.sshd.client.kex.DHGEX256.Factory(),
-                            new org.apache.sshd.client.kex.DHGEX.Factory(),
-                            new org.apache.sshd.client.kex.ECDHP256.Factory(),
-                            new org.apache.sshd.client.kex.ECDHP384.Factory(),
-                            new org.apache.sshd.client.kex.ECDHP521.Factory(),
-                            new org.apache.sshd.client.kex.DHG1.Factory());
-                }
-            } else {
-                if (keyExchangeFactories == null) {
-                    keyExchangeFactories = Arrays.asList(
-                            new org.apache.sshd.client.kex.DHGEX256.Factory(),
-                            new org.apache.sshd.client.kex.DHGEX.Factory(),
-                            new org.apache.sshd.client.kex.DHG1.Factory());
-                }
+            if (keyExchangeFactories == null) {
+                keyExchangeFactories = setUpDefaultKeyExchanges(false);
             }
             if (channelFactories == null) {
                 channelFactories = Arrays.<NamedFactory<Channel>>asList(
@@ -363,6 +362,37 @@ public class SshBuilder {
             client.setServerKeyVerifier(serverKeyVerifier);
             return client;
         }
+
+        /**
+         * @param ignoreUnsupported If {@code true} then all the default
+         * key exchanges are included, regardless of whether they are currently
+         * supported by the JCE. Otherwise, only the supported ones out of the
+         * list are included
+         * @return A {@link List} of the default {@link NamedFactory}
+         * instances of the {@link KeyExchange}s according to the preference
+         * order defined by {@link #DEFAULT_KEX_PREFERENCE}.
+         * <B>Note:</B> the list may be filtered to exclude unsupported JCE
+         * key exchanges according to the <tt>ignoreUnsupported</tt> parameter
+         * @see BuiltinDHFactories#isSupported()
+         */
+        public static List<NamedFactory<KeyExchange>> setUpDefaultKeyExchanges(boolean ignoreUnsupported) {
+            List<NamedFactory<KeyExchange>> avail = new ArrayList<>(DEFAULT_KEX_PREFERENCE.size());
+            for (BuiltinDHFactories f : BuiltinDHFactories.VALUES) {
+                if (ignoreUnsupported || f.isSupported()) {
+                    avail.add(getKeyExchangeFactory(f));
+                }
+            }
+            return avail;
+        }
+
+        public static NamedFactory<KeyExchange> getKeyExchangeFactory(DHFactory factory) {
+            if (factory.isGroupExchange()) {
+                return DHGEXClient.newFactory(factory);
+            } else {
+                return DHGClient.newFactory(factory);
+            }
+        }
+
     }
 
     /**
@@ -373,35 +403,8 @@ public class SshBuilder {
         @Override
         protected ServerBuilder fillWithDefaultValues() {
             super.fillWithDefaultValues();
-            if (SecurityUtils.isBouncyCastleRegistered()) {
-                if (keyExchangeFactories == null) {
-                    keyExchangeFactories = Arrays.asList(
-                            new org.apache.sshd.server.kex.DHGEX256.Factory(),
-                            new org.apache.sshd.server.kex.DHGEX.Factory(),
-                            new org.apache.sshd.server.kex.ECDHP256.Factory(),
-                            new org.apache.sshd.server.kex.ECDHP384.Factory(),
-                            new org.apache.sshd.server.kex.ECDHP521.Factory(),
-                            new org.apache.sshd.server.kex.DHG14.Factory(),
-                            new org.apache.sshd.server.kex.DHG1.Factory());
-                }
-            // EC keys are not supported until OpenJDK 7
-            } else if (SecurityUtils.hasEcc()) {
-                if (keyExchangeFactories == null) {
-                    keyExchangeFactories = Arrays.asList(
-                            new org.apache.sshd.server.kex.DHGEX256.Factory(),
-                            new org.apache.sshd.server.kex.DHGEX.Factory(),
-                            new org.apache.sshd.server.kex.ECDHP256.Factory(),
-                            new org.apache.sshd.server.kex.ECDHP384.Factory(),
-                            new org.apache.sshd.server.kex.ECDHP521.Factory(),
-                            new org.apache.sshd.server.kex.DHG1.Factory());
-                }
-            } else {
-                if (keyExchangeFactories == null) {
-                    keyExchangeFactories = Arrays.asList(
-                            new org.apache.sshd.server.kex.DHGEX256.Factory(),
-                            new org.apache.sshd.server.kex.DHGEX.Factory(),
-                            new org.apache.sshd.server.kex.DHG1.Factory());
-                }
+            if (keyExchangeFactories == null) {
+                keyExchangeFactories = setUpDefaultKeyExchanges(false);
             }
             if (channelFactories == null) {
                 channelFactories = Arrays.asList(
@@ -420,6 +423,37 @@ public class SshBuilder {
             }
             return me();
         }
+
+        /**
+         * @param ignoreUnsupported If {@code true} then all the default
+         * key exchanges are included, regardless of whether they are currently
+         * supported by the JCE. Otherwise, only the supported ones out of the
+         * list are included
+         * @return A {@link List} of the default {@link NamedFactory}
+         * instances of the {@link KeyExchange}s according to the preference
+         * order defined by {@link #DEFAULT_KEX_PREFERENCE}.
+         * <B>Note:</B> the list may be filtered to exclude unsupported JCE
+         * key exchanges according to the <tt>ignoreUnsupported</tt> parameter
+         * @see BuiltinDHFactories#isSupported()
+         */
+        public static List<NamedFactory<KeyExchange>> setUpDefaultKeyExchanges(boolean ignoreUnsupported) {
+            List<NamedFactory<KeyExchange>> avail = new ArrayList<>(DEFAULT_KEX_PREFERENCE.size());
+            for (BuiltinDHFactories f : BuiltinDHFactories.VALUES) {
+                if (ignoreUnsupported || f.isSupported()) {
+                    avail.add(getKeyExchangeFactory(f));
+                }
+            }
+            return avail;
+        }
+
+        public static NamedFactory<KeyExchange> getKeyExchangeFactory(DHFactory factory) {
+            if (factory.isGroupExchange()) {
+                return DHGEXServer.newFactory(factory);
+            } else {
+                return DHGServer.newFactory(factory);
+            }
+        }
+
     }
 
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/client/kex/AbstractDHClientKeyExchange.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/kex/AbstractDHClientKeyExchange.java b/sshd-core/src/main/java/org/apache/sshd/client/kex/AbstractDHClientKeyExchange.java
new file mode 100644
index 0000000..077f159
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/kex/AbstractDHClientKeyExchange.java
@@ -0,0 +1,52 @@
+/*
+ * 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.client.kex;
+
+import java.security.PublicKey;
+
+import org.apache.sshd.client.session.ClientSessionImpl;
+import org.apache.sshd.common.kex.dh.AbstractDHKeyExchange;
+import org.apache.sshd.common.session.AbstractSession;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public abstract class AbstractDHClientKeyExchange extends AbstractDHKeyExchange {
+
+    protected ClientSessionImpl session;
+    protected PublicKey serverKey;
+
+    protected AbstractDHClientKeyExchange() {
+        super();
+    }
+
+    @Override
+    public void init(AbstractSession s, byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception {
+        super.init(s, V_S, V_C, I_S, I_C);
+        if (!(s instanceof ClientSessionImpl)) {
+            throw new IllegalStateException("Using a client side KeyExchange on a server");
+        }
+        session = (ClientSessionImpl) s;
+    }
+
+    public PublicKey getServerKey() {
+        return serverKey;
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/client/kex/AbstractDHGClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/kex/AbstractDHGClient.java b/sshd-core/src/main/java/org/apache/sshd/client/kex/AbstractDHGClient.java
deleted file mode 100644
index 68d6dd4..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/client/kex/AbstractDHGClient.java
+++ /dev/null
@@ -1,144 +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.client.kex;
-
-import java.security.PublicKey;
-
-import org.apache.sshd.client.session.ClientSessionImpl;
-import org.apache.sshd.common.Digest;
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.Signature;
-import org.apache.sshd.common.SshConstants;
-import org.apache.sshd.common.SshException;
-import org.apache.sshd.common.kex.AbstractDH;
-import org.apache.sshd.common.kex.DH;
-import org.apache.sshd.common.session.AbstractSession;
-import org.apache.sshd.common.util.Buffer;
-import org.apache.sshd.common.util.KeyUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Base class for DHG key exchange algorithms.
- * Implementations will only have to configure the required data on the
- * {@link DH} class in the {@link #getDH()} method.
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public abstract class AbstractDHGClient implements KeyExchange {
-
-    private final Logger log = LoggerFactory.getLogger(getClass());
-
-    private ClientSessionImpl session;
-    private byte[] V_S;
-    private byte[] V_C;
-    private byte[] I_S;
-    private byte[] I_C;
-    private Digest hash;
-    private AbstractDH dh;
-    private byte[] e;
-    private byte[] f;
-    private byte[] K;
-    private byte[] H;
-    private PublicKey serverKey;
-
-    public void init(AbstractSession s, byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception {
-        if (!(s instanceof ClientSessionImpl)) {
-            throw new IllegalStateException("Using a client side KeyExchange on a server");
-        }
-        session = (ClientSessionImpl) s;
-        this.V_S = V_S;
-        this.V_C = V_C;
-        this.I_S = I_S;
-        this.I_C = I_C;
-        dh = getDH();
-        hash =  dh.getHash();
-        hash.init();
-        e = dh.getE();
-
-        log.debug("Send SSH_MSG_KEXDH_INIT");
-        Buffer buffer = s.createBuffer(SshConstants.SSH_MSG_KEXDH_INIT);
-        buffer.putMPInt(e);
-        session.writePacket(buffer);
-    }
-
-    protected abstract AbstractDH getDH() throws Exception;
-
-    public boolean next(Buffer buffer) throws Exception {
-        byte cmd = buffer.getByte();
-        if (cmd != SshConstants.SSH_MSG_KEXDH_REPLY) {
-            throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
-                                   "Protocol error: expected packet SSH_MSG_KEXDH_REPLY, got " + cmd);
-        }
-
-        log.debug("Received SSH_MSG_KEXDH_REPLY");
-        
-        byte[] K_S = buffer.getBytes();
-        f = buffer.getMPIntAsBytes();
-        byte[] sig = buffer.getBytes();
-        dh.setF(f);
-        K = dh.getK();
-
-        buffer = new Buffer(K_S);
-        serverKey = buffer.getRawPublicKey();
-        final String keyAlg = KeyUtils.getKeyType(serverKey);
-        if (keyAlg == null) {
-            throw new SshException("Unsupported server key type");
-        }
-
-        buffer = new Buffer();
-        buffer.putString(V_C);
-        buffer.putString(V_S);
-        buffer.putString(I_C);
-        buffer.putString(I_S);
-        buffer.putString(K_S);
-        buffer.putMPInt(e);
-        buffer.putMPInt(f);
-        buffer.putMPInt(K);
-        hash.update(buffer.array(), 0, buffer.available());
-        H = hash.digest();
-
-        Signature verif = NamedFactory.Utils.create(session.getFactoryManager().getSignatureFactories(), keyAlg);
-        verif.init(serverKey, null);
-        verif.update(H, 0, H.length);
-        if (!verif.verify(sig)) {
-            throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
-                                   "KeyExchange signature verification failed");
-        }
-        return true;
-    }
-
-    public Digest getHash() {
-        return hash;
-    }
-
-    public byte[] getH() {
-        return H;
-    }
-
-    public byte[] getK() {
-        return K;
-    }
-
-    public PublicKey getServerKey() {
-        return serverKey;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/client/kex/DHG1.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/kex/DHG1.java b/sshd-core/src/main/java/org/apache/sshd/client/kex/DHG1.java
deleted file mode 100644
index 5359d03..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/client/kex/DHG1.java
+++ /dev/null
@@ -1,55 +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.client.kex;
-
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.kex.DH;
-import org.apache.sshd.common.kex.DHGroupData;
-
-/**
- * TODO Add javadoc
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class DHG1 extends AbstractDHGClient {
-
-    /**
-     * Named factory for DHG1 key exchange
-     */
-    public static class Factory implements NamedFactory<KeyExchange> {
-
-        public String getName() {
-            return "diffie-hellman-group1-sha1";
-        }
-
-        public KeyExchange create() {
-            return new DHG1();
-        }
-
-    }
-
-    protected DH getDH() throws Exception {
-        DH dh = new DH();
-        dh.setG(DHGroupData.getG());
-        dh.setP(DHGroupData.getP1());
-        return dh;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/client/kex/DHG14.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/kex/DHG14.java b/sshd-core/src/main/java/org/apache/sshd/client/kex/DHG14.java
deleted file mode 100644
index 6c47e9d..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/client/kex/DHG14.java
+++ /dev/null
@@ -1,57 +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.client.kex;
-
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.kex.DH;
-import org.apache.sshd.common.kex.DHGroupData;
-
-/**
- * DHG14 does not work with the default JCE implementation provided by Sun
- * because it does not support 2048 bits encryption.
- * It requires BouncyCastle to be used.
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class DHG14 extends AbstractDHGClient {
-
-    /**
-     * Named factory for DHG14 key exchange
-     */
-    public static class Factory implements NamedFactory<KeyExchange> {
-
-        public String getName() {
-            return "diffie-hellman-group14-sha1";
-        }
-
-        public KeyExchange create() {
-            return new DHG14();
-        }
-
-    }
-
-    protected DH getDH() throws Exception {
-        DH dh = new DH();
-        dh.setG(DHGroupData.getG());
-        dh.setP(DHGroupData.getP14());
-        return dh;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGClient.java b/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGClient.java
new file mode 100644
index 0000000..69bea58
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGClient.java
@@ -0,0 +1,131 @@
+/*
+ * 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.client.kex;
+
+import org.apache.sshd.common.KeyExchange;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.Signature;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.kex.AbstractDH;
+import org.apache.sshd.common.kex.DHFactory;
+import org.apache.sshd.common.session.AbstractSession;
+import org.apache.sshd.common.util.Buffer;
+import org.apache.sshd.common.util.KeyUtils;
+
+/**
+ * Base class for DHG key exchange algorithms.
+ * Implementations will only have to configure the required data on the
+ * {@link org.apache.sshd.common.kex.DHG} class in the {@link #getDH()} method.
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class DHGClient extends AbstractDHClientKeyExchange {
+
+    protected final DHFactory factory;
+    protected AbstractDH dh;
+
+    public static final NamedFactory<KeyExchange> newFactory(final DHFactory delegate) {
+        return new NamedFactory<KeyExchange>() {
+            @Override
+            public String getName() {
+                return delegate.getName();
+            }
+
+            @Override
+            public KeyExchange create() {
+                return new DHGClient(delegate);
+            }
+
+            @Override
+            public String toString() {
+                return NamedFactory.class.getSimpleName()
+                        + "<" + KeyExchange.class.getSimpleName() + ">"
+                        + "[" + getName() + "]";
+            }
+        };
+    }
+
+    protected DHGClient(DHFactory factory) {
+        super();
+        this.factory = factory;
+    }
+
+    public void init(AbstractSession s, byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception {
+        super.init(s, V_S, V_C, I_S, I_C);
+        dh = getDH();
+        hash =  dh.getHash();
+        hash.init();
+        e = dh.getE();
+
+        log.debug("Send SSH_MSG_KEXDH_INIT");
+        Buffer buffer = s.createBuffer(SshConstants.SSH_MSG_KEXDH_INIT);
+        buffer.putMPInt(e);
+        session.writePacket(buffer);
+    }
+
+    protected AbstractDH getDH() throws Exception {
+        return factory.create();
+    }
+
+    public boolean next(Buffer buffer) throws Exception {
+        byte cmd = buffer.getByte();
+        if (cmd != SshConstants.SSH_MSG_KEXDH_REPLY) {
+            throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
+                                   "Protocol error: expected packet SSH_MSG_KEXDH_REPLY, got " + cmd);
+        }
+
+        log.debug("Received SSH_MSG_KEXDH_REPLY");
+        
+        byte[] K_S = buffer.getBytes();
+        f = buffer.getMPIntAsBytes();
+        byte[] sig = buffer.getBytes();
+        dh.setF(f);
+        K = dh.getK();
+
+        buffer = new Buffer(K_S);
+        serverKey = buffer.getRawPublicKey();
+        final String keyAlg = KeyUtils.getKeyType(serverKey);
+        if (keyAlg == null) {
+            throw new SshException("Unsupported server key type");
+        }
+
+        buffer = new Buffer();
+        buffer.putString(V_C);
+        buffer.putString(V_S);
+        buffer.putString(I_C);
+        buffer.putString(I_S);
+        buffer.putString(K_S);
+        buffer.putMPInt(e);
+        buffer.putMPInt(f);
+        buffer.putMPInt(K);
+        hash.update(buffer.array(), 0, buffer.available());
+        H = hash.digest();
+
+        Signature verif = NamedFactory.Utils.create(session.getFactoryManager().getSignatureFactories(), keyAlg);
+        verif.init(serverKey, null);
+        verif.update(H, 0, H.length);
+        if (!verif.verify(sig)) {
+            throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
+                                   "KeyExchange signature verification failed");
+        }
+        return true;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEX.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEX.java b/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEX.java
deleted file mode 100644
index c493a34..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEX.java
+++ /dev/null
@@ -1,195 +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.client.kex;
-
-import java.math.BigInteger;
-import java.security.PublicKey;
-
-import org.apache.sshd.client.session.ClientSessionImpl;
-import org.apache.sshd.common.Digest;
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.Signature;
-import org.apache.sshd.common.SshConstants;
-import org.apache.sshd.common.SshException;
-import org.apache.sshd.common.kex.AbstractDH;
-import org.apache.sshd.common.kex.DH;
-import org.apache.sshd.common.session.AbstractSession;
-import org.apache.sshd.common.util.Buffer;
-import org.apache.sshd.common.util.KeyUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Client side Diffie Hellman Group Exchange
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class DHGEX implements KeyExchange {
-
-    /**
-     * Named factory for DHGEX key exchange
-     */
-    public static class Factory implements NamedFactory<KeyExchange> {
-
-        public String getName() {
-            return "diffie-hellman-group-exchange-sha1";
-        }
-
-        public KeyExchange create() {
-            return new DHGEX();
-        }
-
-    }
-
-    private final Logger log = LoggerFactory.getLogger(getClass());
-
-    private ClientSessionImpl session;
-    private byte[] V_S;
-    private byte[] V_C;
-    private byte[] I_S;
-    private byte[] I_C;
-    private Digest hash;
-    private AbstractDH dh;
-    private byte[] p;
-    private byte[] g;
-    private byte[] e;
-    private byte[] f;
-    private byte[] K;
-    private byte[] H;
-    private PublicKey serverKey;
-    private byte expected;
-
-    int min = 1024;
-    int prf = 4096;
-    int max = 8192;
-
-    public void init(AbstractSession s, byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception {
-        if (!(s instanceof ClientSessionImpl)) {
-            throw new IllegalStateException("Using a client side KeyExchange on a server");
-        }
-        session = (ClientSessionImpl) s;
-        this.V_S = V_S;
-        this.V_C = V_C;
-        this.I_S = I_S;
-        this.I_C = I_C;
-
-        log.debug("Send SSH_MSG_KEX_DH_GEX_REQUEST");
-        Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST);
-        buffer.putInt(min);
-        buffer.putInt(prf);
-        buffer.putInt(max);
-        session.writePacket(buffer);
-
-        expected = SshConstants.SSH_MSG_KEX_DH_GEX_GROUP;
-    }
-
-    public boolean next(Buffer buffer) throws Exception {
-        byte cmd = buffer.getByte();
-        if (cmd != expected) {
-            throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
-                    "Protocol error: expected packet " + expected + ", got " + cmd);
-        }
-
-        if (cmd == SshConstants.SSH_MSG_KEX_DH_GEX_GROUP) {
-            log.debug("Received SSH_MSG_KEX_DH_GEX_GROUP");
-            p = buffer.getMPIntAsBytes();
-            g = buffer.getMPIntAsBytes();
-
-            dh = getDH(new BigInteger(p), new BigInteger(g));
-            hash =  dh.getHash();
-            hash.init();
-            e = dh.getE();
-
-            log.debug("Send SSH_MSG_KEX_DH_GEX_INIT");
-            buffer = session.createBuffer(SshConstants.SSH_MSG_KEX_DH_GEX_INIT);
-            buffer.putMPInt(e);
-            session.writePacket(buffer);
-            expected = SshConstants.SSH_MSG_KEX_DH_GEX_REPLY;
-            return false;
-        }
-
-        if (cmd == SshConstants.SSH_MSG_KEX_DH_GEX_REPLY) {
-            log.debug("Received SSH_MSG_KEX_DH_GEX_REPLY");
-            byte[] K_S = buffer.getBytes();
-            f = buffer.getMPIntAsBytes();
-            byte[] sig = buffer.getBytes();
-            dh.setF(f);
-            K = dh.getK();
-
-            buffer = new Buffer(K_S);
-            serverKey = buffer.getRawPublicKey();
-            final String keyAlg = KeyUtils.getKeyType(serverKey);
-            if (keyAlg == null) {
-                throw new SshException("Unsupported server key type");
-            }
-
-            buffer = new Buffer();
-            buffer.putString(V_C);
-            buffer.putString(V_S);
-            buffer.putString(I_C);
-            buffer.putString(I_S);
-            buffer.putString(K_S);
-            buffer.putInt(min);
-            buffer.putInt(prf);
-            buffer.putInt(max);
-            buffer.putMPInt(p);
-            buffer.putMPInt(g);
-            buffer.putMPInt(e);
-            buffer.putMPInt(f);
-            buffer.putMPInt(K);
-            hash.update(buffer.array(), 0, buffer.available());
-            H = hash.digest();
-
-            Signature verif = NamedFactory.Utils.create(session.getFactoryManager().getSignatureFactories(), keyAlg);
-            verif.init(serverKey, null);
-            verif.update(H, 0, H.length);
-            if (!verif.verify(sig)) {
-                throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
-                        "KeyExchange signature verification failed");
-            }
-            return true;
-        }
-
-        throw new IllegalStateException();
-    }
-
-    protected DH getDH(BigInteger p, BigInteger g) throws Exception {
-        DH dh = new DH();
-        dh.setP(p);
-        dh.setG(g);
-        return dh;
-    }
-
-    public Digest getHash() {
-        return hash;
-    }
-
-    public byte[] getH() {
-        return H;
-    }
-
-    public byte[] getK() {
-        return K;
-    }
-
-    public PublicKey getServerKey() {
-        return serverKey;
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEX256.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEX256.java b/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEX256.java
deleted file mode 100644
index a9582af..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEX256.java
+++ /dev/null
@@ -1,58 +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.client.kex;
-
-import java.math.BigInteger;
-
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.digest.SHA256;
-import org.apache.sshd.common.kex.DH;
-
-/**
- * Client side Diffie Hellman Group Exchange
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class DHGEX256 extends DHGEX {
-
-    /**
-     * Named factory for DHGEX key exchange
-     */
-    public static class Factory implements NamedFactory<KeyExchange> {
-
-        public String getName() {
-            return "diffie-hellman-group-exchange-sha256";
-        }
-
-        public KeyExchange create() {
-            return new DHGEX256();
-        }
-
-    }
-
-    @Override
-    protected DH getDH(BigInteger p, BigInteger g) throws Exception {
-        DH dh = new DH(new SHA256.Factory());
-        dh.setP(p);
-        dh.setG(g);
-        return dh;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEXClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEXClient.java b/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEXClient.java
new file mode 100644
index 0000000..38fca91
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEXClient.java
@@ -0,0 +1,160 @@
+/*
+ * 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.client.kex;
+
+import java.math.BigInteger;
+
+import org.apache.sshd.common.KeyExchange;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.Signature;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.kex.AbstractDH;
+import org.apache.sshd.common.kex.DHFactory;
+import org.apache.sshd.common.session.AbstractSession;
+import org.apache.sshd.common.util.Buffer;
+import org.apache.sshd.common.util.KeyUtils;
+
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class DHGEXClient extends AbstractDHClientKeyExchange {
+
+    protected final DHFactory factory;
+    protected byte expected;
+    protected int min = 1024;
+    protected int prf = 4096;
+    protected int max = 8192;
+    protected AbstractDH dh;
+    protected byte[] p;
+    protected byte[] g;
+
+    public static final NamedFactory<KeyExchange> newFactory(final DHFactory delegate) {
+        return new NamedFactory<KeyExchange>() {
+            public String getName() {
+                return delegate.getName();
+            }
+
+            public KeyExchange create() {
+                return new DHGEXClient(delegate);
+            }
+
+            @Override
+            public String toString() {
+                return NamedFactory.class.getSimpleName()
+                        + "<" + KeyExchange.class.getSimpleName() + ">"
+                        + "[" + getName() + "]";
+            }
+        };
+    }
+    protected DHGEXClient(DHFactory factory) {
+        super();
+        this.factory = factory;
+    }
+
+    @Override
+    public void init(AbstractSession s, byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception {
+        super.init(s, V_S, V_C, I_S, I_C);
+        log.debug("Send SSH_MSG_KEX_DH_GEX_REQUEST");
+        Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST);
+        buffer.putInt(min);
+        buffer.putInt(prf);
+        buffer.putInt(max);
+        session.writePacket(buffer);
+
+        expected = SshConstants.SSH_MSG_KEX_DH_GEX_GROUP;
+    }
+
+    public boolean next(Buffer buffer) throws Exception {
+        byte cmd = buffer.getByte();
+        if (cmd != expected) {
+            throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
+                    "Protocol error: expected packet " + expected + ", got " + cmd);
+        }
+
+        if (cmd == SshConstants.SSH_MSG_KEX_DH_GEX_GROUP) {
+            log.debug("Received SSH_MSG_KEX_DH_GEX_GROUP");
+            p = buffer.getMPIntAsBytes();
+            g = buffer.getMPIntAsBytes();
+
+            dh = getDH(new BigInteger(p), new BigInteger(g));
+            hash = dh.getHash();
+            hash.init();
+            e = dh.getE();
+
+            log.debug("Send SSH_MSG_KEX_DH_GEX_INIT");
+            buffer = session.createBuffer(SshConstants.SSH_MSG_KEX_DH_GEX_INIT);
+            buffer.putMPInt(e);
+            session.writePacket(buffer);
+            expected = SshConstants.SSH_MSG_KEX_DH_GEX_REPLY;
+            return false;
+        }
+
+        if (cmd == SshConstants.SSH_MSG_KEX_DH_GEX_REPLY) {
+            log.debug("Received SSH_MSG_KEX_DH_GEX_REPLY");
+            byte[] K_S = buffer.getBytes();
+            f = buffer.getMPIntAsBytes();
+            byte[] sig = buffer.getBytes();
+            dh.setF(f);
+            K = dh.getK();
+
+            buffer = new Buffer(K_S);
+            serverKey = buffer.getRawPublicKey();
+            final String keyAlg = KeyUtils.getKeyType(serverKey);
+            if (keyAlg == null) {
+                throw new SshException("Unsupported server key type");
+            }
+
+            buffer = new Buffer();
+            buffer.putString(V_C);
+            buffer.putString(V_S);
+            buffer.putString(I_C);
+            buffer.putString(I_S);
+            buffer.putString(K_S);
+            buffer.putInt(min);
+            buffer.putInt(prf);
+            buffer.putInt(max);
+            buffer.putMPInt(p);
+            buffer.putMPInt(g);
+            buffer.putMPInt(e);
+            buffer.putMPInt(f);
+            buffer.putMPInt(K);
+            hash.update(buffer.array(), 0, buffer.available());
+            H = hash.digest();
+
+            Signature verif = NamedFactory.Utils.create(session.getFactoryManager().getSignatureFactories(), keyAlg);
+            verif.init(serverKey, null);
+            verif.update(H, 0, H.length);
+            if (!verif.verify(sig)) {
+                throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
+                        "KeyExchange signature verification failed");
+            }
+            return true;
+        }
+
+        throw new IllegalStateException("Unknown command value: " + cmd);
+    }
+
+    protected AbstractDH getDH(BigInteger p, BigInteger g) throws Exception {
+        return factory.create(p, g);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/client/kex/ECDHP256.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/kex/ECDHP256.java b/sshd-core/src/main/java/org/apache/sshd/client/kex/ECDHP256.java
deleted file mode 100644
index e14738e..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/client/kex/ECDHP256.java
+++ /dev/null
@@ -1,53 +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.client.kex;
-
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.cipher.ECCurves;
-import org.apache.sshd.common.kex.AbstractDH;
-import org.apache.sshd.common.kex.ECDH;
-
-/**
- * Elliptic Curve Diffie-Hellman with NIST P-256 curve.
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class ECDHP256 extends AbstractDHGClient {
-
-    public static class Factory implements NamedFactory<KeyExchange> {
-
-        public String getName() {
-            return "ecdh-sha2-nistp256";
-        }
-
-        public KeyExchange create() {
-            return new ECDHP256();
-        }
-
-    }
-
-    @Override
-    protected AbstractDH getDH() throws Exception {
-        ECDH ecdh = new ECDH();
-        ecdh.setCurveParameters(ECCurves.EllipticCurves.nistp256);
-        return ecdh;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/client/kex/ECDHP384.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/kex/ECDHP384.java b/sshd-core/src/main/java/org/apache/sshd/client/kex/ECDHP384.java
deleted file mode 100644
index cb05e47..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/client/kex/ECDHP384.java
+++ /dev/null
@@ -1,53 +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.client.kex;
-
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.cipher.ECCurves;
-import org.apache.sshd.common.kex.AbstractDH;
-import org.apache.sshd.common.kex.ECDH;
-
-/**
- * Elliptic Curve Diffie-Hellman with NIST P-256 curve.
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class ECDHP384 extends AbstractDHGClient {
-
-    public static class Factory implements NamedFactory<KeyExchange> {
-
-        public String getName() {
-            return "ecdh-sha2-nistp384";
-        }
-
-        public KeyExchange create() {
-            return new ECDHP384();
-        }
-
-    }
-
-    @Override
-    protected AbstractDH getDH() throws Exception {
-        ECDH ecdh = new ECDH();
-        ecdh.setCurveParameters(ECCurves.EllipticCurves.nistp384);
-        return ecdh;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/client/kex/ECDHP521.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/kex/ECDHP521.java b/sshd-core/src/main/java/org/apache/sshd/client/kex/ECDHP521.java
deleted file mode 100644
index 9e36951..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/client/kex/ECDHP521.java
+++ /dev/null
@@ -1,53 +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.client.kex;
-
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.cipher.ECCurves;
-import org.apache.sshd.common.kex.AbstractDH;
-import org.apache.sshd.common.kex.ECDH;
-
-/**
- * Elliptic Curve Diffie-Hellman with NIST P-256 curve.
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class ECDHP521 extends AbstractDHGClient {
-
-    public static class Factory implements NamedFactory<KeyExchange> {
-
-        public String getName() {
-            return "ecdh-sha2-nistp521";
-        }
-
-        public KeyExchange create() {
-            return new ECDHP521();
-        }
-
-    }
-
-    @Override
-    protected AbstractDH getDH() throws Exception {
-        ECDH ecdh = new ECDH();
-        ecdh.setCurveParameters(ECCurves.EllipticCurves.nistp521);
-        return ecdh;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/common/FactoryManagerUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/FactoryManagerUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/FactoryManagerUtils.java
index 6dde364..ece21bc 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/FactoryManagerUtils.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/FactoryManagerUtils.java
@@ -106,15 +106,15 @@ public class FactoryManagerUtils {
     }
 
     public static final String updateProperty(Session session, String name, long value) {
-        return updateProperty(session, name, String.valueOf(value));
+        return updateProperty(session, name, Long.toString(value));
     }
 
     public static final String updateProperty(FactoryManager manager, String name, long value) {
-        return updateProperty(manager, name, String.valueOf(value));
+        return updateProperty(manager, name, Long.toString(value));
     }
 
     public static final String updateProperty(Map<String, String> props, String name, long value) {
-        return updateProperty(props, name, String.valueOf(value));
+        return updateProperty(props, name, Long.toString(value));
     }
 
     public static final int getIntProperty(Session session, String name, int defaultValue) {
@@ -152,15 +152,15 @@ public class FactoryManagerUtils {
     }
 
     public static final String updateProperty(Session session, String name, int value) {
-        return updateProperty(session, name, String.valueOf(value));
+        return updateProperty(session, name, Integer.toString(value));
     }
 
     public static final String updateProperty(FactoryManager manager, String name, int value) {
-        return updateProperty(manager, name, String.valueOf(value));
+        return updateProperty(manager, name, Integer.toString(value));
     }
 
     public static final String updateProperty(Map<String, String> props, String name, int value) {
-        return updateProperty(props, name, String.valueOf(value));
+        return updateProperty(props, name, Integer.toString(value));
     }
 
     public static final boolean getBooleanProperty(Session session, String name, boolean defaultValue) {
@@ -198,15 +198,15 @@ public class FactoryManagerUtils {
     }
 
     public static final String updateProperty(Session session, String name, boolean value) {
-        return updateProperty(session, name, String.valueOf(value));
+        return updateProperty(session, name, Boolean.toString(value));
     }
 
     public static final String updateProperty(FactoryManager manager, String name, boolean value) {
-        return updateProperty(manager, name, String.valueOf(value));
+        return updateProperty(manager, name, Boolean.toString(value));
     }
 
     public static final String updateProperty(Map<String, String> props, String name, boolean value) {
-        return updateProperty(props, name, String.valueOf(value));
+        return updateProperty(props, name, Boolean.toString(value));
     }
 
     public static final String getString(Session session, String name) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/common/NamedFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/NamedFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/NamedFactory.java
index ba8d60f..6850b8d 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/NamedFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/NamedFactory.java
@@ -33,14 +33,7 @@ import org.apache.sshd.common.util.GenericUtils;
  *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public interface NamedFactory<T> extends Factory<T> {
-
-    /**
-     * Name of this factory
-     * @return the name of this factory
-     */
-    String getName();
-
+public interface NamedFactory<T> extends Factory<T>, NamedResource {
     /**
      * Utility class to help using NamedFactories
      */
@@ -72,15 +65,13 @@ public interface NamedFactory<T> extends Factory<T> {
          * @param <T> type of object to create
          * @return a newly created object or <code>null</code> if the factory is not in the list
          */
-        public static <T> T create(List<NamedFactory<T>> factories, String name) {
-            if (factories != null) {
-                for (NamedFactory<T> f : factories) {
-                    if (f.getName().equals(name)) {
-                        return f.create();
-                    }
-                }
+        public static <T> T create(Collection<? extends NamedFactory<T>> factories, String name) {
+            NamedFactory<? extends T>   f=get(factories, name);
+            if (f != null) {
+                return f.create();
+            } else {
+                return null;
             }
-            return null;
         }
 
         /**
@@ -90,7 +81,7 @@ public interface NamedFactory<T> extends Factory<T> {
          * @param <T> type of object to create
          * @return a comma separated list of factory names
          */
-        public static <T> String getNames(List<NamedFactory<T>> factories) {
+        public static <T> String getNames(Collection<? extends NamedFactory<T>> factories) {
             StringBuilder sb = new StringBuilder();
             for (NamedFactory<T> f : factories) {
                 if (sb.length() > 0) {
@@ -109,14 +100,12 @@ public interface NamedFactory<T> extends Factory<T> {
          * @param <T> type of object to create
          * @return the factory removed from the list or <code>null</code> if not in the list
          */
-        public static <T> NamedFactory<T> remove(List<NamedFactory<T>> factories, String name) {
-            for (NamedFactory<T> f : factories) {
-                if (f.getName().equals(name)) {
-                    factories.remove(f);
-                    return f;
-                }
+        public static <T> NamedFactory<T> remove(Collection<? extends NamedFactory<T>> factories, String name) {
+            NamedFactory<T> f=get(factories, name);
+            if (f != null) {
+                factories.remove(f);
             }
-            return null;
+            return f;
         }
 
         /**
@@ -127,7 +116,11 @@ public interface NamedFactory<T> extends Factory<T> {
          * @param <T> type of object create by the factories
          * @return a factory or <code>null</code> if not found in the list
          */
-        public static <T> NamedFactory<T> get(List<NamedFactory<T>> factories, String name) {
+        public static <T> NamedFactory<T> get(Collection<? extends NamedFactory<T>> factories, String name) {
+            if (GenericUtils.isEmpty(factories)) {
+                return null;
+            }
+
             for (NamedFactory<T> f : factories) {
                 if (f.getName().equals(name)) {
                     return f;
@@ -135,7 +128,6 @@ public interface NamedFactory<T> extends Factory<T> {
             }
             return null;
         }
-
     }
 
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/common/NamedResource.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/NamedResource.java b/sshd-core/src/main/java/org/apache/sshd/common/NamedResource.java
new file mode 100644
index 0000000..85f78a8
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/NamedResource.java
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public interface NamedResource {
+    /**
+     * @return The resource name
+     */
+    String getName();
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/common/ServiceFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/ServiceFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/ServiceFactory.java
index b70b963..d74989c 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/ServiceFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/ServiceFactory.java
@@ -19,16 +19,11 @@
 package org.apache.sshd.common;
 
 import java.io.IOException;
-import java.util.List;
+import java.util.Collection;
 
-public interface ServiceFactory {
-
-    /**
-     * Name of this factory
-     * @return
-     */
-    String getName();
+import org.apache.sshd.common.util.GenericUtils;
 
+public interface ServiceFactory extends NamedResource {
     Service create(Session session) throws IOException;
 
     /**
@@ -44,14 +39,17 @@ public interface ServiceFactory {
          * @param name the factory name to use
          * @return a newly created object or <code>null</code> if the factory is not in the list
          */
-        public static Service create(List<ServiceFactory> factories, String name, Session session) throws IOException {
-            if (factories != null) {
-                for (ServiceFactory f : factories) {
-                    if (f.getName().equals(name)) {
-                        return f.create(session);
-                    }
+        public static Service create(Collection<? extends ServiceFactory> factories, String name, Session session) throws IOException {
+            if (GenericUtils.isEmpty(factories)) {
+                return null;
+            }
+
+            for (ServiceFactory f : factories) {
+                if (f.getName().equals(name)) {
+                    return f.create(session);
                 }
             }
+
             return null;
         }
     }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/common/kex/AbstractDH.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/kex/AbstractDH.java b/sshd-core/src/main/java/org/apache/sshd/common/kex/AbstractDH.java
index 05a0680..6e66a20 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/kex/AbstractDH.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/kex/AbstractDH.java
@@ -27,18 +27,12 @@ import org.apache.sshd.common.Digest;
  * 
  */
 public abstract class AbstractDH {
+
     protected BigInteger K; // shared secret key
     private byte[] K_array;
 
     protected AbstractDH() {
-    }
-
-    public static AbstractDH getInstance(String algo) throws Exception {
-        if (algo.startsWith("ecdh-sha2-")) {
-            return new ECDH();
-        } else {
-            return new DH();
-        }
+        super();
     }
 
     public abstract void setF(byte[] e);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/common/kex/BuiltinDHFactories.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/kex/BuiltinDHFactories.java b/sshd-core/src/main/java/org/apache/sshd/common/kex/BuiltinDHFactories.java
new file mode 100644
index 0000000..b2c63cd
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/kex/BuiltinDHFactories.java
@@ -0,0 +1,184 @@
+/*
+ * 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.kex;
+
+import java.math.BigInteger;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+
+import org.apache.sshd.common.cipher.ECCurves;
+import org.apache.sshd.common.digest.SHA1;
+import org.apache.sshd.common.digest.SHA256;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.SecurityUtils;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public enum BuiltinDHFactories implements DHFactory {
+
+    dhg1(Constants.DIFFIE_HELLMAN_GROUP1_SHA1) {
+        @Override
+        public DHG create(Object... params) throws Exception {
+            if (params != null && params.length > 0) {
+                throw new IllegalArgumentException("No accepted parameters for " + getName());
+            }
+            return new DHG(new SHA1.Factory(), new BigInteger(DHGroupData.getP1()), new BigInteger(DHGroupData.getG()));
+        }
+    },
+    dhg14(Constants.DIFFIE_HELLMAN_GROUP14_SHA1) {
+        @Override
+        public DHG create(Object... params) throws Exception {
+            if (params != null && params.length > 0) {
+                throw new IllegalArgumentException("No accepted parameters for " + getName());
+            }
+            return new DHG(new SHA1.Factory(), new BigInteger(DHGroupData.getP14()), new BigInteger(DHGroupData.getG()));
+        }
+        @Override
+        public boolean isSupported() {
+            return SecurityUtils.isBouncyCastleRegistered();
+        }
+    },
+    dhgex(Constants.DIFFIE_HELLMAN_GROUP_EXCHANGE_SHA1) {
+        @Override
+        public DHG create(Object... params) throws Exception {
+            if (params == null || params.length != 2
+                    || !(params[0] instanceof BigInteger) || !(params[1] instanceof BigInteger)) {
+                throw new IllegalArgumentException("Bad parameters for " + getName());
+            }
+            return new DHG(new SHA1.Factory(), (BigInteger) params[0], (BigInteger) params[1]);
+        }
+        @Override
+        public boolean isGroupExchange() {
+            return true;
+        }
+    },
+    dhgex256(Constants.DIFFIE_HELLMAN_GROUP_EXCHANGE_SHA256) {
+        @Override
+        public AbstractDH create(Object... params) throws Exception {
+            if (params == null || params.length != 2
+                    || !(params[0] instanceof BigInteger) || !(params[1] instanceof BigInteger)) {
+                throw new IllegalArgumentException("Bad parameters for " + getName());
+            }
+            return new DHG(new SHA256.Factory(), (BigInteger) params[0], (BigInteger) params[1]);
+        }
+        @Override
+        public boolean isSupported() {  // avoid "Prime size must be multiple of 64, and can only range from 512 to 2048 (inclusive)"
+            return SecurityUtils.isBouncyCastleRegistered();
+        }
+        @Override
+        public boolean isGroupExchange() {
+            return true;
+        }
+    },
+    ecdhp256(Constants.ECDH_SHA2_NISTP256) {
+        @Override
+        public ECDH create(Object... params) throws Exception {
+            if (params != null && params.length > 0) {
+                throw new IllegalArgumentException("No accepted parameters for " + getName());
+            }
+            return new ECDH(ECCurves.EllipticCurves.nistp256);
+        }
+        @Override
+        public boolean isSupported() {
+            return SecurityUtils.hasEcc();
+        }
+    },
+    ecdhp384(Constants.ECDH_SHA2_NISTP384) {
+        @Override
+        public ECDH create(Object... params) throws Exception {
+            if (params != null && params.length > 0) {
+                throw new IllegalArgumentException("No accepted parameters for " + getName());
+            }
+            return new ECDH(ECCurves.EllipticCurves.nistp384);
+        }
+        @Override
+        public boolean isSupported() {
+            return SecurityUtils.hasEcc();
+        }
+    },
+    ecdhp521(Constants.ECDH_SHA2_NISTP521) {
+        @Override
+        public ECDH create(Object... params) throws Exception {
+            if (params != null && params.length > 0) {
+                throw new IllegalArgumentException("No accepted parameters for " + getName());
+            }
+            return new ECDH(ECCurves.EllipticCurves.nistp521);
+        }
+        @Override
+        public boolean isSupported() {
+            return SecurityUtils.hasEcc();
+        }
+    };
+
+    private final String factoryName;
+
+    @Override
+    public final String getName() {
+        return factoryName;
+    }
+
+    public boolean isSupported() {
+        return true;
+    }
+
+    BuiltinDHFactories(String name) {
+        factoryName = name;
+    }
+
+    public static final Set<BuiltinDHFactories> VALUES =
+            Collections.unmodifiableSet(EnumSet.allOf(BuiltinDHFactories.class));
+
+    /**
+     * @param name The factory name - ignored if {@code null}/empty
+     * @return The matching {@link BuiltinDHFactories} (case <U>insensitive</U>)
+     * or {@code null} if no match found
+     */
+    public static final BuiltinDHFactories fromFactoryName(String name) {
+        if (GenericUtils.isEmpty(name)) {
+            return null;
+        }
+
+        for (BuiltinDHFactories f : VALUES) {
+            if (name.equalsIgnoreCase(f.getName())) {
+                return f;
+            }
+        }
+
+        return null;
+    }
+
+    @Override
+    public boolean isGroupExchange() {
+        return false;
+    }
+
+    public static class Constants {
+        public static final String DIFFIE_HELLMAN_GROUP1_SHA1 = "diffie-hellman-group1-sha1";
+        public static final String DIFFIE_HELLMAN_GROUP14_SHA1 = "diffie-hellman-group14-sha1";
+        public static final String DIFFIE_HELLMAN_GROUP_EXCHANGE_SHA1 = "diffie-hellman-group-exchange-sha1";
+        public static final String DIFFIE_HELLMAN_GROUP_EXCHANGE_SHA256 = "diffie-hellman-group-exchange-sha256";
+        public static final String ECDH_SHA2_NISTP256 = "ecdh-sha2-nistp256";
+        public static final String ECDH_SHA2_NISTP384 = "ecdh-sha2-nistp384";
+        public static final String ECDH_SHA2_NISTP521 = "ecdh-sha2-nistp521";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/common/kex/DH.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/kex/DH.java b/sshd-core/src/main/java/org/apache/sshd/common/kex/DH.java
deleted file mode 100644
index 7b2bc89..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/kex/DH.java
+++ /dev/null
@@ -1,118 +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.kex;
-
-import java.math.BigInteger;
-import java.security.KeyFactory;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.PublicKey;
-
-import javax.crypto.KeyAgreement;
-import javax.crypto.spec.DHParameterSpec;
-import javax.crypto.spec.DHPublicKeySpec;
-
-import org.apache.sshd.common.Digest;
-import org.apache.sshd.common.Factory;
-import org.apache.sshd.common.digest.SHA1;
-import org.apache.sshd.common.util.SecurityUtils;
-
-/**
- * Diffie-Hellman key generator.
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class DH extends AbstractDH {
-
-    private BigInteger p;
-    private BigInteger g;
-    private BigInteger e;  // my public key
-    private byte[] e_array;
-    private BigInteger f;  // your public key
-    private KeyPairGenerator myKpairGen;
-    private KeyAgreement myKeyAgree;
-    private Factory<Digest> factory;
-
-    public DH() throws Exception {
-        this(new SHA1.Factory());
-    }
-
-    public DH(Factory<Digest> factory) throws Exception {
-        myKpairGen = SecurityUtils.getKeyPairGenerator("DH");
-        myKeyAgree = SecurityUtils.getKeyAgreement("DH");
-        this.factory = factory;
-    }
-
-    public byte[] getE() throws Exception {
-        if (e == null) {
-            DHParameterSpec dhSkipParamSpec = new DHParameterSpec(p, g);
-            myKpairGen.initialize(dhSkipParamSpec);
-            KeyPair myKpair = myKpairGen.generateKeyPair();
-            myKeyAgree.init(myKpair.getPrivate());
-            e = ((javax.crypto.interfaces.DHPublicKey) (myKpair.getPublic())).getY();
-            e_array = e.toByteArray();
-        }
-        return e_array;
-    }
-
-    protected byte[] calculateK() throws Exception {
-        KeyFactory myKeyFac = SecurityUtils.getKeyFactory("DH");
-        DHPublicKeySpec keySpec = new DHPublicKeySpec(f, p, g);
-        PublicKey yourPubKey = myKeyFac.generatePublic(keySpec);
-        myKeyAgree.doPhase(yourPubKey, true);
-        return stripLeadingZeroes(myKeyAgree.generateSecret());
-    }
-
-    public void setP(byte[] p) {
-        setP(new BigInteger(p));
-    }
-
-    public void setG(byte[] g) {
-        setG(new BigInteger(g));
-    }
-
-    public void setF(byte[] f) {
-        setF(new BigInteger(f));
-    }
-
-    public BigInteger getP() {
-        return p;
-    }
-
-    public void setP(BigInteger p) {
-        this.p = p;
-    }
-
-    public BigInteger getG() {
-        return g;
-    }
-
-    public void setG(BigInteger g) {
-        this.g = g;
-    }
-
-    public void setF(BigInteger f) {
-        this.f = f;
-    }
-
-    @Override
-    public Digest getHash() throws Exception {
-        return factory.create();
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/common/kex/DHFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/kex/DHFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/kex/DHFactory.java
new file mode 100644
index 0000000..ad80eca
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/kex/DHFactory.java
@@ -0,0 +1,34 @@
+/*
+ * 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.kex;
+
+import java.math.BigInteger;
+
+import org.apache.sshd.common.NamedResource;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public interface DHFactory extends NamedResource {
+
+    boolean isGroupExchange();
+
+    AbstractDH create(Object... params) throws Exception;
+
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/common/kex/DHG.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/kex/DHG.java b/sshd-core/src/main/java/org/apache/sshd/common/kex/DHG.java
new file mode 100644
index 0000000..2658eb1
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/kex/DHG.java
@@ -0,0 +1,119 @@
+/*
+ * 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.kex;
+
+import java.math.BigInteger;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PublicKey;
+
+import javax.crypto.KeyAgreement;
+import javax.crypto.spec.DHParameterSpec;
+import javax.crypto.spec.DHPublicKeySpec;
+
+import org.apache.sshd.common.Digest;
+import org.apache.sshd.common.Factory;
+import org.apache.sshd.common.util.SecurityUtils;
+
+/**
+ * Diffie-Hellman key generator.
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class DHG extends AbstractDH {
+
+    private BigInteger p;
+    private BigInteger g;
+    private BigInteger e;  // my public key
+    private byte[] e_array;
+    private BigInteger f;  // your public key
+    private KeyPairGenerator myKpairGen;
+    private KeyAgreement myKeyAgree;
+    private Factory<Digest> factory;
+
+    public DHG(Factory<Digest> digestFactory) throws Exception {
+        this(digestFactory, null, null);
+    }
+
+    public DHG(Factory<Digest> digestFactory, BigInteger pValue, BigInteger gValue) throws Exception {
+        myKpairGen = SecurityUtils.getKeyPairGenerator("DH");
+        myKeyAgree = SecurityUtils.getKeyAgreement("DH");
+        factory = digestFactory;
+        p = pValue;
+        g = gValue;
+    }
+
+    public byte[] getE() throws Exception {
+        if (e == null) {
+            DHParameterSpec dhSkipParamSpec = new DHParameterSpec(p, g);
+            myKpairGen.initialize(dhSkipParamSpec);
+            KeyPair myKpair = myKpairGen.generateKeyPair();
+            myKeyAgree.init(myKpair.getPrivate());
+            e = ((javax.crypto.interfaces.DHPublicKey) (myKpair.getPublic())).getY();
+            e_array = e.toByteArray();
+        }
+        return e_array;
+    }
+
+    protected byte[] calculateK() throws Exception {
+        KeyFactory myKeyFac = SecurityUtils.getKeyFactory("DH");
+        DHPublicKeySpec keySpec = new DHPublicKeySpec(f, p, g);
+        PublicKey yourPubKey = myKeyFac.generatePublic(keySpec);
+        myKeyAgree.doPhase(yourPubKey, true);
+        return stripLeadingZeroes(myKeyAgree.generateSecret());
+    }
+
+    public void setP(byte[] p) {
+        setP(new BigInteger(p));
+    }
+
+    public void setG(byte[] g) {
+        setG(new BigInteger(g));
+    }
+
+    public void setF(byte[] f) {
+        setF(new BigInteger(f));
+    }
+
+    public BigInteger getP() {
+        return p;
+    }
+
+    public void setP(BigInteger p) {
+        this.p = p;
+    }
+
+    public BigInteger getG() {
+        return g;
+    }
+
+    public void setG(BigInteger g) {
+        this.g = g;
+    }
+
+    public void setF(BigInteger f) {
+        this.f = f;
+    }
+
+    @Override
+    public Digest getHash() throws Exception {
+        return factory.create();
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/common/kex/ECDH.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/kex/ECDH.java b/sshd-core/src/main/java/org/apache/sshd/common/kex/ECDH.java
index bd63570..fbb7090 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/kex/ECDH.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/kex/ECDH.java
@@ -48,8 +48,13 @@ public class ECDH extends AbstractDH {
     private KeyAgreement myKeyAgree;
 
     public ECDH() throws Exception {
+        this(null);
+    }
+
+    public ECDH(ECParameterSpec paramSpec) throws Exception {
         myKpairGen = SecurityUtils.getKeyPairGenerator("EC");
         myKeyAgree = SecurityUtils.getKeyAgreement("ECDH");
+        params = paramSpec;
     }
 
     @Override
@@ -73,8 +78,8 @@ public class ECDH extends AbstractDH {
         return stripLeadingZeroes(myKeyAgree.generateSecret());
     }
 
-    public void setCurveParameters(ECParameterSpec params) {
-        this.params = params;
+    public void setCurveParameters(ECParameterSpec paramSpec) {
+        params = paramSpec;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/common/kex/dh/AbstractDHKeyExchange.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/kex/dh/AbstractDHKeyExchange.java b/sshd-core/src/main/java/org/apache/sshd/common/kex/dh/AbstractDHKeyExchange.java
new file mode 100644
index 0000000..17d3a00
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/kex/dh/AbstractDHKeyExchange.java
@@ -0,0 +1,67 @@
+/*
+ * 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.kex.dh;
+
+import org.apache.sshd.common.Digest;
+import org.apache.sshd.common.KeyExchange;
+import org.apache.sshd.common.session.AbstractSession;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public abstract class AbstractDHKeyExchange implements KeyExchange {
+
+    protected final Logger log = LoggerFactory.getLogger(getClass());
+    protected byte[] V_S;
+    protected byte[] V_C;
+    protected byte[] I_S;
+    protected byte[] I_C;
+    protected Digest hash;
+    protected byte[] e;
+    protected byte[] f;
+    protected byte[] K;
+    protected byte[] H;
+
+    protected AbstractDHKeyExchange() {
+        super();
+    }
+
+    public void init(AbstractSession s, byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception {
+        this.V_S = V_S;
+        this.V_C = V_C;
+        this.I_S = I_S;
+        this.I_C = I_C;
+    }
+
+    public Digest getHash() {
+        return hash;
+    }
+
+    public byte[] getH() {
+        return H;
+    }
+
+    public byte[] getK() {
+        return K;
+    }
+
+}


[5/6] mina-sshd git commit: [SSHD-430] Refactor BuiltinCiphers into a Factory

Posted by gn...@apache.org.
[SSHD-430] Refactor BuiltinCiphers into a Factory<Cipher>


Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/31d4dc5a
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/31d4dc5a
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/31d4dc5a

Branch: refs/heads/master
Commit: 31d4dc5ac5a41552ee72d688ba41124d4a020be4
Parents: 7355193
Author: Guillaume Nodet <gn...@apache.org>
Authored: Thu Mar 26 16:46:37 2015 +0100
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Mon Mar 30 10:52:43 2015 +0200

----------------------------------------------------------------------
 .../main/java/org/apache/sshd/SshBuilder.java   |   2 +-
 .../apache/sshd/common/cipher/AES128CBC.java    |  54 ---------
 .../apache/sshd/common/cipher/AES128CTR.java    |  54 ---------
 .../apache/sshd/common/cipher/AES192CBC.java    |  54 ---------
 .../apache/sshd/common/cipher/AES192CTR.java    |  54 ---------
 .../apache/sshd/common/cipher/AES256CBC.java    |  54 ---------
 .../apache/sshd/common/cipher/AES256CTR.java    |  54 ---------
 .../apache/sshd/common/cipher/ARCFOUR128.java   |  54 ---------
 .../apache/sshd/common/cipher/ARCFOUR256.java   |  54 ---------
 .../apache/sshd/common/cipher/BlowfishCBC.java  |  54 ---------
 .../sshd/common/cipher/BuiltinCiphers.java      | 119 ++++++++-----------
 .../apache/sshd/common/cipher/CipherNone.java   |  19 ---
 .../apache/sshd/common/cipher/TripleDESCBC.java |  54 ---------
 .../test/java/org/apache/sshd/CipherTest.java   |  22 ++--
 .../test/java/org/apache/sshd/ClientTest.java   |   5 +-
 .../src/test/java/org/apache/sshd/LoadTest.java |   3 +-
 .../src/test/java/org/apache/sshd/MacTest.java  |  13 +-
 .../sshd/common/cipher/AES192CTRTest.java       |   2 +-
 .../sshd/common/cipher/AES256CBCTest.java       |   2 +-
 .../sshd/common/cipher/ARCFOUR128Test.java      |   2 +-
 .../sshd/common/cipher/ARCFOUR256Test.java      |   2 +-
 .../sshd/common/cipher/BuiltinCiphersTest.java  |  34 +++---
 22 files changed, 87 insertions(+), 678 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/31d4dc5a/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java b/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java
index e441457..df9fad8 100644
--- a/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java
+++ b/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java
@@ -297,7 +297,7 @@ public class SshBuilder {
             List<NamedFactory<Cipher>> avail = new ArrayList<NamedFactory<Cipher>>(DEFAULT_CIPHERS_PREFERENCE.size());
             for (BuiltinCiphers c : DEFAULT_CIPHERS_PREFERENCE) {
                 if (ignoreUnsupported || c.isSupported()) {
-                    avail.add(c.create());
+                    avail.add(c);
                 }
             }
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/31d4dc5a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES128CBC.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES128CBC.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES128CBC.java
deleted file mode 100644
index 39a1a08..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES128CBC.java
+++ /dev/null
@@ -1,54 +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.cipher;
-
-import org.apache.sshd.common.Cipher;
-import org.apache.sshd.common.NamedFactory;
-
-/**
- * AES128CBC cipher
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class AES128CBC extends BaseCipher {
-
-    /**
-     * Named factory for AES128CBC Cipher
-     */
-    public static class Factory implements NamedFactory<Cipher> {
-        public static final String NAME = "aes128-cbc";
-
-        public Factory() {
-            super();
-        }
-
-        public String getName() {
-            return NAME;
-        }
-
-        public Cipher create() {
-            return new AES128CBC();
-        }
-    }
-
-    public AES128CBC() {
-        super(16, 16, "AES", "AES/CBC/NoPadding");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/31d4dc5a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES128CTR.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES128CTR.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES128CTR.java
deleted file mode 100644
index 2cbfb21..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES128CTR.java
+++ /dev/null
@@ -1,54 +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.cipher;
-
-import org.apache.sshd.common.Cipher;
-import org.apache.sshd.common.NamedFactory;
-
-/**
- * AES128CTR cipher
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class AES128CTR extends BaseCipher {
-
-    /**
-     * Named factory for AES128CTR Cipher
-     */
-    public static class Factory implements NamedFactory<Cipher> {
-        public static final String NAME = "aes128-ctr";
-
-        public Factory() {
-            super();
-        }
-
-        public String getName() {
-            return NAME;
-        }
-
-        public Cipher create() {
-            return new AES128CTR();
-        }
-    }
-
-    public AES128CTR() {
-        super(16, 16, "AES", "AES/CTR/NoPadding");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/31d4dc5a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES192CBC.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES192CBC.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES192CBC.java
deleted file mode 100644
index 3d26f76..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES192CBC.java
+++ /dev/null
@@ -1,54 +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.cipher;
-
-import org.apache.sshd.common.Cipher;
-import org.apache.sshd.common.NamedFactory;
-
-/**
- * AES192CBC Cipher
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class AES192CBC extends BaseCipher {
-
-    /**
-     * Named factory for AES192CBC Cipher
-     */
-    public static class Factory implements NamedFactory<Cipher> {
-        public static final String NAME = "aes192-cbc";
-
-        public Factory() {
-            super();
-        }
-
-        public String getName() {
-            return NAME;
-        }
-
-        public Cipher create() {
-            return new AES192CBC();
-        }
-    }
-
-    public AES192CBC() {
-        super(16, 24, "AES", "AES/CBC/NoPadding");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/31d4dc5a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES192CTR.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES192CTR.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES192CTR.java
deleted file mode 100644
index cf13b9f..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES192CTR.java
+++ /dev/null
@@ -1,54 +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.cipher;
-
-import org.apache.sshd.common.Cipher;
-import org.apache.sshd.common.NamedFactory;
-
-/**
- * AES192CBC Cipher
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class AES192CTR extends BaseCipher {
-
-    /**
-     * Named factory for AES192CBC Cipher
-     */
-    public static class Factory implements NamedFactory<Cipher> {
-        public static final String NAME = "aes192-ctr";
-
-        public Factory() {
-            super();
-        }
-
-        public String getName() {
-            return NAME;
-        }
-
-        public Cipher create() {
-            return new AES192CTR();
-        }
-    }
-
-    public AES192CTR() {
-        super(16, 24, "AES", "AES/CTR/NoPadding");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/31d4dc5a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES256CBC.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES256CBC.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES256CBC.java
deleted file mode 100644
index 38122d8..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES256CBC.java
+++ /dev/null
@@ -1,54 +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.cipher;
-
-import org.apache.sshd.common.Cipher;
-import org.apache.sshd.common.NamedFactory;
-
-/**
- * AES256CBC Cipher
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class AES256CBC extends BaseCipher {
-
-    /**
-     * Named factory for AES256CBC Cipher
-     */
-    public static class Factory implements NamedFactory<Cipher> {
-        public static final String NAME = "aes256-cbc";
-
-        public Factory() {
-            super();
-        }
-
-        public String getName() {
-            return NAME;
-        }
-
-        public Cipher create() {
-            return new AES256CBC();
-        }
-    }
-
-    public AES256CBC() {
-        super(16, 32, "AES", "AES/CBC/NoPadding");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/31d4dc5a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES256CTR.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES256CTR.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES256CTR.java
deleted file mode 100644
index 718017f..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES256CTR.java
+++ /dev/null
@@ -1,54 +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.cipher;
-
-import org.apache.sshd.common.Cipher;
-import org.apache.sshd.common.NamedFactory;
-
-/**
- * AES256CTR Cipher
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class AES256CTR extends BaseCipher {
-
-    /**
-     * Named factory for AES256CTR Cipher
-     */
-    public static class Factory implements NamedFactory<Cipher> {
-        public static final String NAME = "aes256-ctr";
-
-        public Factory() {
-            super();
-        }
-
-        public String getName() {
-            return NAME;
-        }
-
-        public Cipher create() {
-            return new AES256CTR();
-        }
-    }
-
-    public AES256CTR() {
-        super(16, 32, "AES", "AES/CTR/NoPadding");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/31d4dc5a/sshd-core/src/main/java/org/apache/sshd/common/cipher/ARCFOUR128.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/ARCFOUR128.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/ARCFOUR128.java
deleted file mode 100644
index 33d6a6e..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/ARCFOUR128.java
+++ /dev/null
@@ -1,54 +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.cipher;
-
-import org.apache.sshd.common.Cipher;
-import org.apache.sshd.common.NamedFactory;
-
-/**
- * ARCFOUR128 cipher
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class ARCFOUR128 extends BaseRC4Cipher {
-
-    /**
-     * Named factory for ARCFOUR128 Cipher
-     */
-    public static class Factory implements NamedFactory<Cipher> {
-        public static final String NAME = "arcfour128";
-
-        public Factory() {
-            super();
-        }
-
-        public String getName() {
-            return NAME;
-        }
-
-        public Cipher create() {
-            return new ARCFOUR128();
-        }
-    }
-
-    public ARCFOUR128() {
-        super(8, 16);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/31d4dc5a/sshd-core/src/main/java/org/apache/sshd/common/cipher/ARCFOUR256.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/ARCFOUR256.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/ARCFOUR256.java
deleted file mode 100644
index 500c1b7..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/ARCFOUR256.java
+++ /dev/null
@@ -1,54 +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.cipher;
-
-import org.apache.sshd.common.Cipher;
-import org.apache.sshd.common.NamedFactory;
-
-/**
- * ARCFOUR256 cipher
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class ARCFOUR256 extends BaseRC4Cipher {
-
-    /**
-     * Named factory for AES128CTR Cipher
-     */
-    public static class Factory implements NamedFactory<Cipher> {
-        public static final String NAME = "arcfour256";
-
-        public Factory() {
-            super();
-        }
-
-        public String getName() {
-            return NAME;
-        }
-
-        public Cipher create() {
-            return new ARCFOUR256();
-        }
-    }
-
-    public ARCFOUR256() {
-        super(8, 32);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/31d4dc5a/sshd-core/src/main/java/org/apache/sshd/common/cipher/BlowfishCBC.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/BlowfishCBC.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/BlowfishCBC.java
deleted file mode 100644
index b2c6135..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/BlowfishCBC.java
+++ /dev/null
@@ -1,54 +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.cipher;
-
-import org.apache.sshd.common.Cipher;
-import org.apache.sshd.common.NamedFactory;
-
-/**
- * BlowfishCBC Cipher
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class BlowfishCBC extends BaseCipher {
-
-    /**
-     * Named factory for BlowfishCBC Cipher
-     */
-    public static class Factory implements NamedFactory<Cipher> {
-        public static final String NAME = "blowfish-cbc";
-
-        public Factory() {
-            super();
-        }
-
-        public String getName() {
-            return NAME;
-        }
-
-        public Cipher create() {
-            return new BlowfishCBC();
-        }
-    }
-
-    public BlowfishCBC() {
-        super(8, 16, "Blowfish", "Blowfish/CBC/NoPadding");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/31d4dc5a/sshd-core/src/main/java/org/apache/sshd/common/cipher/BuiltinCiphers.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/BuiltinCiphers.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/BuiltinCiphers.java
index 74c45f1..d6c0526 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/BuiltinCiphers.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/cipher/BuiltinCiphers.java
@@ -33,89 +33,83 @@ import org.apache.sshd.common.util.GenericUtils;
  *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public enum BuiltinCiphers implements NamedFactory<NamedFactory<Cipher>> {
-    none(CipherNone.Factory.NAME, CipherNone.class) {
+public enum BuiltinCiphers implements NamedFactory<Cipher> {
+    none(Constants.NONE) {
         @Override
-        public NamedFactory<Cipher> create() {
-            return new CipherNone.Factory();
+        public Cipher create() {
+            return new CipherNone();
         }
     },
-    aes128cbc(AES128CBC.Factory.NAME, AES128CBC.class) {
+    aes128cbc(Constants.AES128_CBC) {
         @Override
-        public NamedFactory<Cipher> create() {
-            return new AES128CBC.Factory();
+        public Cipher create() {
+            return new BaseCipher(16, 16, "AES", "AES/CBC/NoPadding");
         }
     },
-    aes128ctr(AES128CTR.Factory.NAME, AES128CTR.class) {
+    aes128ctr(Constants.AES128_CTR) {
         @Override
-        public NamedFactory<Cipher> create() {
-            return new AES128CTR.Factory();
+        public Cipher create() {
+            return new BaseCipher(16, 16, "AES", "AES/CTR/NoPadding");
         }
     },
-    aes192cbc(AES192CBC.Factory.NAME, AES192CBC.class) {
+    aes192cbc(Constants.AES192_CBC) {
         @Override
-        public NamedFactory<Cipher> create() {
-            return new AES192CBC.Factory();
+        public Cipher create() {
+            return new BaseCipher(16, 24, "AES", "AES/CBC/NoPadding");
         }
     },
-    aes192ctr(AES192CTR.Factory.NAME, AES192CTR.class) {
+    aes192ctr(Constants.AES192_CTR) {
         @Override
-        public NamedFactory<Cipher> create() {
-            return new AES192CTR.Factory();
+        public Cipher create() {
+            return new BaseCipher(16, 24, "AES", "AES/CTR/NoPadding");
         }
     },
-    aes256cbc(AES256CBC.Factory.NAME, AES256CBC.class) {
+    aes256cbc(Constants.AES256_CBC) {
         @Override
-        public NamedFactory<Cipher> create() {
-            return new AES256CBC.Factory();
+        public Cipher create() {
+            return new BaseCipher(16, 32, "AES", "AES/CBC/NoPadding");
         }
     },
-    aes256ctr(AES256CTR.Factory.NAME, AES256CTR.class) {
+    aes256ctr(Constants.AES256_CTR) {
         @Override
-        public NamedFactory<Cipher> create() {
-            return new AES256CTR.Factory();
+        public Cipher create() {
+            return new BaseCipher(16, 32, "AES", "AES/CTR/NoPadding");
         }
     },
-    arcfour128(ARCFOUR128.Factory.NAME, ARCFOUR128.class) {
+    arcfour128(Constants.ARCFOUR128) {
         @Override
-        public NamedFactory<Cipher> create() {
-            return new ARCFOUR128.Factory();
+        public Cipher create() {
+            return new BaseRC4Cipher(8, 16);
         }
     },
-    arcfour256(ARCFOUR256.Factory.NAME, ARCFOUR256.class) {
+    arcfour256(Constants.ARCFOUR256) {
         @Override
-        public NamedFactory<Cipher> create() {
-            return new ARCFOUR256.Factory();
+        public Cipher create() {
+            return new BaseRC4Cipher(8, 32);
         }
     },
-    blowfishcbc(BlowfishCBC.Factory.NAME, BlowfishCBC.class) {
+    blowfishcbc(Constants.BLOWFISH_CBC) {
         @Override
-        public NamedFactory<Cipher> create() {
-            return new BlowfishCBC.Factory();
+        public Cipher create() {
+            return new BaseCipher(8, 16, "Blowfish", "Blowfish/CBC/NoPadding");
         }
     },
-    tripledescbc(TripleDESCBC.Factory.NAME, TripleDESCBC.class) {
+    tripledescbc(Constants.DES_CBC) {
         @Override
-        public NamedFactory<Cipher> create() {
-            return new TripleDESCBC.Factory();
+        public Cipher create() {
+            return new BaseCipher(8, 24, "DESede", "DESede/CBC/NoPadding");
         }
     };
 
     private final String factoryName;
-    private Class<? extends Cipher> cipherType;
 
     @Override
     public final String getName() {
         return factoryName;
     }
 
-    public final Class<? extends Cipher> getCipherType() {
-        return cipherType;
-    }
-
-    BuiltinCiphers(String facName, Class<? extends Cipher> cipherClass) {
+    BuiltinCiphers(String facName) {
         factoryName = facName;
-        cipherType = cipherClass;
     }
 
     private final AtomicReference<Boolean> _supported = new AtomicReference<>(null);
@@ -199,36 +193,17 @@ public enum BuiltinCiphers implements NamedFactory<NamedFactory<Cipher>> {
         return null;
     }
 
-    /**
-     * @param c The {@link Cipher} instance - ignored if {@code null}
-     * @return The matching {@link BuiltinCiphers} - {@code null} if no match
-     * @see #fromCipherType(Class)
-     */
-    public static BuiltinCiphers fromCipher(Cipher c) {
-        if (c == null) {
-            return null;
-        } else {
-            return fromCipherType(c.getClass());
-        }
-    }
-
-    /**
-     * @param type The cipher type - ignored if {@code null} or not a
-     *             {@link Cipher} derived class
-     * @return The matching {@link BuiltinCiphers} - {@code null} if no match
-     */
-    public static BuiltinCiphers fromCipherType(Class<?> type) {
-        if ((type == null) || (!Cipher.class.isAssignableFrom(type))) {
-            return null;
-        }
-
-        for (BuiltinCiphers c : VALUES) {
-            Class<?> t = c.getCipherType();
-            if (t.isAssignableFrom(type)) {
-                return c;
-            }
-        }
-
-        return null;
+    private static class Constants {
+        public static final String NONE = "none";
+        public static final String AES128_CBC = "aes128-cbc";
+        public static final String AES128_CTR = "aes128-ctr";
+        public static final String AES192_CBC = "aes192-cbc";
+        public static final String AES192_CTR = "aes192-ctr";
+        public static final String AES256_CBC = "aes256-cbc";
+        public static final String AES256_CTR = "aes256-ctr";
+        public static final String ARCFOUR128 = "arcfour128";
+        public static final String ARCFOUR256 = "arcfour256";
+        public static final String BLOWFISH_CBC = "blowfish-cbc";
+        public static final String DES_CBC = "3des-cbc";
     }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/31d4dc5a/sshd-core/src/main/java/org/apache/sshd/common/cipher/CipherNone.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/CipherNone.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/CipherNone.java
index 95c82d9..3484d93 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/CipherNone.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/cipher/CipherNone.java
@@ -31,25 +31,6 @@ import org.apache.sshd.common.NamedFactory;
  */
 public class CipherNone implements Cipher {
 
-    /**
-     * Named factory for the no-op Cipher
-     */
-    public static class Factory implements NamedFactory<Cipher> {
-        public static final String NAME = "none";
-
-        public Factory() {
-            super();
-        }
-
-        public String getName() {
-            return NAME;
-        }
-
-        public Cipher create() {
-            return new CipherNone();
-        }
-    }
-
     public int getIVSize() {
         return 8;
     }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/31d4dc5a/sshd-core/src/main/java/org/apache/sshd/common/cipher/TripleDESCBC.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/TripleDESCBC.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/TripleDESCBC.java
deleted file mode 100644
index 5cdae9a..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/TripleDESCBC.java
+++ /dev/null
@@ -1,54 +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.cipher;
-
-import org.apache.sshd.common.Cipher;
-import org.apache.sshd.common.NamedFactory;
-
-/**
- * TripleDESCBC Cipher
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class TripleDESCBC extends BaseCipher {
-
-    /**
-     * Named factory for TripleDESCBC Cipher
-     */
-    public static class Factory implements NamedFactory<Cipher> {
-        public static final String NAME = "3des-cbc";
-
-        public Factory() {
-            super();
-        }
-
-        public String getName() {
-            return NAME;
-        }
-
-        public Cipher create() {
-            return new TripleDESCBC();
-        }
-    }
-
-    public TripleDESCBC() {
-        super(8, 24, "DESede", "DESede/CBC/NoPadding");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/31d4dc5a/sshd-core/src/test/java/org/apache/sshd/CipherTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/CipherTest.java b/sshd-core/src/test/java/org/apache/sshd/CipherTest.java
index af53004..9f9fa74 100644
--- a/sshd-core/src/test/java/org/apache/sshd/CipherTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/CipherTest.java
@@ -26,11 +26,7 @@ import com.jcraft.jsch.JSch;
 import org.apache.sshd.common.Cipher;
 import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.Random;
-import org.apache.sshd.common.cipher.AES128CBC;
-import org.apache.sshd.common.cipher.AES192CBC;
-import org.apache.sshd.common.cipher.AES256CBC;
-import org.apache.sshd.common.cipher.BlowfishCBC;
-import org.apache.sshd.common.cipher.TripleDESCBC;
+import org.apache.sshd.common.cipher.BuiltinCiphers;
 import org.apache.sshd.common.random.BouncyCastleRandom;
 import org.apache.sshd.common.util.SecurityUtils;
 import org.apache.sshd.util.BaseTest;
@@ -56,14 +52,14 @@ public class CipherTest extends BaseTest {
 
     @Test
     public void testAES128CBC() throws Exception {
-        setUp(new AES128CBC.Factory());
+        setUp(BuiltinCiphers.aes128cbc);
         runTest();
     }
 
     @Test
     public void testAES192CBC() throws Exception {
         if (SecurityUtils.isBouncyCastleRegistered() && checkCipher(com.jcraft.jsch.jce.AES192CBC.class.getName())) {
-            setUp(new AES192CBC.Factory());
+            setUp(BuiltinCiphers.aes192cbc);
             runTest();
         }
     }
@@ -71,29 +67,29 @@ public class CipherTest extends BaseTest {
     @Test
     public void testAES256CBC() throws Exception {
         if (SecurityUtils.isBouncyCastleRegistered() && checkCipher(com.jcraft.jsch.jce.AES256CBC.class.getName())) {
-            setUp(new AES256CBC.Factory());
+            setUp(BuiltinCiphers.aes256cbc);
             runTest();
         }
     }
 
     @Test
     public void testBlowfishCBC() throws Exception {
-        setUp(new BlowfishCBC.Factory());
+        setUp(BuiltinCiphers.blowfishcbc);
         runTest();
     }
 
     @Test
     public void testTripleDESCBC() throws Exception {
-        setUp(new TripleDESCBC.Factory());
+        setUp(BuiltinCiphers.tripledescbc);
         runTest();
     }
 
     @Test
     public void loadTest() throws Exception {
         Random random = new BouncyCastleRandom();
-        loadTest(new AES128CBC.Factory(), random);
-        loadTest(new BlowfishCBC.Factory(), random);
-        loadTest(new TripleDESCBC.Factory(), random);
+        loadTest(BuiltinCiphers.aes128cbc, random);
+        loadTest(BuiltinCiphers.blowfishcbc, random);
+        loadTest(BuiltinCiphers.tripledescbc, random);
     }
 
     protected void loadTest(NamedFactory<Cipher> factory, Random random) throws Exception {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/31d4dc5a/sshd-core/src/test/java/org/apache/sshd/ClientTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/ClientTest.java b/sshd-core/src/test/java/org/apache/sshd/ClientTest.java
index 45881d9..8ae3830 100644
--- a/sshd-core/src/test/java/org/apache/sshd/ClientTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/ClientTest.java
@@ -51,6 +51,7 @@ import org.apache.sshd.common.Service;
 import org.apache.sshd.common.Session;
 import org.apache.sshd.common.SshConstants;
 import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.cipher.BuiltinCiphers;
 import org.apache.sshd.common.cipher.CipherNone;
 import org.apache.sshd.common.forward.TcpipServerChannel;
 import org.apache.sshd.common.future.CloseFuture;
@@ -747,8 +748,8 @@ public class ClientTest extends BaseTest {
 
     @Test
     public void testSwitchToNoneCipher() throws Exception {
-        sshd.getCipherFactories().add(new CipherNone.Factory());
-        client.getCipherFactories().add(new CipherNone.Factory());
+        sshd.getCipherFactories().add(BuiltinCiphers.none);
+        client.getCipherFactories().add(BuiltinCiphers.none);
         client.start();
         ClientSession session = client.connect("smx", "localhost", port).await().getSession();
         session.addPasswordIdentity("smx");

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/31d4dc5a/sshd-core/src/test/java/org/apache/sshd/LoadTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/LoadTest.java b/sshd-core/src/test/java/org/apache/sshd/LoadTest.java
index 6489265..86ce8b4 100644
--- a/sshd-core/src/test/java/org/apache/sshd/LoadTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/LoadTest.java
@@ -29,6 +29,7 @@ import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 
 import org.apache.sshd.client.kex.DHGClient;
+import org.apache.sshd.common.Cipher;
 import org.apache.sshd.common.FactoryManager;
 import org.apache.sshd.common.FactoryManagerUtils;
 import org.apache.sshd.common.NamedFactory;
@@ -118,7 +119,7 @@ public class LoadTest extends BaseTest {
             FactoryManagerUtils.updateProperty(props, FactoryManager.WINDOW_SIZE, 1024 * 8);
             client.setKeyExchangeFactories(Arrays.asList(
                     DHGClient.newFactory(BuiltinDHFactories.dhg1)));
-            client.setCipherFactories(Arrays.asList(BuiltinCiphers.blowfishcbc.create()));
+            client.setCipherFactories(Arrays.<NamedFactory<Cipher>>asList(BuiltinCiphers.blowfishcbc));
             client.start();
             try {
                 ClientSession session = client.connect("sshd", "localhost", port).await().getSession();

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/31d4dc5a/sshd-core/src/test/java/org/apache/sshd/MacTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/MacTest.java b/sshd-core/src/test/java/org/apache/sshd/MacTest.java
index 54e8d4a..b0d7092 100644
--- a/sshd-core/src/test/java/org/apache/sshd/MacTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/MacTest.java
@@ -27,11 +27,7 @@ import org.apache.sshd.common.Cipher;
 import org.apache.sshd.common.Mac;
 import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.Random;
-import org.apache.sshd.common.cipher.AES128CBC;
-import org.apache.sshd.common.cipher.AES192CBC;
-import org.apache.sshd.common.cipher.AES256CBC;
-import org.apache.sshd.common.cipher.BlowfishCBC;
-import org.apache.sshd.common.cipher.TripleDESCBC;
+import org.apache.sshd.common.cipher.BuiltinCiphers;
 import org.apache.sshd.common.mac.HMACMD5;
 import org.apache.sshd.common.mac.HMACMD596;
 import org.apache.sshd.common.mac.HMACSHA1;
@@ -39,7 +35,6 @@ import org.apache.sshd.common.mac.HMACSHA196;
 import org.apache.sshd.common.mac.HMACSHA256;
 import org.apache.sshd.common.mac.HMACSHA512;
 import org.apache.sshd.common.random.BouncyCastleRandom;
-import org.apache.sshd.common.util.SecurityUtils;
 import org.apache.sshd.util.BaseTest;
 import org.apache.sshd.util.BogusPasswordAuthenticator;
 import org.apache.sshd.util.EchoShellFactory;
@@ -102,9 +97,9 @@ public class MacTest extends BaseTest {
     @Test
     public void loadTest() throws Exception {
         Random random = new BouncyCastleRandom();
-        loadTest(new AES128CBC.Factory(), random);
-        loadTest(new BlowfishCBC.Factory(), random);
-        loadTest(new TripleDESCBC.Factory(), random);
+        loadTest(BuiltinCiphers.aes128cbc, random);
+        loadTest(BuiltinCiphers.blowfishcbc, random);
+        loadTest(BuiltinCiphers.tripledescbc, random);
     }
 
     protected void loadTest(NamedFactory<Cipher> factory, Random random) throws Exception {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/31d4dc5a/sshd-core/src/test/java/org/apache/sshd/common/cipher/AES192CTRTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/cipher/AES192CTRTest.java b/sshd-core/src/test/java/org/apache/sshd/common/cipher/AES192CTRTest.java
index 12c3e97..138163e 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/cipher/AES192CTRTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/cipher/AES192CTRTest.java
@@ -33,6 +33,6 @@ public class AES192CTRTest extends BaseCipherTest {
 	public void testEncryptDecrypt() throws Exception {
 		// for AES 256 bits we need the JCE unlimited strength policy
 		ensureKeySizeSupported(16, 24, "AES", "AES/CTR/NoPadding");
-		testEncryptDecrypt(new AES192CTR.Factory());
+		testEncryptDecrypt(BuiltinCiphers.aes192ctr);
 	}
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/31d4dc5a/sshd-core/src/test/java/org/apache/sshd/common/cipher/AES256CBCTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/cipher/AES256CBCTest.java b/sshd-core/src/test/java/org/apache/sshd/common/cipher/AES256CBCTest.java
index f63b3d8..fd1ab48 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/cipher/AES256CBCTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/cipher/AES256CBCTest.java
@@ -33,6 +33,6 @@ public class AES256CBCTest extends BaseCipherTest {
 	public void testEncryptDecrypt() throws Exception {
 		// for AES 256 bits we need the JCE unlimited strength policy
 		ensureKeySizeSupported(16, 32, "AES", "AES/CBC/NoPadding");
-		testEncryptDecrypt(new AES256CBC.Factory());
+		testEncryptDecrypt(BuiltinCiphers.aes256cbc);
 	}
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/31d4dc5a/sshd-core/src/test/java/org/apache/sshd/common/cipher/ARCFOUR128Test.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/cipher/ARCFOUR128Test.java b/sshd-core/src/test/java/org/apache/sshd/common/cipher/ARCFOUR128Test.java
index 369e67d..d7672bd 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/cipher/ARCFOUR128Test.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/cipher/ARCFOUR128Test.java
@@ -31,6 +31,6 @@ public class ARCFOUR128Test extends BaseCipherTest {
 
 	@Test
 	public void testEncryptDecrypt() throws Exception {
-		testEncryptDecrypt(new ARCFOUR128.Factory());
+		testEncryptDecrypt(BuiltinCiphers.arcfour128);
 	}
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/31d4dc5a/sshd-core/src/test/java/org/apache/sshd/common/cipher/ARCFOUR256Test.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/cipher/ARCFOUR256Test.java b/sshd-core/src/test/java/org/apache/sshd/common/cipher/ARCFOUR256Test.java
index 5d4b862..9026362 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/cipher/ARCFOUR256Test.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/cipher/ARCFOUR256Test.java
@@ -33,6 +33,6 @@ public class ARCFOUR256Test extends BaseCipherTest {
 	public void testEncryptDecrypt() throws Exception {
 		// for RC4 256 bits we need the JCE unlimited strength policy
 		ensureKeySizeSupported(32, "ARCFOUR", "RC4");
-		testEncryptDecrypt(new ARCFOUR256.Factory());
+		testEncryptDecrypt(BuiltinCiphers.arcfour256);
 	}
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/31d4dc5a/sshd-core/src/test/java/org/apache/sshd/common/cipher/BuiltinCiphersTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/cipher/BuiltinCiphersTest.java b/sshd-core/src/test/java/org/apache/sshd/common/cipher/BuiltinCiphersTest.java
index f9e2f04..357502b 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/cipher/BuiltinCiphersTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/cipher/BuiltinCiphersTest.java
@@ -67,7 +67,7 @@ public class BuiltinCiphersTest extends BaseTest {
                 continue;
             }
             
-            NamedFactory<Cipher>    factory=expected.create();
+            NamedFactory<Cipher>    factory=expected;
             Assert.assertEquals(expected.name() + " - mismatched factory names", expected.getName(), factory.getName());
 
             BuiltinCiphers  actual=BuiltinCiphers.fromFactory(factory);
@@ -75,20 +75,20 @@ public class BuiltinCiphersTest extends BaseTest {
         }
     }
 
-    @Test
-    public void testFromCipher() {
-        for (BuiltinCiphers expected : BuiltinCiphers.VALUES) {
-            if (!expected.isSupported()) {
-                System.out.append("Skip unsupported cipher: ").println(expected);
-                continue;
-            }
-            
-            NamedFactory<Cipher>    factory=expected.create();
-            Cipher                  cipher=factory.create();
-            assertObjectInstanceOf(expected.name() + " - mismatched cipher type", expected.getCipherType(), cipher);
-
-            BuiltinCiphers  actual=BuiltinCiphers.fromCipher(cipher);
-            Assert.assertSame(expected.getName() + " - mismatched enum values", expected, actual);
-        }
-    }
+//    @Test
+//    public void testFromCipher() {
+//        for (BuiltinCiphers expected : BuiltinCiphers.VALUES) {
+//            if (!expected.isSupported()) {
+//                System.out.append("Skip unsupported cipher: ").println(expected);
+//                continue;
+//            }
+//
+//            NamedFactory<Cipher>    factory=expected;
+//            Cipher                  cipher=factory.create();
+//            assertObjectInstanceOf(expected.name() + " - mismatched cipher type", expected.getCipherType(), cipher);
+//
+//            BuiltinCiphers  actual=BuiltinCiphers.fromCipher(cipher);
+//            Assert.assertSame(expected.getName() + " - mismatched enum values", expected, actual);
+//        }
+//    }
 }


[2/6] mina-sshd git commit: [SSHD-438] Use common code to negotiate SFTP version

Posted by gn...@apache.org.
[SSHD-438] Use common code to negotiate SFTP version

Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/7ea07880
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/7ea07880
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/7ea07880

Branch: refs/heads/master
Commit: 7ea0788094726c193d2ecb2f5521b6479764b933
Parents: 2b640b0
Author: Guillaume Nodet <gn...@apache.org>
Authored: Mon Mar 30 10:50:50 2015 +0200
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Mon Mar 30 10:50:50 2015 +0200

----------------------------------------------------------------------
 .../apache/sshd/server/sftp/SftpSubsystem.java  | 225 +++++++++++--------
 1 file changed, 134 insertions(+), 91 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/7ea07880/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java b/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java
index ccf2b9c..92c043d 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java
@@ -113,11 +113,22 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
      */
     public static final String SFTP_VERSION = "sftp-version";
 
-    public static final int LOWER_SFTP_IMPL = 3; // Working implementation from v3
-    public static final int HIGHER_SFTP_IMPL = 6; //  .. up to
-    public static final String ALL_SFTP_IMPL = "3,4,5,6";
+    public static final int LOWER_SFTP_IMPL = SFTP_V3; // Working implementation from v3
+    public static final int HIGHER_SFTP_IMPL = SFTP_V6; //  .. up to
+    public static final String ALL_SFTP_IMPL;
     public static final int  MAX_PACKET_LENGTH = 1024 * 16;
 
+    static {
+        StringBuilder sb = new StringBuilder(2 * (1 + (HIGHER_SFTP_IMPL - LOWER_SFTP_IMPL)));
+        for (int v = LOWER_SFTP_IMPL; v <= HIGHER_SFTP_IMPL; v++) {
+            if (sb.length() > 0) {
+                sb.append(',');
+            }
+            sb.append(v);
+        }
+        ALL_SFTP_IMPL = sb.toString();
+    }
+
     private ExitCallback callback;
     private InputStream in;
     private OutputStream out;
@@ -574,19 +585,63 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
     protected void doVersionSelect(Buffer buffer, int id) throws IOException {
         String ver = buffer.getString();
         log.debug("Received SSH_FXP_EXTENDED(version-select) (version={})", version);
-        if (Integer.toString(SFTP_V3).equals(ver)) {
-            version = SFTP_V3;
-        } else if (Integer.toString(SFTP_V4).equals(ver)) {
-            version = SFTP_V4;
-        } else if (Integer.toString(SFTP_V5).equals(ver)) {
-            version = SFTP_V5;
-        } else if (Integer.toString(SFTP_V6).equals(ver)) {
-            version = SFTP_V6;
-        } else {
-            sendStatus(id, SSH_FX_FAILURE, "Unsupported version " + ver);
-            return;
+        
+        if (GenericUtils.length(ver) == 1) {
+            char digit = ver.charAt(0);
+            if ((digit >= '0') && (digit <= '9')) {
+                int value = digit - '0';
+                String all = checkVersionCompatibility(id, value, SSH_FX_FAILURE);
+                if (GenericUtils.isEmpty(all)) {    // validation failed
+                    return;
+                }
+
+                version = value;
+                sendStatus(id, SSH_FX_OK, "");
+                return;
+            }
         }
-        sendStatus(id, SSH_FX_OK, "");
+
+        sendStatus(id, SSH_FX_FAILURE, "Unsupported version " + ver);
+    }
+
+    /**
+     * Checks if a proposed version is within supported range. <B>Note:</B>
+     * if the user forced a specific value via the {@link #SFTP_VERSION}
+     * property, then it is used to validate the proposed value
+     * @param id The SSH message ID to be used to send the failure message
+     * if required
+     * @param proposed The proposed version value
+     * @param failureOpcode The failure opcode to send if validation fails
+     * @return A {@link String} of comma separated values representing all
+     * the supported version - {@code null} if validation failed and an
+     * appropriate status message was sent
+     * @throws IOException If failed to send the failure status message
+     */
+    protected String checkVersionCompatibility(int id, int proposed, int failureOpcode) throws IOException {
+        int low = LOWER_SFTP_IMPL;
+        int hig = HIGHER_SFTP_IMPL;
+        String available = ALL_SFTP_IMPL;
+        // check if user wants to use a specific version
+        Integer sftpVersion = FactoryManagerUtils.getInteger(session, SFTP_VERSION);
+        if (sftpVersion != null) {
+            int forcedValue = sftpVersion.intValue();
+            if ((forcedValue < LOWER_SFTP_IMPL) || (forcedValue > HIGHER_SFTP_IMPL)) {
+                throw new IllegalStateException("Forced SFTP version (" + sftpVersion + ") not within supported values: " + available);
+            }
+            low = hig = sftpVersion.intValue();
+            available = sftpVersion.toString();
+        }
+
+        if (log.isTraceEnabled()) {
+            log.trace("checkVersionCompatibility(id={}) - proposed={}, available={}", new Object[] { id, proposed, available });
+        }
+
+        if ((proposed < low) || (proposed > hig)) {
+            sendStatus(id, failureOpcode, "Proposed version (" + proposed + ") not in supported range: " + available);
+            return null;
+        }
+
+        return available;
     }
 
     protected void doBlock(Buffer buffer, int id) throws IOException {
@@ -1119,6 +1174,11 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
         if (log.isDebugEnabled()) {
             log.debug("Received SSH_FXP_INIT (version={})", id);
         }
+
+        String all = checkVersionCompatibility(id, id, SSH_FX_OP_UNSUPPORTED);
+        if (GenericUtils.isEmpty(all)) { // i.e. validation failed
+            return;
+        }
         version = id;
         while (buffer.available() > 0) {
             String name = buffer.getString();
@@ -1126,86 +1186,69 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
             extensions.put(name, data);
         }
 
-        int low = LOWER_SFTP_IMPL;
-        int hig = HIGHER_SFTP_IMPL;
-        String all = ALL_SFTP_IMPL;
+        buffer.clear();
+        buffer.putByte((byte) SSH_FXP_VERSION);
+        buffer.putInt(version);
 
-        // check if specific version forced
-        Integer sftpVersion = FactoryManagerUtils.getInteger(session, SFTP_VERSION);
-        if (sftpVersion != null) {
-            low = hig = sftpVersion.intValue();
-            all = sftpVersion.toString();
-        }
-
-        if (version >= low) {
-            version = Math.min(version, hig);
-            buffer.clear();
-            buffer.putByte((byte) SSH_FXP_VERSION);
-            buffer.putInt(version);
-
-            // newline
-            buffer.putString("newline");
-            buffer.putString(System.getProperty("line.separator"));
-
-            // versions
-            buffer.putString("versions");
-            buffer.putString(all);
-
-            // supported
-            buffer.putString("supported");
-            buffer.putInt(5 * 4); // length of 5 integers
-            // supported-attribute-mask
-            buffer.putInt(SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_PERMISSIONS
-                    | SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_CREATETIME
-                    | SSH_FILEXFER_ATTR_MODIFYTIME | SSH_FILEXFER_ATTR_OWNERGROUP
-                    | SSH_FILEXFER_ATTR_BITS);
-            // TODO: supported-attribute-bits
-            buffer.putInt(0);
-            // supported-open-flags
-            buffer.putInt(SSH_FXF_READ | SSH_FXF_WRITE | SSH_FXF_APPEND
-                    | SSH_FXF_CREAT | SSH_FXF_TRUNC | SSH_FXF_EXCL);
-            // TODO: supported-access-mask
-            buffer.putInt(0);
-            // max-read-size
-            buffer.putInt(0);
+        // newline
+        buffer.putString("newline");
+        buffer.putString(System.getProperty("line.separator"));
 
-            // supported2
-            buffer.putString("supported2");
-            buffer.putInt(8 * 4); // length of 7 integers + 2 shorts
-            // supported-attribute-mask
-            buffer.putInt(SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_PERMISSIONS
-                    | SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_CREATETIME
-                    | SSH_FILEXFER_ATTR_MODIFYTIME | SSH_FILEXFER_ATTR_OWNERGROUP
-                    | SSH_FILEXFER_ATTR_BITS);
-            // TODO: supported-attribute-bits
-            buffer.putInt(0);
-            // supported-open-flags
-            buffer.putInt(SSH_FXF_ACCESS_DISPOSITION | SSH_FXF_APPEND_DATA);
-            // TODO: supported-access-mask
-            buffer.putInt(0);
-            // max-read-size
-            buffer.putInt(0);
-            // supported-open-block-vector
-            buffer.putShort(0);
-            // supported-block-vector
-            buffer.putShort(0);
-            // attrib-extension-count
-            buffer.putInt(0);
-            // extension-count
-            buffer.putInt(0);
+        // versions
+        buffer.putString("versions");
+        buffer.putString(all);
 
-                /*
-                buffer.putString("acl-supported");
-                buffer.putInt(4);
-                // capabilities
-                buffer.putInt(0);
-                */
+        // supported
+        buffer.putString("supported");
+        buffer.putInt(5 * 4); // length of 5 integers
+        // supported-attribute-mask
+        buffer.putInt(SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_PERMISSIONS
+                | SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_CREATETIME
+                | SSH_FILEXFER_ATTR_MODIFYTIME | SSH_FILEXFER_ATTR_OWNERGROUP
+                | SSH_FILEXFER_ATTR_BITS);
+        // TODO: supported-attribute-bits
+        buffer.putInt(0);
+        // supported-open-flags
+        buffer.putInt(SSH_FXF_READ | SSH_FXF_WRITE | SSH_FXF_APPEND
+                | SSH_FXF_CREAT | SSH_FXF_TRUNC | SSH_FXF_EXCL);
+        // TODO: supported-access-mask
+        buffer.putInt(0);
+        // max-read-size
+        buffer.putInt(0);
 
-            send(buffer);
-        } else {
-            // We only support version >= 3 (Version 1 and 2 are not common)
-            sendStatus(id, SSH_FX_OP_UNSUPPORTED, "SFTP server only support versions " + all);
-        }
+        // supported2
+        buffer.putString("supported2");
+        buffer.putInt(8 * 4); // length of 7 integers + 2 shorts
+        // supported-attribute-mask
+        buffer.putInt(SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_PERMISSIONS
+                | SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_CREATETIME
+                | SSH_FILEXFER_ATTR_MODIFYTIME | SSH_FILEXFER_ATTR_OWNERGROUP
+                | SSH_FILEXFER_ATTR_BITS);
+        // TODO: supported-attribute-bits
+        buffer.putInt(0);
+        // supported-open-flags
+        buffer.putInt(SSH_FXF_ACCESS_DISPOSITION | SSH_FXF_APPEND_DATA);
+        // TODO: supported-access-mask
+        buffer.putInt(0);
+        // max-read-size
+        buffer.putInt(0);
+        // supported-open-block-vector
+        buffer.putShort(0);
+        // supported-block-vector
+        buffer.putShort(0);
+        // attrib-extension-count
+        buffer.putInt(0);
+        // extension-count
+        buffer.putInt(0);
+
+        /*
+        buffer.putString("acl-supported");
+        buffer.putInt(4);
+        // capabilities
+        buffer.putInt(0);
+        */
+
+        send(buffer);
     }
 
     protected void sendHandle(int id, String handle) throws IOException {


[3/6] mina-sshd git commit: [SSHD-436] Refactor kex factories

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHGServer.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHGServer.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHGServer.java
deleted file mode 100644
index e6a4023..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHGServer.java
+++ /dev/null
@@ -1,151 +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.server.kex;
-
-import java.security.KeyPair;
-import java.security.PublicKey;
-
-import org.apache.sshd.common.Digest;
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.Signature;
-import org.apache.sshd.common.SshConstants;
-import org.apache.sshd.common.SshException;
-import org.apache.sshd.common.kex.AbstractDH;
-import org.apache.sshd.common.session.AbstractSession;
-import org.apache.sshd.common.util.Buffer;
-import org.apache.sshd.common.util.BufferUtils;
-import org.apache.sshd.server.session.ServerSession;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * TODO Add javadoc
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public abstract class AbstractDHGServer implements KeyExchange {
-
-    private final Logger log = LoggerFactory.getLogger(getClass());
-
-    private ServerSession session;
-    private byte[] V_S;
-    private byte[] V_C;
-    private byte[] I_S;
-    private byte[] I_C;
-    private Digest hash;
-    private AbstractDH dh;
-    private byte[] e;
-    private byte[] f;
-    private byte[] K;
-    private byte[] H;
-
-    public void init(AbstractSession s, byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception {
-        if (!(s instanceof ServerSession)) {
-            throw new IllegalStateException("Using a server side KeyExchange on a client");
-        }
-        session = (ServerSession) s;
-        this.V_S = V_S;
-        this.V_C = V_C;
-        this.I_S = I_S;
-        this.I_C = I_C;
-        dh = getDH();
-        hash = dh.getHash();
-        hash.init();
-        f = dh.getE();
-    }
-
-    protected abstract AbstractDH getDH() throws Exception;
-
-    public boolean next(Buffer buffer) throws Exception {
-        byte cmd = buffer.getByte();
-        if (cmd != SshConstants.SSH_MSG_KEXDH_INIT) {
-            throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED, 
-                                   "Protocol error: expected packet " + SshConstants.SSH_MSG_KEXDH_INIT + ", got " + cmd);
-        }
-        log.debug("Received SSH_MSG_KEXDH_INIT");
-        e = buffer.getMPIntAsBytes();
-        dh.setF(e);
-        K = dh.getK();
-
-        byte[] K_S;
-        KeyPair kp = session.getHostKey();
-        String algo = session.getNegotiated(SshConstants.PROPOSAL_SERVER_HOST_KEY_ALGS);
-        Signature sig = NamedFactory.Utils.create(session.getFactoryManager().getSignatureFactories(), algo);
-        sig.init(kp.getPublic(), kp.getPrivate());
-
-        buffer = new Buffer();
-        buffer.putRawPublicKey(kp.getPublic());
-        K_S = buffer.getCompactData();
-
-        buffer.clear();
-        buffer.putString(V_C);
-        buffer.putString(V_S);
-        buffer.putString(I_C);
-        buffer.putString(I_S);
-        buffer.putString(K_S);
-        buffer.putMPInt(e);
-        buffer.putMPInt(f);
-        buffer.putMPInt(K);
-        hash.update(buffer.array(), 0, buffer.available());
-        H = hash.digest();
-
-        byte[] sigH;
-        buffer.clear();
-        sig.update(H, 0, H.length);
-        buffer.putString(algo);
-        buffer.putString(sig.sign());
-        sigH = buffer.getCompactData();
-
-        if (log.isDebugEnabled()) {
-            log.debug("K_S:  {}", BufferUtils.printHex(K_S));
-            log.debug("f:    {}", BufferUtils.printHex(f));
-            log.debug("sigH: {}", BufferUtils.printHex(sigH));
-        }
-
-        // Send response
-        log.debug("Send SSH_MSG_KEXDH_REPLY");
-        buffer.clear();
-        buffer.rpos(5);
-        buffer.wpos(5);
-        buffer.putByte(SshConstants.SSH_MSG_KEXDH_REPLY);
-        buffer.putString(K_S);
-        buffer.putString(f);
-        buffer.putString(sigH);
-        session.writePacket(buffer);
-        return true;
-    }
-
-    public Digest getHash() {
-        return hash;
-    }
-
-    public byte[] getH() {
-        return H;
-    }
-
-    public byte[] getK() {
-        return K;
-    }
-
-    public PublicKey getServerKey() {
-        return session.getHostKey().getPublic();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHServerKeyExchange.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHServerKeyExchange.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHServerKeyExchange.java
new file mode 100644
index 0000000..6d1172b
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHServerKeyExchange.java
@@ -0,0 +1,50 @@
+/*
+ * 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.server.kex;
+
+import java.security.PublicKey;
+
+import org.apache.sshd.common.kex.dh.AbstractDHKeyExchange;
+import org.apache.sshd.common.session.AbstractSession;
+import org.apache.sshd.server.session.ServerSession;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public abstract class AbstractDHServerKeyExchange extends AbstractDHKeyExchange {
+
+    protected ServerSession session;
+
+    protected AbstractDHServerKeyExchange() {
+        super();
+    }
+
+    public void init(AbstractSession s, byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception {
+        super.init(s, V_S, V_C, I_S, I_C);
+        if (!(s instanceof ServerSession)) {
+            throw new IllegalStateException("Using a server side KeyExchange on a client");
+        }
+        session = (ServerSession) s;
+    }
+
+    public PublicKey getServerKey() {
+        return session.getHostKey().getPublic();
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/server/kex/DHG1.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHG1.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHG1.java
deleted file mode 100644
index abe3474..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHG1.java
+++ /dev/null
@@ -1,54 +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.server.kex;
-
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.kex.AbstractDH;
-import org.apache.sshd.common.kex.DH;
-import org.apache.sshd.common.kex.DHGroupData;
-
-/**
- * TODO Add javadoc
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class DHG1 extends AbstractDHGServer {
-
-    public static class Factory implements NamedFactory<KeyExchange> {
-
-        public String getName() {
-            return "diffie-hellman-group1-sha1";
-        }
-
-        public KeyExchange create() {
-            return new DHG1();
-        }
-
-    }
-
-    @Override
-    protected AbstractDH getDH() throws Exception {
-        DH dh = new DH();
-        dh.setG(DHGroupData.getG());
-        dh.setP(DHGroupData.getP1());
-        return dh;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/server/kex/DHG14.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHG14.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHG14.java
deleted file mode 100644
index 2a7b925..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHG14.java
+++ /dev/null
@@ -1,58 +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.server.kex;
-
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.kex.AbstractDH;
-import org.apache.sshd.common.kex.DH;
-import org.apache.sshd.common.kex.DHGroupData;
-
-/**
- * DHG14 does not work with the default JCE implementation provided by Sun
- * because it does not support 2048 bits encryption.
- * It requires BouncyCastle to be used.
- *
- * TODO Add javadoc
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class DHG14 extends AbstractDHGServer {
-
-    public static class Factory implements NamedFactory<KeyExchange> {
-
-        public String getName() {
-            return "diffie-hellman-group14-sha1";
-        }
-
-        public KeyExchange create() {
-            return new DHG14();
-        }
-
-    }
-
-    @Override
-    protected AbstractDH getDH() throws Exception {
-        DH dh = new DH();
-        dh.setG(DHGroupData.getG());
-        dh.setP(DHGroupData.getP14());
-        return dh;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEX.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEX.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEX.java
deleted file mode 100644
index ef777d6..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEX.java
+++ /dev/null
@@ -1,314 +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.server.kex;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.net.URL;
-import java.security.KeyPair;
-import java.security.PublicKey;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.sshd.common.Digest;
-import org.apache.sshd.common.FactoryManagerUtils;
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.Random;
-import org.apache.sshd.common.Signature;
-import org.apache.sshd.common.SshConstants;
-import org.apache.sshd.common.SshException;
-import org.apache.sshd.common.digest.SHA1;
-import org.apache.sshd.common.kex.DH;
-import org.apache.sshd.common.kex.DHGroupData;
-import org.apache.sshd.common.session.AbstractSession;
-import org.apache.sshd.common.util.Buffer;
-import org.apache.sshd.common.util.BufferUtils;
-import org.apache.sshd.common.util.GenericUtils;
-import org.apache.sshd.common.util.SecurityUtils;
-import org.apache.sshd.server.ServerFactoryManager;
-import org.apache.sshd.server.session.ServerSession;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Server side Diffie Hellman Group Exchange
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class DHGEX implements KeyExchange {
-
-    public static class Factory implements NamedFactory<KeyExchange> {
-
-        public String getName() {
-            return "diffie-hellman-group-exchange-sha1";
-        }
-
-        public KeyExchange create() {
-            return new DHGEX();
-        }
-
-    }
-
-    private final Logger log = LoggerFactory.getLogger(getClass());
-
-    private ServerSession session;
-    private byte[] V_S;
-    private byte[] V_C;
-    private byte[] I_S;
-    private byte[] I_C;
-    private Digest hash;
-    private DH dh;
-    private byte[] e;
-    private byte[] f;
-    private byte[] K;
-    private byte[] H;
-
-    int min;
-    int prf;
-    int max;
-    private byte expected;
-    boolean oldRequest;
-
-    public void init(AbstractSession s, byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception {
-        if (!(s instanceof ServerSession)) {
-            throw new IllegalStateException("Using a server side KeyExchange on a client");
-        }
-        session = (ServerSession) s;
-        this.V_S = V_S;
-        this.V_C = V_C;
-        this.I_S = I_S;
-        this.I_C = I_C;
-
-        expected = SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST;
-    }
-
-    public boolean next(Buffer buffer) throws Exception {
-        byte cmd = buffer.getByte();
-
-        if (cmd == SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST_OLD && expected == SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST) {
-            log.debug("Received SSH_MSG_KEX_DH_GEX_REQUEST_OLD");
-            oldRequest = true;
-            min = 1024;
-            prf = buffer.getInt();
-            max = 8192;
-
-            if (max < min || prf < min || max < prf) {
-                throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
-                        "Protocol error: bad parameters " + min + " !< " + prf + " !< " + max);
-            }
-            dh = chooseDH(min, prf, max);
-            f = dh.getE();
-            hash = dh.getHash();
-            hash.init();
-
-            log.debug("Send SSH_MSG_KEX_DH_GEX_GROUP");
-            buffer = session.createBuffer(SshConstants.SSH_MSG_KEX_DH_GEX_GROUP);
-            buffer.putMPInt(dh.getP());
-            buffer.putMPInt(dh.getG());
-            session.writePacket(buffer);
-
-            expected = SshConstants.SSH_MSG_KEX_DH_GEX_INIT;
-            return false;
-        }
-        if (cmd == SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST && expected == SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST) {
-            log.debug("Received SSH_MSG_KEX_DH_GEX_REQUEST");
-            min = buffer.getInt();
-            prf = buffer.getInt();
-            max = buffer.getInt();
-            if (max < min || prf < min || max < prf) {
-                throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
-                        "Protocol error: bad parameters " + min + " !< " + prf + " !< " + max);
-            }
-            dh = chooseDH(min, prf, max);
-            f = dh.getE();
-            hash = dh.getHash();
-            hash.init();
-
-            log.debug("Send SSH_MSG_KEX_DH_GEX_GROUP");
-            buffer = session.createBuffer(SshConstants.SSH_MSG_KEX_DH_GEX_GROUP);
-            buffer.putMPInt(dh.getP());
-            buffer.putMPInt(dh.getG());
-            session.writePacket(buffer);
-
-            expected = SshConstants.SSH_MSG_KEX_DH_GEX_INIT;
-            return false;
-        }
-        if (cmd != expected) {
-            throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
-                    "Protocol error: expected packet " + expected + ", got " + cmd);
-        }
-
-        if (cmd == SshConstants.SSH_MSG_KEX_DH_GEX_INIT) {
-            log.debug("Received SSH_MSG_KEX_DH_GEX_INIT");
-            e = buffer.getMPIntAsBytes();
-            dh.setF(e);
-            K = dh.getK();
-
-
-            byte[] K_S;
-            KeyPair kp = session.getHostKey();
-            String algo = session.getNegotiated(SshConstants.PROPOSAL_SERVER_HOST_KEY_ALGS);
-            Signature sig = NamedFactory.Utils.create(session.getFactoryManager().getSignatureFactories(), algo);
-            sig.init(kp.getPublic(), kp.getPrivate());
-
-            buffer = new Buffer();
-            buffer.putRawPublicKey(kp.getPublic());
-            K_S = buffer.getCompactData();
-
-            buffer.clear();
-            buffer.putString(V_C);
-            buffer.putString(V_S);
-            buffer.putString(I_C);
-            buffer.putString(I_S);
-            buffer.putString(K_S);
-            if (oldRequest) {
-                buffer.putInt(prf);
-            } else {
-                buffer.putInt(min);
-                buffer.putInt(prf);
-                buffer.putInt(max);
-            }
-            buffer.putMPInt(dh.getP());
-            buffer.putMPInt(dh.getG());
-            buffer.putMPInt(e);
-            buffer.putMPInt(f);
-            buffer.putMPInt(K);
-            hash.update(buffer.array(), 0, buffer.available());
-            H = hash.digest();
-
-            byte[] sigH;
-            buffer.clear();
-            sig.update(H, 0, H.length);
-            buffer.putString(algo);
-            buffer.putString(sig.sign());
-            sigH = buffer.getCompactData();
-
-            if (log.isDebugEnabled()) {
-                log.debug("K_S:  {}", BufferUtils.printHex(K_S));
-                log.debug("f:    {}", BufferUtils.printHex(f));
-                log.debug("sigH: {}", BufferUtils.printHex(sigH));
-            }
-
-            // Send response
-            log.debug("Send SSH_MSG_KEX_DH_GEX_REPLY");
-            buffer.clear();
-            buffer.rpos(5);
-            buffer.wpos(5);
-            buffer.putByte(SshConstants.SSH_MSG_KEX_DH_GEX_REPLY);
-            buffer.putString(K_S);
-            buffer.putString(f);
-            buffer.putString(sigH);
-            session.writePacket(buffer);
-            return true;
-        }
-
-        return false;
-    }
-
-    private DH chooseDH(int min, int prf, int max) throws Exception {
-        List<Moduli.DhGroup> groups = loadModuliGroups();
-
-        min = Math.max(min, 1024);
-        prf = Math.max(prf, 1024);
-        // Keys of size > 1024 are not support by default with JCE, so only enable
-        // those if BouncyCastle is registered
-        prf = Math.min(prf, SecurityUtils.isBouncyCastleRegistered() ? 8192 : 1024);
-        max = Math.min(max, 8192);
-        int bestSize = 0;
-        List<Moduli.DhGroup> selected = new ArrayList<Moduli.DhGroup>();
-        for (Moduli.DhGroup group : groups) {
-            if (group.size < min || group.size > max) {
-                continue;
-            }
-            if ((group.size > prf && group.size < bestSize) || (group.size > bestSize && bestSize < prf)) {
-                bestSize = group.size;
-                selected.clear();
-            }
-            if (group.size == bestSize) {
-                selected.add(group);
-            }
-        }
-        if (selected.isEmpty()) {
-            log.warn("No suitable primes found, defaulting to DHG1");
-            return getDH(new BigInteger(DHGroupData.getP1()), new BigInteger(DHGroupData.getG()));
-        }
-        Random random = session.getFactoryManager().getRandomFactory().create();
-        int which = random.random(selected.size());
-        Moduli.DhGroup group = selected.get(which);
-        return getDH(group.p, group.g);
-    }
-
-    protected List<Moduli.DhGroup> loadModuliGroups() throws IOException {
-        List<Moduli.DhGroup> groups = null;
-        URL moduli;
-        String moduliStr = FactoryManagerUtils.getString(session, ServerFactoryManager.MODULI_URL);
-        if (!GenericUtils.isEmpty(moduliStr)) {
-            try {
-                moduli = new URL(moduliStr);
-                groups = Moduli.parseModuli(moduli);
-            } catch (IOException e) {   // OK - use internal moduli
-                log.warn("Error (" + e.getClass().getSimpleName() + ") loading external moduli from " + moduliStr + ": " + e.getMessage());
-            }
-        }
-
-        if (groups == null) {
-            moduliStr = "/org/apache/sshd/moduli";
-            try {
-                if ((moduli = getClass().getResource(moduliStr)) == null) {
-                    throw new FileNotFoundException("Missing internal moduli file");
-                }
-
-                moduliStr = moduli.toExternalForm();
-                groups = Moduli.parseModuli(moduli);
-            } catch (IOException e) {
-                log.warn("Error (" + e.getClass().getSimpleName() + ") loading internal moduli from " + moduliStr + ": " + e.getMessage());
-                throw e;    // this time we MUST throw the exception
-            }
-        }
-
-        log.debug("Loaded moduli groups from {}", moduliStr);
-        return groups;
-    }
-
-    protected DH getDH(BigInteger p, BigInteger g) throws Exception {
-        DH dh = new DH(new SHA1.Factory());
-        dh.setP(p);
-        dh.setG(g);
-        return dh;
-    }
-
-    public Digest getHash() {
-        return hash;
-    }
-
-    public byte[] getH() {
-        return H;
-    }
-
-    public byte[] getK() {
-        return K;
-    }
-
-    public PublicKey getServerKey() {
-        return session.getHostKey().getPublic();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEX256.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEX256.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEX256.java
deleted file mode 100644
index a6dd41e..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEX256.java
+++ /dev/null
@@ -1,55 +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.server.kex;
-
-import java.math.BigInteger;
-
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.digest.SHA256;
-import org.apache.sshd.common.kex.DH;
-
-/**
- * Server side Diffie Hellman Group Exchange
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class DHGEX256 extends DHGEX {
-
-    public static class Factory implements NamedFactory<KeyExchange> {
-
-        public String getName() {
-            return "diffie-hellman-group-exchange-sha256";
-        }
-
-        public KeyExchange create() {
-            return new DHGEX256();
-        }
-
-    }
-
-    @Override
-    protected DH getDH(BigInteger p, BigInteger g) throws Exception {
-        DH dh = new DH(new SHA256.Factory());
-        dh.setP(p);
-        dh.setG(g);
-        return dh;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java
new file mode 100644
index 0000000..5473d65
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java
@@ -0,0 +1,283 @@
+/*
+ * 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.server.kex;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.net.URL;
+import java.security.KeyPair;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.sshd.common.FactoryManagerUtils;
+import org.apache.sshd.common.KeyExchange;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.Random;
+import org.apache.sshd.common.Signature;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.kex.DHG;
+import org.apache.sshd.common.kex.DHFactory;
+import org.apache.sshd.common.kex.DHGroupData;
+import org.apache.sshd.common.session.AbstractSession;
+import org.apache.sshd.common.util.Buffer;
+import org.apache.sshd.common.util.BufferUtils;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.SecurityUtils;
+import org.apache.sshd.server.ServerFactoryManager;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class DHGEXServer extends AbstractDHServerKeyExchange {
+
+    protected final DHFactory factory;
+    protected DHG dh;
+    protected int min;
+    protected int prf;
+    protected int max;
+    protected byte expected;
+    protected boolean oldRequest;
+
+    public static NamedFactory<KeyExchange> newFactory(final DHFactory factory) {
+        return new NamedFactory<KeyExchange>() {
+            @Override
+            public KeyExchange create() {
+                return new DHGEXServer(factory);
+            }
+
+            @Override
+            public String getName() {
+                return factory.getName();
+            }
+
+            @Override
+            public String toString() {
+                return NamedFactory.class.getSimpleName()
+                        + "<" + KeyExchange.class.getSimpleName() + ">"
+                        + "[" + getName() + "]";
+            }
+        };
+    }
+
+    protected DHGEXServer(DHFactory factory) {
+        super();
+        this.factory = factory;
+    }
+
+    public void init(AbstractSession s, byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception {
+        super.init(s, V_S, V_C, I_S, I_C);
+        expected = SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST;
+    }
+
+    public boolean next(Buffer buffer) throws Exception {
+        byte cmd = buffer.getByte();
+
+        if (cmd == SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST_OLD && expected == SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST) {
+            log.debug("Received SSH_MSG_KEX_DH_GEX_REQUEST_OLD");
+            oldRequest = true;
+            min = 1024;
+            prf = buffer.getInt();
+            max = 8192;
+
+            if (max < min || prf < min || max < prf) {
+                throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
+                        "Protocol error: bad parameters " + min + " !< " + prf + " !< " + max);
+            }
+            dh = chooseDH(min, prf, max);
+            f = dh.getE();
+            hash = dh.getHash();
+            hash.init();
+
+            log.debug("Send SSH_MSG_KEX_DH_GEX_GROUP");
+            buffer = session.createBuffer(SshConstants.SSH_MSG_KEX_DH_GEX_GROUP);
+            buffer.putMPInt(dh.getP());
+            buffer.putMPInt(dh.getG());
+            session.writePacket(buffer);
+
+            expected = SshConstants.SSH_MSG_KEX_DH_GEX_INIT;
+            return false;
+        }
+        if (cmd == SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST && expected == SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST) {
+            log.debug("Received SSH_MSG_KEX_DH_GEX_REQUEST");
+            min = buffer.getInt();
+            prf = buffer.getInt();
+            max = buffer.getInt();
+            if (prf < min || max < prf) {
+                throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
+                        "Protocol error: bad parameters " + min + " !< " + prf + " !< " + max);
+            }
+            dh = chooseDH(min, prf, max);
+            f = dh.getE();
+            hash = dh.getHash();
+            hash.init();
+
+            log.debug("Send SSH_MSG_KEX_DH_GEX_GROUP");
+            buffer = session.createBuffer(SshConstants.SSH_MSG_KEX_DH_GEX_GROUP);
+            buffer.putMPInt(dh.getP());
+            buffer.putMPInt(dh.getG());
+            session.writePacket(buffer);
+
+            expected = SshConstants.SSH_MSG_KEX_DH_GEX_INIT;
+            return false;
+        }
+        if (cmd != expected) {
+            throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
+                    "Protocol error: expected packet " + expected + ", got " + cmd);
+        }
+
+        if (cmd == SshConstants.SSH_MSG_KEX_DH_GEX_INIT) {
+            log.debug("Received SSH_MSG_KEX_DH_GEX_INIT");
+            e = buffer.getMPIntAsBytes();
+            dh.setF(e);
+            K = dh.getK();
+
+
+            byte[] K_S;
+            KeyPair kp = session.getHostKey();
+            String algo = session.getNegotiated(SshConstants.PROPOSAL_SERVER_HOST_KEY_ALGS);
+            Signature sig = NamedFactory.Utils.create(session.getFactoryManager().getSignatureFactories(), algo);
+            sig.init(kp.getPublic(), kp.getPrivate());
+
+            buffer = new Buffer();
+            buffer.putRawPublicKey(kp.getPublic());
+            K_S = buffer.getCompactData();
+
+            buffer.clear();
+            buffer.putString(V_C);
+            buffer.putString(V_S);
+            buffer.putString(I_C);
+            buffer.putString(I_S);
+            buffer.putString(K_S);
+            if (oldRequest) {
+                buffer.putInt(prf);
+            } else {
+                buffer.putInt(min);
+                buffer.putInt(prf);
+                buffer.putInt(max);
+            }
+            buffer.putMPInt(dh.getP());
+            buffer.putMPInt(dh.getG());
+            buffer.putMPInt(e);
+            buffer.putMPInt(f);
+            buffer.putMPInt(K);
+            hash.update(buffer.array(), 0, buffer.available());
+            H = hash.digest();
+
+            byte[] sigH;
+            buffer.clear();
+            sig.update(H, 0, H.length);
+            buffer.putString(algo);
+            buffer.putString(sig.sign());
+            sigH = buffer.getCompactData();
+
+            if (log.isDebugEnabled()) {
+                log.debug("K_S:  {}", BufferUtils.printHex(K_S));
+                log.debug("f:    {}", BufferUtils.printHex(f));
+                log.debug("sigH: {}", BufferUtils.printHex(sigH));
+            }
+
+            // Send response
+            log.debug("Send SSH_MSG_KEX_DH_GEX_REPLY");
+            buffer.clear();
+            buffer.rpos(5);
+            buffer.wpos(5);
+            buffer.putByte(SshConstants.SSH_MSG_KEX_DH_GEX_REPLY);
+            buffer.putString(K_S);
+            buffer.putString(f);
+            buffer.putString(sigH);
+            session.writePacket(buffer);
+            return true;
+        }
+
+        return false;
+    }
+
+    private DHG chooseDH(int min, int prf, int max) throws Exception {
+        List<Moduli.DhGroup> groups = loadModuliGroups();
+
+        min = Math.max(min, 1024);
+        prf = Math.max(prf, 1024);
+        // Keys of size > 1024 are not support by default with JCE, so only enable
+        // those if BouncyCastle is registered
+        prf = Math.min(prf, SecurityUtils.isBouncyCastleRegistered() ? 8192 : 1024);
+        max = Math.min(max, 8192);
+        int bestSize = 0;
+        List<Moduli.DhGroup> selected = new ArrayList<>();
+        for (Moduli.DhGroup group : groups) {
+            if (group.size < min || group.size > max) {
+                continue;
+            }
+            if ((group.size > prf && group.size < bestSize) || (group.size > bestSize && bestSize < prf)) {
+                bestSize = group.size;
+                selected.clear();
+            }
+            if (group.size == bestSize) {
+                selected.add(group);
+            }
+        }
+        if (selected.isEmpty()) {
+            log.warn("No suitable primes found, defaulting to DHG1");
+            return getDH(new BigInteger(DHGroupData.getP1()), new BigInteger(DHGroupData.getG()));
+        }
+        Random random = session.getFactoryManager().getRandomFactory().create();
+        int which = random.random(selected.size());
+        Moduli.DhGroup group = selected.get(which);
+        return getDH(group.p, group.g);
+    }
+
+    protected List<Moduli.DhGroup> loadModuliGroups() throws IOException {
+        List<Moduli.DhGroup> groups = null;
+        URL moduli;
+        String moduliStr = FactoryManagerUtils.getString(session, ServerFactoryManager.MODULI_URL);
+        if (!GenericUtils.isEmpty(moduliStr)) {
+            try {
+                moduli = new URL(moduliStr);
+                groups = Moduli.parseModuli(moduli);
+            } catch (IOException e) {   // OK - use internal moduli
+                log.warn("Error (" + e.getClass().getSimpleName() + ") loading external moduli from " + moduliStr + ": " + e.getMessage());
+            }
+        }
+
+        if (groups == null) {
+            moduliStr = "/org/apache/sshd/moduli";
+            try {
+                if ((moduli = getClass().getResource(moduliStr)) == null) {
+                    throw new FileNotFoundException("Missing internal moduli file");
+                }
+
+                moduliStr = moduli.toExternalForm();
+                groups = Moduli.parseModuli(moduli);
+            } catch (IOException e) {
+                log.warn("Error (" + e.getClass().getSimpleName() + ") loading internal moduli from " + moduliStr + ": " + e.getMessage());
+                throw e;    // this time we MUST throw the exception
+            }
+        }
+
+        log.debug("Loaded moduli groups from {}", moduliStr);
+        return groups;
+    }
+
+    protected DHG getDH(BigInteger p, BigInteger g) throws Exception {
+        return (DHG) factory.create(p, g);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGServer.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGServer.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGServer.java
new file mode 100644
index 0000000..13df5c2
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGServer.java
@@ -0,0 +1,136 @@
+/*
+ * 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.server.kex;
+
+import java.security.KeyPair;
+
+import org.apache.sshd.common.KeyExchange;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.Signature;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.kex.AbstractDH;
+import org.apache.sshd.common.kex.DHFactory;
+import org.apache.sshd.common.session.AbstractSession;
+import org.apache.sshd.common.util.Buffer;
+import org.apache.sshd.common.util.BufferUtils;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class DHGServer extends AbstractDHServerKeyExchange {
+
+    protected final DHFactory factory;
+    protected AbstractDH dh;
+
+    public static NamedFactory<KeyExchange> newFactory(final DHFactory factory) {
+        return new NamedFactory<KeyExchange>() {
+            @Override
+            public KeyExchange create() {
+                return new DHGServer(factory);
+            }
+
+            @Override
+            public String getName() {
+                return factory.getName();
+            }
+
+            @Override
+            public String toString() {
+                return NamedFactory.class.getSimpleName()
+                        + "<" + KeyExchange.class.getSimpleName() + ">"
+                        + "[" + getName() + "]";
+            }
+        };
+    }
+
+    protected DHGServer(DHFactory factory) {
+        super();
+        this.factory = factory;
+    }
+
+    @Override
+    public void init(AbstractSession s, byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception {
+        super.init(s, V_S, V_C, I_S, I_C);
+        dh = factory.create();
+        hash = dh.getHash();
+        hash.init();
+        f = dh.getE();
+    }
+
+    public boolean next(Buffer buffer) throws Exception {
+        byte cmd = buffer.getByte();
+        if (cmd != SshConstants.SSH_MSG_KEXDH_INIT) {
+            throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED, 
+                                   "Protocol error: expected packet " + SshConstants.SSH_MSG_KEXDH_INIT + ", got " + cmd);
+        }
+        log.debug("Received SSH_MSG_KEXDH_INIT");
+        e = buffer.getMPIntAsBytes();
+        dh.setF(e);
+        K = dh.getK();
+
+        byte[] K_S;
+        KeyPair kp = session.getHostKey();
+        String algo = session.getNegotiated(SshConstants.PROPOSAL_SERVER_HOST_KEY_ALGS);
+        Signature sig = NamedFactory.Utils.create(session.getFactoryManager().getSignatureFactories(), algo);
+        sig.init(kp.getPublic(), kp.getPrivate());
+
+        buffer = new Buffer();
+        buffer.putRawPublicKey(kp.getPublic());
+        K_S = buffer.getCompactData();
+
+        buffer.clear();
+        buffer.putString(V_C);
+        buffer.putString(V_S);
+        buffer.putString(I_C);
+        buffer.putString(I_S);
+        buffer.putString(K_S);
+        buffer.putMPInt(e);
+        buffer.putMPInt(f);
+        buffer.putMPInt(K);
+        hash.update(buffer.array(), 0, buffer.available());
+        H = hash.digest();
+
+        byte[] sigH;
+        buffer.clear();
+        sig.update(H, 0, H.length);
+        buffer.putString(algo);
+        buffer.putString(sig.sign());
+        sigH = buffer.getCompactData();
+
+        if (log.isDebugEnabled()) {
+            log.debug("K_S:  {}", BufferUtils.printHex(K_S));
+            log.debug("f:    {}", BufferUtils.printHex(f));
+            log.debug("sigH: {}", BufferUtils.printHex(sigH));
+        }
+
+        // Send response
+        log.debug("Send SSH_MSG_KEXDH_REPLY");
+        buffer.clear();
+        buffer.rpos(5);
+        buffer.wpos(5);
+        buffer.putByte(SshConstants.SSH_MSG_KEXDH_REPLY);
+        buffer.putString(K_S);
+        buffer.putString(f);
+        buffer.putString(sigH);
+        session.writePacket(buffer);
+        return true;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/server/kex/ECDHP256.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/ECDHP256.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/ECDHP256.java
deleted file mode 100644
index 7da6c9a..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/server/kex/ECDHP256.java
+++ /dev/null
@@ -1,53 +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.server.kex;
-
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.cipher.ECCurves;
-import org.apache.sshd.common.kex.AbstractDH;
-import org.apache.sshd.common.kex.ECDH;
-
-/**
- * Elliptic Curve Diffie-Hellman with NIST P-256 curve.
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class ECDHP256 extends AbstractDHGServer {
-
-    public static class Factory implements NamedFactory<KeyExchange> {
-
-        public String getName() {
-            return "ecdh-sha2-nistp256";
-        }
-
-        public KeyExchange create() {
-            return new ECDHP256();
-        }
-
-    }
-
-    @Override
-    protected AbstractDH getDH() throws Exception {
-        ECDH ecdh = new ECDH();
-        ecdh.setCurveParameters(ECCurves.EllipticCurves.nistp256);
-        return ecdh;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/server/kex/ECDHP384.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/ECDHP384.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/ECDHP384.java
deleted file mode 100644
index 093cba7..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/server/kex/ECDHP384.java
+++ /dev/null
@@ -1,53 +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.server.kex;
-
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.cipher.ECCurves;
-import org.apache.sshd.common.kex.AbstractDH;
-import org.apache.sshd.common.kex.ECDH;
-
-/**
- * Elliptic Curve Diffie-Hellman with NIST P-256 curve.
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class ECDHP384 extends AbstractDHGServer {
-
-    public static class Factory implements NamedFactory<KeyExchange> {
-
-        public String getName() {
-            return "ecdh-sha2-nistp384";
-        }
-
-        public KeyExchange create() {
-            return new ECDHP384();
-        }
-
-    }
-
-    @Override
-    protected AbstractDH getDH() throws Exception {
-        ECDH ecdh = new ECDH();
-        ecdh.setCurveParameters(ECCurves.EllipticCurves.nistp384);
-        return ecdh;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/server/kex/ECDHP521.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/ECDHP521.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/ECDHP521.java
deleted file mode 100644
index 674e95b..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/server/kex/ECDHP521.java
+++ /dev/null
@@ -1,53 +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.server.kex;
-
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.cipher.ECCurves;
-import org.apache.sshd.common.kex.AbstractDH;
-import org.apache.sshd.common.kex.ECDH;
-
-/**
- * Elliptic Curve Diffie-Hellman with NIST P-256 curve.
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class ECDHP521 extends AbstractDHGServer {
-
-    public static class Factory implements NamedFactory<KeyExchange> {
-
-        public String getName() {
-            return "ecdh-sha2-nistp521";
-        }
-
-        public KeyExchange create() {
-            return new ECDHP521();
-        }
-
-    }
-
-    @Override
-    protected AbstractDH getDH() throws Exception {
-        ECDH ecdh = new ECDH();
-        ecdh.setCurveParameters(ECCurves.EllipticCurves.nistp521);
-        return ecdh;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/test/java/org/apache/sshd/KexTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/KexTest.java b/sshd-core/src/test/java/org/apache/sshd/KexTest.java
deleted file mode 100644
index 2b866e5..0000000
--- a/sshd-core/src/test/java/org/apache/sshd/KexTest.java
+++ /dev/null
@@ -1,153 +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;
-
-import java.io.ByteArrayOutputStream;
-import java.io.OutputStream;
-import java.io.PipedInputStream;
-import java.io.PipedOutputStream;
-import java.util.Collections;
-
-import org.apache.sshd.client.kex.DHG1;
-import org.apache.sshd.client.kex.DHG14;
-import org.apache.sshd.client.kex.DHGEX;
-import org.apache.sshd.client.kex.DHGEX256;
-import org.apache.sshd.client.kex.ECDHP256;
-import org.apache.sshd.client.kex.ECDHP384;
-import org.apache.sshd.client.kex.ECDHP521;
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.util.SecurityUtils;
-import org.apache.sshd.util.BaseTest;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
-import org.apache.sshd.util.EchoShellFactory;
-import org.apache.sshd.util.TeeOutputStream;
-import org.apache.sshd.util.Utils;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertTrue;
-
-/**
- * Test key exchange algorithms.
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class KexTest extends BaseTest {
-
-    private SshServer sshd;
-    private int port;
-
-    @Before
-    public void setUp() throws Exception {
-        sshd = SshServer.setUpDefaultServer();
-        sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
-        sshd.setShellFactory(new EchoShellFactory());
-        sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator());
-        sshd.start();
-        port  = sshd.getPort();
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        sshd.stop(true);
-    }
-
-    @Test
-    public void testDHGEX256() throws Exception {
-        testClient(new DHGEX256.Factory());
-    }
-
-    @Test
-    public void testDHGEX() throws Exception {
-        testClient(new DHGEX.Factory());
-    }
-
-    @Test
-    public void testDHG14() throws Exception {
-        if (SecurityUtils.isBouncyCastleRegistered()) {
-            testClient(new DHG14.Factory());
-        }
-    }
-
-    @Test
-    public void testDHG1() throws Exception {
-        testClient(new DHG1.Factory());
-    }
-
-    @Test
-    public void testECDHP521() throws Exception {
-        testClient(new ECDHP521.Factory());
-    }
-
-    @Test
-    public void testECDHP384() throws Exception {
-        testClient(new ECDHP384.Factory());
-    }
-
-    @Test
-    public void testECDHP256() throws Exception {
-        testClient(new ECDHP256.Factory());
-    }
-
-    private void testClient(NamedFactory<KeyExchange> kex) throws Exception {
-        SshClient client = SshClient.setUpDefaultClient();
-        ByteArrayOutputStream sent = new ByteArrayOutputStream();
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        try {
-            client.setKeyExchangeFactories(Collections.singletonList(kex));
-            client.start();
-            ClientSession session = client.connect("smx", "localhost", port).await().getSession();
-            session.addPasswordIdentity("smx");
-            session.auth().verify();
-            ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
-
-            PipedOutputStream pipedIn = new PipedOutputStream();
-            channel.setIn(new PipedInputStream(pipedIn));
-            OutputStream teeOut = new TeeOutputStream(sent, pipedIn);
-            ByteArrayOutputStream err = new ByteArrayOutputStream();
-            channel.setOut(out);
-            channel.setErr(err);
-            assertTrue(channel.open().await().isOpened());
-
-            teeOut.write("this is my command\n".getBytes());
-            teeOut.flush();
-
-            StringBuilder sb = new StringBuilder();
-            for (int i = 0; i < 10; i++) {
-                sb.append("0123456789");
-            }
-            sb.append("\n");
-            teeOut.write(sb.toString().getBytes());
-
-            teeOut.write("exit\n".getBytes());
-            teeOut.flush();
-
-            channel.waitFor(ClientChannel.CLOSED, 0);
-
-            channel.close(false);
-        } finally {
-            client.stop();
-        }
-
-        assertArrayEquals(sent.toByteArray(), out.toByteArray());
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/test/java/org/apache/sshd/LoadTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/LoadTest.java b/sshd-core/src/test/java/org/apache/sshd/LoadTest.java
index cd73484..6489265 100644
--- a/sshd-core/src/test/java/org/apache/sshd/LoadTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/LoadTest.java
@@ -18,18 +18,23 @@
  */
 package org.apache.sshd;
 
+import static org.junit.Assert.assertArrayEquals;
+
 import java.io.ByteArrayOutputStream;
 import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 
-import org.apache.sshd.client.kex.DHG1;
-import org.apache.sshd.common.Cipher;
-import org.apache.sshd.common.KeyExchange;
+import org.apache.sshd.client.kex.DHGClient;
+import org.apache.sshd.common.FactoryManager;
+import org.apache.sshd.common.FactoryManagerUtils;
 import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.cipher.BlowfishCBC;
+import org.apache.sshd.common.cipher.BuiltinCiphers;
+import org.apache.sshd.common.kex.AbstractDH;
+import org.apache.sshd.common.kex.BuiltinDHFactories;
 import org.apache.sshd.util.BaseTest;
 import org.apache.sshd.util.BogusPasswordAuthenticator;
 import org.apache.sshd.util.EchoShellFactory;
@@ -38,8 +43,6 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
-import static org.junit.Assert.assertArrayEquals;
-
 public class LoadTest extends BaseTest {
 
     private SshServer sshd;
@@ -84,7 +87,7 @@ public class LoadTest extends BaseTest {
     }
 
     protected void test(final String msg, final int nbThreads, final int nbSessionsPerThread) throws Exception {
-        final List<Throwable> errors = new ArrayList<Throwable>();
+        final List<Throwable> errors = new ArrayList<>();
         final CountDownLatch latch = new CountDownLatch(nbThreads);
         for (int i = 0; i < nbThreads; i++) {
             Runnable r = new Runnable() {
@@ -109,37 +112,41 @@ public class LoadTest extends BaseTest {
     }
 
     protected void runClient(String msg) throws Exception {
-        SshClient client = SshClient.setUpDefaultClient();
-        try {
-            client.getProperties().put(SshClient.MAX_PACKET_SIZE, Integer.toString(1024 * 16));
-            client.getProperties().put(SshClient.WINDOW_SIZE, Integer.toString(1024 * 8));
-            client.setKeyExchangeFactories(Arrays.<NamedFactory<KeyExchange>>asList(
-                    new DHG1.Factory()));
-            client.setCipherFactories(Arrays.<NamedFactory<Cipher>>asList(
-                    new BlowfishCBC.Factory()));
+        try(SshClient client = SshClient.setUpDefaultClient()) {
+            Map<String,String>  props=client.getProperties();
+            FactoryManagerUtils.updateProperty(props, FactoryManager.MAX_PACKET_SIZE, 1024 * 16);
+            FactoryManagerUtils.updateProperty(props, FactoryManager.WINDOW_SIZE, 1024 * 8);
+            client.setKeyExchangeFactories(Arrays.asList(
+                    DHGClient.newFactory(BuiltinDHFactories.dhg1)));
+            client.setCipherFactories(Arrays.asList(BuiltinCiphers.blowfishcbc.create()));
             client.start();
-            ClientSession session = client.connect("sshd", "localhost", port).await().getSession();
-            session.addPasswordIdentity("sshd");
-            session.auth().verify();
-
-            ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
-            ByteArrayOutputStream out = new ByteArrayOutputStream();
-            ByteArrayOutputStream err = new ByteArrayOutputStream();
-            channel.setOut(out);
-            channel.setErr(err);
-            channel.open().await();
-            OutputStream pipedIn = channel.getInvertedIn();
-
-            msg += "\nexit\n";
-            pipedIn.write(msg.getBytes());
-            pipedIn.flush();
-
-            channel.waitFor(ClientChannel.CLOSED, 0);
+            try {
+                ClientSession session = client.connect("sshd", "localhost", port).await().getSession();
+                session.addPasswordIdentity("sshd");
+                session.auth().verify();
+    
+                ByteArrayOutputStream out = new ByteArrayOutputStream();
+                ByteArrayOutputStream err = new ByteArrayOutputStream();
+                ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
+                channel.setOut(out);
+                channel.setErr(err);
+                try {
+                    channel.open().await();
+                    OutputStream pipedIn = channel.getInvertedIn();
+        
+                    msg += "\nexit\n";
+                    pipedIn.write(msg.getBytes());
+                    pipedIn.flush();
+        
+                    channel.waitFor(ClientChannel.CLOSED, 0);
+                } finally {    
+                    channel.close(false);
+                }
 
-            channel.close(false);
-            assertArrayEquals(msg.getBytes(), out.toByteArray());
-        } finally {
-            client.stop();
+                assertArrayEquals("Mismatched message data", msg.getBytes(), out.toByteArray());
+            } finally {
+                client.stop();
+            }
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/test/java/org/apache/sshd/client/kex/KexTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/kex/KexTest.java b/sshd-core/src/test/java/org/apache/sshd/client/kex/KexTest.java
new file mode 100644
index 0000000..848dd20
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/client/kex/KexTest.java
@@ -0,0 +1,147 @@
+/*
+ * 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.client.kex;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.util.Collections;
+
+import org.apache.sshd.ClientChannel;
+import org.apache.sshd.ClientSession;
+import org.apache.sshd.SshBuilder;
+import org.apache.sshd.SshClient;
+import org.apache.sshd.SshServer;
+import org.apache.sshd.common.KeyExchange;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.kex.BuiltinDHFactories;
+import org.apache.sshd.common.kex.DHFactory;
+import org.apache.sshd.util.BaseTest;
+import org.apache.sshd.util.BogusPasswordAuthenticator;
+import org.apache.sshd.util.EchoShellFactory;
+import org.apache.sshd.util.TeeOutputStream;
+import org.apache.sshd.util.Utils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test client key exchange algorithms.
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class KexTest extends BaseTest {
+
+    private SshServer sshd;
+    private int port;
+
+    @Before
+    public void setUp() throws Exception {
+        sshd = SshServer.setUpDefaultServer();
+        sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
+        sshd.setShellFactory(new EchoShellFactory());
+        sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator());
+        sshd.start();
+        port  = sshd.getPort();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        sshd.stop(true);
+    }
+
+    @Test
+    public void testClientKeyExchanges() throws Exception {
+        Exception   err=null;
+
+        for (BuiltinDHFactories f : BuiltinDHFactories.VALUES) {
+            if (!f.isSupported()) {
+                System.out.println("Skip KEX=" + f.getName() + " - unsupported");
+                continue;
+            }
+            
+            try {
+                testClient(f);
+            } catch(Exception e) {
+                System.err.println(e.getClass().getSimpleName() + " while test KEX=" + f.getName() + ": " + e.getMessage());
+                err = e;
+            }
+        }
+        
+        if (err != null) {
+            throw err;
+        }
+    }
+
+    private void testClient(DHFactory factory) throws Exception {
+        testClient(SshBuilder.ClientBuilder.getKeyExchangeFactory(factory));
+    }
+
+    private void testClient(NamedFactory<KeyExchange> kex) throws Exception {
+        System.out.println("testClient - KEX=" + kex.getName());
+
+        ByteArrayOutputStream sent = new ByteArrayOutputStream();
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        try(SshClient client = SshClient.setUpDefaultClient()) {
+            client.setKeyExchangeFactories(Collections.singletonList(kex));
+            client.start();
+            
+            try {
+                ClientSession session = client.connect("smx", "localhost", port).await().getSession();
+                session.addPasswordIdentity("smx");
+                session.auth().verify();
+                ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
+                
+                try(PipedOutputStream pipedIn = new PipedOutputStream();
+                    ByteArrayOutputStream err = new ByteArrayOutputStream();
+                    OutputStream teeOut = new TeeOutputStream(sent, pipedIn)) {
+
+                    channel.setIn(new PipedInputStream(pipedIn));
+                    channel.setOut(out);
+                    channel.setErr(err);
+                    assertTrue(channel.open().await().isOpened());
+        
+                    teeOut.write("this is my command\n".getBytes());
+                    teeOut.flush();
+        
+                    StringBuilder sb = new StringBuilder();
+                    for (int i = 0; i < 10; i++) {
+                        sb.append("0123456789");
+                    }
+                    sb.append("\n");
+                    teeOut.write(sb.toString().getBytes());
+        
+                    teeOut.write("exit\n".getBytes());
+                    teeOut.flush();
+        
+                    channel.waitFor(ClientChannel.CLOSED, 0);
+                } finally {    
+                    channel.close(false);
+                }
+            } finally {
+                client.stop();
+            }
+        }
+
+        assertArrayEquals(kex.getName(), sent.toByteArray(), out.toByteArray());
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/test/java/org/apache/sshd/common/kex/BuiltinDHFactoriesTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/kex/BuiltinDHFactoriesTest.java b/sshd-core/src/test/java/org/apache/sshd/common/kex/BuiltinDHFactoriesTest.java
new file mode 100644
index 0000000..6a53dd3
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/common/kex/BuiltinDHFactoriesTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.kex;
+
+import org.apache.sshd.util.BaseTest;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class BuiltinDHFactoriesTest extends BaseTest {
+
+    public BuiltinDHFactoriesTest() {
+        super();
+    }
+
+    @Test
+    public void testFromName() {
+        for (BuiltinDHFactories expected : BuiltinDHFactories.VALUES) {
+            String name = expected.getName();
+            BuiltinDHFactories actual = BuiltinDHFactories.fromFactoryName(name);
+            Assert.assertSame(name, expected, actual);
+        }
+    }
+
+}


[6/6] mina-sshd git commit: [SSHD-430] Refactor digests, macs, signatures as enums

Posted by gn...@apache.org.
[SSHD-430] Refactor digests, macs, signatures as enums


Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/b9e1401c
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/b9e1401c
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/b9e1401c

Branch: refs/heads/master
Commit: b9e1401c1f7d8938f6a6db66c6bccf930139074a
Parents: 31d4dc5
Author: Guillaume Nodet <gn...@apache.org>
Authored: Fri Mar 27 08:35:04 2015 +0100
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Mon Mar 30 10:52:43 2015 +0200

----------------------------------------------------------------------
 .../main/java/org/apache/sshd/SshBuilder.java   |  55 +++----
 .../main/java/org/apache/sshd/SshClient.java    |   5 -
 .../org/apache/sshd/agent/local/AgentImpl.java  |  10 +-
 .../org/apache/sshd/common/NamedFactory.java    |   7 +-
 .../org/apache/sshd/common/cipher/ECCurves.java |  10 +-
 .../sshd/common/digest/BuiltinDigests.java      | 141 ++++++++++++++++++
 .../java/org/apache/sshd/common/digest/MD5.java |  51 -------
 .../org/apache/sshd/common/digest/SHA1.java     |  51 -------
 .../org/apache/sshd/common/digest/SHA256.java   |  52 -------
 .../org/apache/sshd/common/digest/SHA384.java   |  52 -------
 .../org/apache/sshd/common/digest/SHA512.java   |  52 -------
 .../sshd/common/kex/BuiltinDHFactories.java     |  11 +-
 .../org/apache/sshd/common/mac/BuiltinMacs.java | 149 +++++++++++++++++++
 .../org/apache/sshd/common/mac/HMACMD5.java     |  48 ------
 .../org/apache/sshd/common/mac/HMACMD596.java   |  49 ------
 .../org/apache/sshd/common/mac/HMACSHA1.java    |  48 ------
 .../org/apache/sshd/common/mac/HMACSHA196.java  |  48 ------
 .../org/apache/sshd/common/mac/HMACSHA256.java  |  48 ------
 .../org/apache/sshd/common/mac/HMACSHA512.java  |  48 ------
 .../common/signature/AbstractSignatureDSA.java  |  91 -----------
 .../common/signature/BuiltinSignatures.java     | 149 +++++++++++++++++++
 .../sshd/common/signature/SignatureDSA.java     |  77 +++++++---
 .../sshd/common/signature/SignatureECDSA.java   |  68 ---------
 .../sshd/common/signature/SignatureRSA.java     |  15 --
 .../org/apache/sshd/common/util/KeyUtils.java   |   5 +-
 .../server/session/ServerUserAuthService.java   |   2 +-
 .../test/java/org/apache/sshd/EcdsaTest.java    |  44 +-----
 .../src/test/java/org/apache/sshd/LoadTest.java |   8 +-
 .../src/test/java/org/apache/sshd/MacTest.java  |  19 +--
 29 files changed, 557 insertions(+), 856 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java b/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java
index df9fad8..38ebf63 100644
--- a/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java
+++ b/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java
@@ -46,20 +46,13 @@ import org.apache.sshd.common.file.nativefs.NativeFileSystemFactory;
 import org.apache.sshd.common.forward.DefaultTcpipForwarderFactory;
 import org.apache.sshd.common.forward.TcpipServerChannel;
 import org.apache.sshd.common.kex.BuiltinDHFactories;
-import org.apache.sshd.common.mac.HMACMD5;
-import org.apache.sshd.common.mac.HMACMD596;
-import org.apache.sshd.common.mac.HMACSHA1;
-import org.apache.sshd.common.mac.HMACSHA196;
-import org.apache.sshd.common.mac.HMACSHA256;
-import org.apache.sshd.common.mac.HMACSHA512;
 import org.apache.sshd.common.kex.DHFactory;
+import org.apache.sshd.common.mac.BuiltinMacs;
 import org.apache.sshd.common.random.BouncyCastleRandom;
 import org.apache.sshd.common.random.JceRandom;
 import org.apache.sshd.common.random.SingletonRandomFactory;
 import org.apache.sshd.common.session.ConnectionService;
-import org.apache.sshd.common.signature.SignatureDSA;
-import org.apache.sshd.common.signature.SignatureECDSA;
-import org.apache.sshd.common.signature.SignatureRSA;
+import org.apache.sshd.common.signature.BuiltinSignatures;
 import org.apache.sshd.common.util.ObjectBuilder;
 import org.apache.sshd.common.util.SecurityUtils;
 import org.apache.sshd.server.channel.ChannelSession;
@@ -106,12 +99,12 @@ public class SshBuilder {
         protected S fillWithDefaultValues() {
             if (SecurityUtils.isBouncyCastleRegistered()) {
                 if (signatureFactories == null) {
-                    signatureFactories = Arrays.asList(
-                            new SignatureECDSA.NISTP256Factory(),
-                            new SignatureECDSA.NISTP384Factory(),
-                            new SignatureECDSA.NISTP521Factory(),
-                            new SignatureDSA.Factory(),
-                            new SignatureRSA.Factory());
+                    signatureFactories = Arrays.<NamedFactory<Signature>>asList(
+                            BuiltinSignatures.nistp256,
+                            BuiltinSignatures.nistp384,
+                            BuiltinSignatures.nistp521,
+                            BuiltinSignatures.dsa,
+                            BuiltinSignatures.rsa);
                 }
                 if (randomFactory == null) {
                     randomFactory = new SingletonRandomFactory(new BouncyCastleRandom.Factory());
@@ -119,21 +112,21 @@ public class SshBuilder {
                 // EC keys are not supported until OpenJDK 7
             } else if (SecurityUtils.hasEcc()) {
                 if (signatureFactories == null) {
-                    signatureFactories = Arrays.asList(
-                            new SignatureECDSA.NISTP256Factory(),
-                            new SignatureECDSA.NISTP384Factory(),
-                            new SignatureECDSA.NISTP521Factory(),
-                            new SignatureDSA.Factory(),
-                            new SignatureRSA.Factory());
+                    signatureFactories = Arrays.<NamedFactory<Signature>>asList(
+                            BuiltinSignatures.nistp256,
+                            BuiltinSignatures.nistp384,
+                            BuiltinSignatures.nistp521,
+                            BuiltinSignatures.dsa,
+                            BuiltinSignatures.rsa);
                 }
                 if (randomFactory == null) {
                     randomFactory = new SingletonRandomFactory(new JceRandom.Factory());
                 }
             } else {
                 if (signatureFactories == null) {
-                    signatureFactories = Arrays.asList(
-                            new SignatureDSA.Factory(),
-                            new SignatureRSA.Factory());
+                    signatureFactories = Arrays.<NamedFactory<Signature>>asList(
+                            BuiltinSignatures.dsa,
+                            BuiltinSignatures.rsa);
                 }
                 if (randomFactory == null) {
                     randomFactory = new SingletonRandomFactory(new JceRandom.Factory());
@@ -156,13 +149,13 @@ public class SshBuilder {
                         new CompressionNone.Factory());
             }
             if (macFactories == null) {
-                macFactories = Arrays.asList(
-                        new HMACSHA256.Factory(),
-                        new HMACSHA512.Factory(),
-                        new HMACSHA1.Factory(),
-                        new HMACMD5.Factory(),
-                        new HMACSHA196.Factory(),
-                        new HMACMD596.Factory());
+                macFactories = Arrays.<NamedFactory<Mac>>asList(
+                        BuiltinMacs.hmacsha256,
+                        BuiltinMacs.hmacsha512,
+                        BuiltinMacs.hmacsha1,
+                        BuiltinMacs.hmacmd5,
+                        BuiltinMacs.hmacsha196,
+                        BuiltinMacs.hmacmd596);
             }
             if (fileSystemFactory == null) {
                 fileSystemFactory = new NativeFileSystemFactory();

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/main/java/org/apache/sshd/SshClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/SshClient.java b/sshd-core/src/main/java/org/apache/sshd/SshClient.java
index 25be1f4..b3c102e 100644
--- a/sshd-core/src/main/java/org/apache/sshd/SshClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/SshClient.java
@@ -19,15 +19,11 @@
 package org.apache.sshd;
 
 import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.io.StringWriter;
-import java.io.Writer;
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
 import java.util.ArrayList;
@@ -71,7 +67,6 @@ import org.apache.sshd.common.io.IoConnectFuture;
 import org.apache.sshd.common.io.IoConnector;
 import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
 import org.apache.sshd.common.session.AbstractSession;
-import org.apache.sshd.common.util.CloseableUtils;
 import org.apache.sshd.common.util.NoCloseInputStream;
 import org.apache.sshd.common.util.NoCloseOutputStream;
 import org.apache.sshd.common.util.SecurityUtils;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentImpl.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentImpl.java b/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentImpl.java
index 179d9f2..dc1694c 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentImpl.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentImpl.java
@@ -32,9 +32,7 @@ import java.util.List;
 import org.apache.sshd.agent.SshAgent;
 import org.apache.sshd.common.Signature;
 import org.apache.sshd.common.SshException;
-import org.apache.sshd.common.signature.SignatureDSA;
-import org.apache.sshd.common.signature.SignatureECDSA;
-import org.apache.sshd.common.signature.SignatureRSA;
+import org.apache.sshd.common.signature.BuiltinSignatures;
 
 /**
  * A local SSH agent implementation
@@ -66,12 +64,12 @@ public class AgentImpl implements SshAgent {
         try {
             Signature verif;
             if (kp.getFirst().getPublic() instanceof DSAPublicKey) {
-                verif = new SignatureDSA();
+                verif = BuiltinSignatures.dsa.create();
             } else if (kp.getFirst().getPublic() instanceof ECPublicKey) {
                 ECPublicKey pubKey = (ECPublicKey) kp.getFirst().getPublic();
-                verif = SignatureECDSA.getByCurveSize(pubKey.getParams());
+                verif = BuiltinSignatures.getByCurveSize(pubKey.getParams());
             } else if (kp.getFirst().getPublic() instanceof RSAPublicKey) {
-                verif = new SignatureRSA();
+                verif = BuiltinSignatures.rsa.create();
             } else {
                 throw new SshException("Unsupported key type");
             }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/main/java/org/apache/sshd/common/NamedFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/NamedFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/NamedFactory.java
index 6850b8d..9d2c164 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/NamedFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/NamedFactory.java
@@ -48,7 +48,7 @@ public interface NamedFactory<T> extends Factory<T>, NamedResource {
                 return Collections.emptyList();
             }
 
-            List<String> names = new ArrayList<String>(factories.size());
+            List<String> names = new ArrayList<>(factories.size());
             for (NamedFactory<?> f : factories) {
                 names.add(f.getName());
             }
@@ -78,12 +78,11 @@ public interface NamedFactory<T> extends Factory<T>, NamedResource {
          * Get a comma separated list of the factory names from the given list.
          *
          * @param factories list of available factories
-         * @param <T> type of object to create
          * @return a comma separated list of factory names
          */
-        public static <T> String getNames(Collection<? extends NamedFactory<T>> factories) {
+        public static String getNames(Collection<? extends NamedFactory<?>> factories) {
             StringBuilder sb = new StringBuilder();
-            for (NamedFactory<T> f : factories) {
+            for (NamedFactory<?> f : factories) {
                 if (sb.length() > 0) {
                     sb.append(",");
                 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/main/java/org/apache/sshd/common/cipher/ECCurves.java
----------------------------------------------------------------------
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 7c7a951..927b94c 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
@@ -27,9 +27,7 @@ import java.util.Map;
 import java.util.TreeMap;
 
 import org.apache.sshd.common.Digest;
-import org.apache.sshd.common.digest.SHA256;
-import org.apache.sshd.common.digest.SHA384;
-import org.apache.sshd.common.digest.SHA512;
+import org.apache.sshd.common.digest.BuiltinDigests;
 
 /**
  * Utilities for working with elliptic curves.
@@ -76,11 +74,11 @@ public class ECCurves {
     public static Digest getDigestForParams(ECParameterSpec params) {
         int size = getCurveSize(params);
         if (size <= 256) {
-            return new SHA256();
+            return BuiltinDigests.sha256.create();
         } else if (size <= 384) {
-            return new SHA384();
+            return BuiltinDigests.sha384.create();
         } else {
-            return new SHA512();
+            return BuiltinDigests.sha512.create();
         }
     }
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/main/java/org/apache/sshd/common/digest/BuiltinDigests.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/digest/BuiltinDigests.java b/sshd-core/src/main/java/org/apache/sshd/common/digest/BuiltinDigests.java
new file mode 100644
index 0000000..bb57f4c
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/digest/BuiltinDigests.java
@@ -0,0 +1,141 @@
+/*
+ * 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.digest;
+
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+
+import org.apache.sshd.common.Digest;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.util.GenericUtils;
+
+/**
+ * Provides easy access to the currently implemented digests
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public enum BuiltinDigests implements NamedFactory<Digest> {
+    md5(Constants.MD5) {
+        @Override
+        public Digest create() {
+            return new BaseDigest("MD5", 16);
+        }
+    },
+    sha1(Constants.SHA1) {
+        @Override
+        public Digest create() {
+            return new BaseDigest("SHA-1", 20);
+        }
+    },
+    sha256(Constants.SHA256) {
+        @Override
+        public Digest create() {
+            return new BaseDigest("SHA-256", 32);
+        }
+    },
+    sha384(Constants.SHA384) {
+        @Override
+        public Digest create() {
+            return new BaseDigest("SHA-384", 48);
+        }
+    },
+    sha512(Constants.SHA512) {
+        @Override
+        public Digest create() {
+            return new BaseDigest("SHA-512", 64);
+        }
+    };
+
+    private final String factoryName;
+
+    @Override
+    public final String getName() {
+        return factoryName;
+    }
+
+    BuiltinDigests(String facName) {
+        factoryName = facName;
+    }
+
+
+    public static final Set<BuiltinDigests> VALUES =
+            Collections.unmodifiableSet(EnumSet.allOf(BuiltinDigests.class));
+
+    /**
+     * @param s The {@link Enum}'s name - ignored if {@code null}/empty
+     * @return The matching {@link org.apache.sshd.common.digest.BuiltinDigests} whose {@link Enum#name()} matches
+     * (case <U>insensitive</U>) the provided argument - {@code null} if no match
+     */
+    public static BuiltinDigests fromString(String s) {
+        if (GenericUtils.isEmpty(s)) {
+            return null;
+        }
+
+        for (BuiltinDigests c : VALUES) {
+            if (s.equalsIgnoreCase(c.name())) {
+                return c;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * @param factory The {@link org.apache.sshd.common.NamedFactory} for the cipher - ignored if {@code null}
+     * @return The matching {@link org.apache.sshd.common.digest.BuiltinDigests} whose factory name matches
+     * (case <U>insensitive</U>) the digest factory name
+     * @see #fromFactoryName(String)
+     */
+    public static BuiltinDigests fromFactory(NamedFactory<Digest> factory) {
+        if (factory == null) {
+            return null;
+        } else {
+            return fromFactoryName(factory.getName());
+        }
+    }
+
+    /**
+     * @param n The factory name - ignored if {@code null}/empty
+     * @return The matching {@link org.apache.sshd.common.digest.BuiltinDigests} whose factory name matches
+     * (case <U>insensitive</U>) the provided name - {@code null} if no match
+     */
+    public static BuiltinDigests fromFactoryName(String n) {
+        if (GenericUtils.isEmpty(n)) {
+            return null;
+        }
+
+        for (BuiltinDigests c : VALUES) {
+            if (n.equalsIgnoreCase(c.getName())) {
+                return c;
+            }
+        }
+
+        return null;
+    }
+
+    private static class Constants {
+        public static final String MD5 = "md5";
+        public static final String SHA1 = "sha1";
+        public static final String SHA256 = "sha256";
+        public static final String SHA384 = "sha384";
+        public static final String SHA512 = "sha512";
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/main/java/org/apache/sshd/common/digest/MD5.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/digest/MD5.java b/sshd-core/src/main/java/org/apache/sshd/common/digest/MD5.java
deleted file mode 100644
index 72f2f16..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/digest/MD5.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.digest;
-
-import org.apache.sshd.common.Digest;
-import org.apache.sshd.common.NamedFactory;
-
-/**
- * MD5 Digest.
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class MD5 extends BaseDigest {
-
-    /**
-     * Named factory for MD5 digest
-     */
-    public static class Factory implements NamedFactory<Digest> {
-
-        public String getName() {
-            return "md5";
-        }
-
-        public Digest create() {
-            return new MD5();
-        }
-    }
-
-    /**
-     * Create a new instance of a MD5 digest
-     */
-    public MD5() {
-        super("MD5", 16);
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/main/java/org/apache/sshd/common/digest/SHA1.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/digest/SHA1.java b/sshd-core/src/main/java/org/apache/sshd/common/digest/SHA1.java
deleted file mode 100644
index 0c8d6ce..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/digest/SHA1.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.digest;
-
-import org.apache.sshd.common.Digest;
-import org.apache.sshd.common.NamedFactory;
-
-/**
- * SHA1 Digest.
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class SHA1 extends BaseDigest {
-
-    /**
-     * Named factory for SHA1 digest
-     */
-    public static class Factory implements NamedFactory<Digest> {
-
-        public String getName() {
-            return "sha1";
-        }
-
-        public Digest create() {
-            return new SHA1();
-        }
-    }
-
-    /**
-     * Create a new instance of a SHA1 digest
-     */
-    public SHA1() {
-        super("SHA-1", 20);
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/main/java/org/apache/sshd/common/digest/SHA256.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/digest/SHA256.java b/sshd-core/src/main/java/org/apache/sshd/common/digest/SHA256.java
deleted file mode 100644
index 079663d..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/digest/SHA256.java
+++ /dev/null
@@ -1,52 +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.digest;
-
-import org.apache.sshd.common.Digest;
-import org.apache.sshd.common.NamedFactory;
-
-/**
- * SHA-256 Digest.
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class SHA256 extends BaseDigest {
-
-    /**
-     * Named factory for SHA1 digest
-     */
-    public static class Factory implements NamedFactory<Digest> {
-
-        public String getName() {
-            return "sha256";
-        }
-
-        public Digest create() {
-            return new SHA256();
-        }
-    }
-
-    /**
-     * Create a new instance of a SHA-256 digest
-     */
-    public SHA256() {
-        super("SHA-256", 32);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/main/java/org/apache/sshd/common/digest/SHA384.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/digest/SHA384.java b/sshd-core/src/main/java/org/apache/sshd/common/digest/SHA384.java
deleted file mode 100644
index 04dc356..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/digest/SHA384.java
+++ /dev/null
@@ -1,52 +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.digest;
-
-import org.apache.sshd.common.Digest;
-import org.apache.sshd.common.NamedFactory;
-
-/**
- * SHA-384 Digest.
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class SHA384 extends BaseDigest {
-
-    /**
-     * Named factory for SHA1 digest
-     */
-    public static class Factory implements NamedFactory<Digest> {
-
-        public String getName() {
-            return "sha384";
-        }
-
-        public Digest create() {
-            return new SHA384();
-        }
-    }
-
-    /**
-     * Create a new instance of a SHA-384 digest
-     */
-    public SHA384() {
-        super("SHA-384", 48);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/main/java/org/apache/sshd/common/digest/SHA512.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/digest/SHA512.java b/sshd-core/src/main/java/org/apache/sshd/common/digest/SHA512.java
deleted file mode 100644
index 943ee9a..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/digest/SHA512.java
+++ /dev/null
@@ -1,52 +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.digest;
-
-import org.apache.sshd.common.Digest;
-import org.apache.sshd.common.NamedFactory;
-
-/**
- * SHA-512 Digest.
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class SHA512 extends BaseDigest {
-
-    /**
-     * Named factory for SHA1 digest
-     */
-    public static class Factory implements NamedFactory<Digest> {
-
-        public String getName() {
-            return "sha512";
-        }
-
-        public Digest create() {
-            return new SHA512();
-        }
-    }
-
-    /**
-     * Create a new instance of a SHA-512 digest
-     */
-    public SHA512() {
-        super("SHA-512", 64);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/main/java/org/apache/sshd/common/kex/BuiltinDHFactories.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/kex/BuiltinDHFactories.java b/sshd-core/src/main/java/org/apache/sshd/common/kex/BuiltinDHFactories.java
index b2c63cd..b3ba27d 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/kex/BuiltinDHFactories.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/kex/BuiltinDHFactories.java
@@ -25,8 +25,7 @@ import java.util.EnumSet;
 import java.util.Set;
 
 import org.apache.sshd.common.cipher.ECCurves;
-import org.apache.sshd.common.digest.SHA1;
-import org.apache.sshd.common.digest.SHA256;
+import org.apache.sshd.common.digest.BuiltinDigests;
 import org.apache.sshd.common.util.GenericUtils;
 import org.apache.sshd.common.util.SecurityUtils;
 
@@ -41,7 +40,7 @@ public enum BuiltinDHFactories implements DHFactory {
             if (params != null && params.length > 0) {
                 throw new IllegalArgumentException("No accepted parameters for " + getName());
             }
-            return new DHG(new SHA1.Factory(), new BigInteger(DHGroupData.getP1()), new BigInteger(DHGroupData.getG()));
+            return new DHG(BuiltinDigests.sha1, new BigInteger(DHGroupData.getP1()), new BigInteger(DHGroupData.getG()));
         }
     },
     dhg14(Constants.DIFFIE_HELLMAN_GROUP14_SHA1) {
@@ -50,7 +49,7 @@ public enum BuiltinDHFactories implements DHFactory {
             if (params != null && params.length > 0) {
                 throw new IllegalArgumentException("No accepted parameters for " + getName());
             }
-            return new DHG(new SHA1.Factory(), new BigInteger(DHGroupData.getP14()), new BigInteger(DHGroupData.getG()));
+            return new DHG(BuiltinDigests.sha1, new BigInteger(DHGroupData.getP14()), new BigInteger(DHGroupData.getG()));
         }
         @Override
         public boolean isSupported() {
@@ -64,7 +63,7 @@ public enum BuiltinDHFactories implements DHFactory {
                     || !(params[0] instanceof BigInteger) || !(params[1] instanceof BigInteger)) {
                 throw new IllegalArgumentException("Bad parameters for " + getName());
             }
-            return new DHG(new SHA1.Factory(), (BigInteger) params[0], (BigInteger) params[1]);
+            return new DHG(BuiltinDigests.sha1, (BigInteger) params[0], (BigInteger) params[1]);
         }
         @Override
         public boolean isGroupExchange() {
@@ -78,7 +77,7 @@ public enum BuiltinDHFactories implements DHFactory {
                     || !(params[0] instanceof BigInteger) || !(params[1] instanceof BigInteger)) {
                 throw new IllegalArgumentException("Bad parameters for " + getName());
             }
-            return new DHG(new SHA256.Factory(), (BigInteger) params[0], (BigInteger) params[1]);
+            return new DHG(BuiltinDigests.sha256, (BigInteger) params[0], (BigInteger) params[1]);
         }
         @Override
         public boolean isSupported() {  // avoid "Prime size must be multiple of 64, and can only range from 512 to 2048 (inclusive)"

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/main/java/org/apache/sshd/common/mac/BuiltinMacs.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/mac/BuiltinMacs.java b/sshd-core/src/main/java/org/apache/sshd/common/mac/BuiltinMacs.java
new file mode 100644
index 0000000..df8aa6d
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/mac/BuiltinMacs.java
@@ -0,0 +1,149 @@
+/*
+ * 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.mac;
+
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+
+import org.apache.sshd.common.Digest;
+import org.apache.sshd.common.Mac;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.util.GenericUtils;
+
+/**
+ * Provides easy access to the currently implemented macs
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public enum BuiltinMacs implements NamedFactory<Mac> {
+    hmacmd5(Constants.HMAC_MD5) {
+        @Override
+        public Mac create() {
+            return new BaseMac("HmacMD5", 16, 16);
+        }
+    },
+    hmacmd596(Constants.HMAC_MD5_96) {
+        @Override
+        public Mac create() {
+            return new BaseMac("HmacMD5", 12, 16);
+        }
+    },
+    hmacsha1(Constants.HMAC_SHA1) {
+        @Override
+        public Mac create() {
+            return new BaseMac("HmacSHA1", 20, 20);
+        }
+    },
+    hmacsha196(Constants.HMAC_SHA1_96) {
+        @Override
+        public Mac create() {
+            return new BaseMac("HmacSHA1", 12, 20);
+        }
+    },
+    hmacsha256(Constants.HMAC_SHA2_256) {
+        @Override
+        public Mac create() {
+            return new BaseMac("HmacSHA256", 32, 32);
+        }
+    },
+    hmacsha512(Constants.HMAC_SHA2_512) {
+        @Override
+        public Mac create() {
+            return new BaseMac("HmacSHA1", 64, 64);
+        }
+    };
+
+    private final String factoryName;
+
+    @Override
+    public final String getName() {
+        return factoryName;
+    }
+
+    BuiltinMacs(String facName) {
+        factoryName = facName;
+    }
+
+
+    public static final Set<BuiltinMacs> VALUES =
+            Collections.unmodifiableSet(EnumSet.allOf(BuiltinMacs.class));
+
+    /**
+     * @param s The {@link Enum}'s name - ignored if {@code null}/empty
+     * @return The matching {@link org.apache.sshd.common.mac.BuiltinMacs} whose {@link Enum#name()} matches
+     * (case <U>insensitive</U>) the provided argument - {@code null} if no match
+     */
+    public static BuiltinMacs fromString(String s) {
+        if (GenericUtils.isEmpty(s)) {
+            return null;
+        }
+
+        for (BuiltinMacs c : VALUES) {
+            if (s.equalsIgnoreCase(c.name())) {
+                return c;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * @param factory The {@link org.apache.sshd.common.NamedFactory} for the cipher - ignored if {@code null}
+     * @return The matching {@link org.apache.sshd.common.mac.BuiltinMacs} whose factory name matches
+     * (case <U>insensitive</U>) the digest factory name
+     * @see #fromFactoryName(String)
+     */
+    public static BuiltinMacs fromFactory(NamedFactory<Digest> factory) {
+        if (factory == null) {
+            return null;
+        } else {
+            return fromFactoryName(factory.getName());
+        }
+    }
+
+    /**
+     * @param n The factory name - ignored if {@code null}/empty
+     * @return The matching {@link org.apache.sshd.common.mac.BuiltinMacs} whose factory name matches
+     * (case <U>insensitive</U>) the provided name - {@code null} if no match
+     */
+    public static BuiltinMacs fromFactoryName(String n) {
+        if (GenericUtils.isEmpty(n)) {
+            return null;
+        }
+
+        for (BuiltinMacs c : VALUES) {
+            if (n.equalsIgnoreCase(c.getName())) {
+                return c;
+            }
+        }
+
+        return null;
+    }
+
+    private static class Constants {
+        public static final String HMAC_MD5 = "hmac-md5";
+        public static final String HMAC_MD5_96 = "hmac-md5-96";
+        public static final String HMAC_SHA1 = "hmac-sha1";
+        public static final String HMAC_SHA1_96 = "hmac-sha1-96";
+        public static final String HMAC_SHA2_256 = "hmac-sha2-256";
+        public static final String HMAC_SHA2_512 = "hmac-sha2-512";
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/main/java/org/apache/sshd/common/mac/HMACMD5.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/mac/HMACMD5.java b/sshd-core/src/main/java/org/apache/sshd/common/mac/HMACMD5.java
deleted file mode 100644
index 6d9023f..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/mac/HMACMD5.java
+++ /dev/null
@@ -1,48 +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.mac;
-
-import org.apache.sshd.common.Mac;
-import org.apache.sshd.common.NamedFactory;
-
-/**
- * HMAC-MD5 <code>Mac</code>.
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class HMACMD5 extends BaseMac {
-
-    /**
-     * Named factory for the HMACMD5 <code>Mac</code>
-     */
-    public static class Factory implements NamedFactory<Mac> {
-
-        public String getName() {
-            return "hmac-md5";
-        }
-
-        public Mac create() {
-            return new HMACMD5();
-        }
-    }
-
-    public HMACMD5() {
-        super("HmacMD5", 16, 16);
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/main/java/org/apache/sshd/common/mac/HMACMD596.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/mac/HMACMD596.java b/sshd-core/src/main/java/org/apache/sshd/common/mac/HMACMD596.java
deleted file mode 100644
index 73b92cf..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/mac/HMACMD596.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.mac;
-
-import org.apache.sshd.common.Mac;
-import org.apache.sshd.common.NamedFactory;
-
-/**
- * HMAC-MD5-96 <code>Mac</code>
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class HMACMD596 extends BaseMac {
-
-    /**
-     * Named factory for the HMAC-MD5-96 <code>Mac</code>
-     */
-    public static class Factory implements NamedFactory<Mac> {
-
-        public String getName() {
-            return "hmac-md5-96";
-        }
-
-        public Mac create() {
-            return new HMACMD596();
-        }
-    }
-
-    public HMACMD596() {
-        super("HmacMD5", 12, 16);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/main/java/org/apache/sshd/common/mac/HMACSHA1.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/mac/HMACSHA1.java b/sshd-core/src/main/java/org/apache/sshd/common/mac/HMACSHA1.java
deleted file mode 100644
index 454badf..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/mac/HMACSHA1.java
+++ /dev/null
@@ -1,48 +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.mac;
-
-import org.apache.sshd.common.Mac;
-import org.apache.sshd.common.NamedFactory;
-
-/**
- * HMAC-SHA1 <code>Mac</code>
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class HMACSHA1 extends BaseMac {
-
-    /**
-     * Named factory for the HMAC-SHA1 <code>Mac</code>
-     */
-    public static class Factory implements NamedFactory<Mac> {
-
-        public String getName() {
-            return "hmac-sha1";
-        }
-
-        public Mac create() {
-            return new HMACSHA1();
-        }
-    }
-
-    public HMACSHA1() {
-        super("HmacSHA1", 20, 20);
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/main/java/org/apache/sshd/common/mac/HMACSHA196.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/mac/HMACSHA196.java b/sshd-core/src/main/java/org/apache/sshd/common/mac/HMACSHA196.java
deleted file mode 100644
index 23a2f95..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/mac/HMACSHA196.java
+++ /dev/null
@@ -1,48 +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.mac;
-
-import org.apache.sshd.common.Mac;
-import org.apache.sshd.common.NamedFactory;
-
-/**
- * HMAC-SHA1-96 <code>Mac</code>
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class HMACSHA196 extends BaseMac {
-
-    /**
-     * Named factory for the HMAC-SHA1-96 <code>Mac</code>
-     */
-    public static class Factory implements NamedFactory<Mac> {
-
-        public String getName() {
-            return "hmac-sha1-96";
-        }
-
-        public Mac create() {
-            return new HMACSHA196();
-        }
-    }
-
-    public HMACSHA196() {
-        super("HmacSHA1", 12, 20);
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/main/java/org/apache/sshd/common/mac/HMACSHA256.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/mac/HMACSHA256.java b/sshd-core/src/main/java/org/apache/sshd/common/mac/HMACSHA256.java
deleted file mode 100644
index 5f70e0b..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/mac/HMACSHA256.java
+++ /dev/null
@@ -1,48 +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.mac;
-
-import org.apache.sshd.common.Mac;
-import org.apache.sshd.common.NamedFactory;
-
-/**
- * HMAC-SHA256 <code>Mac</code>
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class HMACSHA256 extends BaseMac {
-
-    /**
-     * Named factory for the HMAC-SHA256 <code>Mac</code>
-     */
-    public static class Factory implements NamedFactory<Mac> {
-
-        public String getName() {
-            return "hmac-sha2-256";
-        }
-
-        public Mac create() {
-            return new HMACSHA256();
-        }
-    }
-
-    public HMACSHA256() {
-        super("HmacSHA256", 32, 32);
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/main/java/org/apache/sshd/common/mac/HMACSHA512.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/mac/HMACSHA512.java b/sshd-core/src/main/java/org/apache/sshd/common/mac/HMACSHA512.java
deleted file mode 100644
index e0ac66f..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/mac/HMACSHA512.java
+++ /dev/null
@@ -1,48 +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.mac;
-
-import org.apache.sshd.common.Mac;
-import org.apache.sshd.common.NamedFactory;
-
-/**
- * HMAC-SHA512 <code>Mac</code>
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class HMACSHA512 extends BaseMac {
-
-    /**
-     * Named factory for the HMAC-SHA512 <code>Mac</code>
-     */
-    public static class Factory implements NamedFactory<Mac> {
-
-        public String getName() {
-            return "hmac-sha2-512";
-        }
-
-        public Mac create() {
-            return new HMACSHA512();
-        }
-    }
-
-    public HMACSHA512() {
-        super("HmacSHA512", 64, 64);
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/main/java/org/apache/sshd/common/signature/AbstractSignatureDSA.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/signature/AbstractSignatureDSA.java b/sshd-core/src/main/java/org/apache/sshd/common/signature/AbstractSignatureDSA.java
deleted file mode 100644
index bd2f466..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/signature/AbstractSignatureDSA.java
+++ /dev/null
@@ -1,91 +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.signature;
-
-
-/**
- * DSA <code>Signature</code>
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public abstract class AbstractSignatureDSA extends AbstractSignature {
-    protected AbstractSignatureDSA(String algorithm) {
-	super(algorithm);
-    }
-
-    public byte[] sign() throws Exception {
-        byte[] sig = signature.sign();
-
-        // sig is in ASN.1
-        // SEQUENCE::={ r INTEGER, s INTEGER }
-        int len = 0;
-        int index = 3;
-        len = sig[index++] & 0xff;
-        byte[] r = new byte[len];
-        System.arraycopy(sig, index, r, 0, r.length);
-        index = index + len + 1;
-        len = sig[index++] & 0xff;
-        byte[] s = new byte[len];
-        System.arraycopy(sig, index, s, 0, s.length);
-
-        byte[] result = new byte[40];
-
-        // result must be 40 bytes, but length of r and s may not be 20 bytes
-
-        System.arraycopy(r,
-                         (r.length > 20) ? 1 : 0,
-                         result,
-                         (r.length > 20) ? 0 : 20 - r.length,
-                         (r.length > 20) ? 20 : r.length);
-        System.arraycopy(s,
-                         (s.length > 20) ? 1 : 0,
-                         result,
-                         (s.length > 20) ? 20 : 40 - s.length,
-                         (s.length > 20) ? 20 : s.length);
-
-        return result;
-    }
-
-    public boolean verify(byte[] sig) throws Exception {
-        sig = extractSig(sig);
-
-        // ASN.1
-        int frst = ((sig[0] & 0x80) != 0 ? 1 : 0);
-        int scnd = ((sig[20] & 0x80) != 0 ? 1 : 0);
-
-        int length = sig.length + 6 + frst + scnd;
-        byte[] tmp = new byte[length];
-        tmp[0] = (byte) 0x30;
-        tmp[1] = (byte) 0x2c;
-        tmp[1] += frst;
-        tmp[1] += scnd;
-        tmp[2] = (byte) 0x02;
-        tmp[3] = (byte) 0x14;
-        tmp[3] += frst;
-        System.arraycopy(sig, 0, tmp, 4 + frst, 20);
-        tmp[4 + tmp[3]] = (byte) 0x02;
-        tmp[5 + tmp[3]] = (byte) 0x14;
-        tmp[5 + tmp[3]] += scnd;
-        System.arraycopy(sig, 20, tmp, 6 + tmp[3] + scnd, 20);
-        sig = tmp;
-
-        return signature.verify(sig);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/main/java/org/apache/sshd/common/signature/BuiltinSignatures.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/signature/BuiltinSignatures.java b/sshd-core/src/main/java/org/apache/sshd/common/signature/BuiltinSignatures.java
new file mode 100644
index 0000000..425a47f
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/signature/BuiltinSignatures.java
@@ -0,0 +1,149 @@
+/*
+ * 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.signature;
+
+import java.security.spec.ECParameterSpec;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+
+import org.apache.sshd.common.Digest;
+import org.apache.sshd.common.KeyPairProvider;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.Signature;
+import org.apache.sshd.common.cipher.ECCurves;
+import org.apache.sshd.common.util.GenericUtils;
+
+/**
+ * Provides easy access to the currently implemented macs
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public enum BuiltinSignatures implements NamedFactory<Signature> {
+    dsa(KeyPairProvider.SSH_DSS) {
+        @Override
+        public Signature create() {
+            return new SignatureDSA("SHA1withDSA");
+        }
+    },
+    rsa(KeyPairProvider.SSH_RSA) {
+        @Override
+        public Signature create() {
+            return new SignatureRSA();
+        }
+    },
+    nistp256(KeyPairProvider.ECDSA_SHA2_NISTP256) {
+        @Override
+        public Signature create() {
+            return new SignatureECDSA("SHA256withECDSA");
+        }
+    },
+    nistp384(KeyPairProvider.ECDSA_SHA2_NISTP384) {
+        @Override
+        public Signature create() {
+            return new SignatureECDSA("SHA384withECDSA");
+        }
+    },
+    nistp521(KeyPairProvider.ECDSA_SHA2_NISTP521) {
+        @Override
+        public Signature create() {
+            return new SignatureECDSA("SHA512withECDSA");
+        }
+    };
+
+    private final String factoryName;
+
+    public static Signature getByCurveSize(ECParameterSpec params) {
+        int curveSize = ECCurves.getCurveSize(params);
+        if (curveSize <= 256) {
+            return nistp256.create();
+        } else if (curveSize <= 384) {
+            return nistp384.create();
+        } else {
+            return nistp521.create();
+        }
+    }
+
+    @Override
+    public final String getName() {
+        return factoryName;
+    }
+
+    BuiltinSignatures(String facName) {
+        factoryName = facName;
+    }
+
+
+    public static final Set<BuiltinSignatures> VALUES =
+            Collections.unmodifiableSet(EnumSet.allOf(BuiltinSignatures.class));
+
+    /**
+     * @param s The {@link Enum}'s name - ignored if {@code null}/empty
+     * @return The matching {@link org.apache.sshd.common.signature.BuiltinSignatures} whose {@link Enum#name()} matches
+     * (case <U>insensitive</U>) the provided argument - {@code null} if no match
+     */
+    public static BuiltinSignatures fromString(String s) {
+        if (GenericUtils.isEmpty(s)) {
+            return null;
+        }
+
+        for (BuiltinSignatures c : VALUES) {
+            if (s.equalsIgnoreCase(c.name())) {
+                return c;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * @param factory The {@link org.apache.sshd.common.NamedFactory} for the cipher - ignored if {@code null}
+     * @return The matching {@link org.apache.sshd.common.signature.BuiltinSignatures} whose factory name matches
+     * (case <U>insensitive</U>) the digest factory name
+     * @see #fromFactoryName(String)
+     */
+    public static BuiltinSignatures fromFactory(NamedFactory<Digest> factory) {
+        if (factory == null) {
+            return null;
+        } else {
+            return fromFactoryName(factory.getName());
+        }
+    }
+
+    /**
+     * @param n The factory name - ignored if {@code null}/empty
+     * @return The matching {@link org.apache.sshd.common.signature.BuiltinSignatures} whose factory name matches
+     * (case <U>insensitive</U>) the provided name - {@code null} if no match
+     */
+    public static BuiltinSignatures fromFactoryName(String n) {
+        if (GenericUtils.isEmpty(n)) {
+            return null;
+        }
+
+        for (BuiltinSignatures c : VALUES) {
+            if (n.equalsIgnoreCase(c.getName())) {
+                return c;
+            }
+        }
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureDSA.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureDSA.java b/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureDSA.java
index 1109f54..d682b3a 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureDSA.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureDSA.java
@@ -18,32 +18,75 @@
  */
 package org.apache.sshd.common.signature;
 
-import org.apache.sshd.common.KeyPairProvider;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.Signature;
 
 /**
- * TODO Add javadoc
+ * DSA <code>Signature</code>
  *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public class SignatureDSA extends AbstractSignatureDSA {
-    /**
-     * A named factory for DSA signature
-     */
-    public static class Factory implements NamedFactory<Signature> {
+public class SignatureDSA extends AbstractSignature {
 
-        public String getName() {
-            return KeyPairProvider.SSH_DSS;
-        }
+    protected SignatureDSA(String algorithm) {
+	    super(algorithm);
+    }
+
+    public byte[] sign() throws Exception {
+        byte[] sig = signature.sign();
+
+        // sig is in ASN.1
+        // SEQUENCE::={ r INTEGER, s INTEGER }
+        int len = 0;
+        int index = 3;
+        len = sig[index++] & 0xff;
+        byte[] r = new byte[len];
+        System.arraycopy(sig, index, r, 0, r.length);
+        index = index + len + 1;
+        len = sig[index++] & 0xff;
+        byte[] s = new byte[len];
+        System.arraycopy(sig, index, s, 0, s.length);
+
+        byte[] result = new byte[40];
+
+        // result must be 40 bytes, but length of r and s may not be 20 bytes
 
-        public Signature create() {
-            return new SignatureDSA();
-        }
+        System.arraycopy(r,
+                         (r.length > 20) ? 1 : 0,
+                         result,
+                         (r.length > 20) ? 0 : 20 - r.length,
+                         (r.length > 20) ? 20 : r.length);
+        System.arraycopy(s,
+                         (s.length > 20) ? 1 : 0,
+                         result,
+                         (s.length > 20) ? 20 : 40 - s.length,
+                         (s.length > 20) ? 20 : s.length);
 
+        return result;
     }
 
-    public SignatureDSA() {
-        super("SHA1withDSA");
+    public boolean verify(byte[] sig) throws Exception {
+        sig = extractSig(sig);
+
+        // ASN.1
+        int frst = ((sig[0] & 0x80) != 0 ? 1 : 0);
+        int scnd = ((sig[20] & 0x80) != 0 ? 1 : 0);
+
+        int length = sig.length + 6 + frst + scnd;
+        byte[] tmp = new byte[length];
+        tmp[0] = (byte) 0x30;
+        tmp[1] = (byte) 0x2c;
+        tmp[1] += frst;
+        tmp[1] += scnd;
+        tmp[2] = (byte) 0x02;
+        tmp[3] = (byte) 0x14;
+        tmp[3] += frst;
+        System.arraycopy(sig, 0, tmp, 4 + frst, 20);
+        tmp[4 + tmp[3]] = (byte) 0x02;
+        tmp[5 + tmp[3]] = (byte) 0x14;
+        tmp[5 + tmp[3]] += scnd;
+        System.arraycopy(sig, 20, tmp, 6 + tmp[3] + scnd, 20);
+        sig = tmp;
+
+        return signature.verify(sig);
     }
+
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureECDSA.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureECDSA.java b/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureECDSA.java
index bbaa44c..b1e5a07 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureECDSA.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureECDSA.java
@@ -35,78 +35,10 @@ import org.apache.sshd.common.util.Buffer;
  */
 public class SignatureECDSA extends AbstractSignature {
 
-    /**
-     * Signature algorithm for curves of above 384 bits.
-     */
-    private static final String SIGNATURE_ALGORITHM_512 = "SHA512withECDSA";
-
-    /**
-     * Signature algorithm for curves from 256 to 384 bits.
-     */
-    private static final String SIGNATURE_ALGORITHM_384 = "SHA384withECDSA";
-
-    /**
-     * Signature algorithm for curves of 256 bits and below.
-     */
-    private static final String SIGNATURE_ALGORITHM_256 = "SHA256withECDSA";
-
-    /**
-     * A named factory for ECDSA signatures of NIST P-256
-     */
-    public static class NISTP256Factory implements NamedFactory<Signature> {
-
-        public String getName() {
-            return KeyPairProvider.ECDSA_SHA2_NISTP256;
-        }
-
-        public Signature create() {
-            return new SignatureECDSA(SIGNATURE_ALGORITHM_256);
-        }
-    }
-
-    /**
-     * A named factory for ECDSA signatures of NIST P-384
-     */
-    public static class NISTP384Factory implements NamedFactory<Signature> {
-
-        public String getName() {
-            return KeyPairProvider.ECDSA_SHA2_NISTP384;
-        }
-
-        public Signature create() {
-            return new SignatureECDSA(SIGNATURE_ALGORITHM_384);
-        }
-    }
-
-    /**
-     * A named factory for ECDSA signatures of NIST P-521
-     */
-    public static class NISTP521Factory implements NamedFactory<Signature> {
-
-        public String getName() {
-            return KeyPairProvider.ECDSA_SHA2_NISTP521;
-        }
-
-        public Signature create() {
-            return new SignatureECDSA(SIGNATURE_ALGORITHM_512);
-        }
-    }
-
     protected SignatureECDSA(String algo) {
         super(algo);
     }
 
-    public static Signature getByCurveSize(ECParameterSpec params) {
-        int curveSize = ECCurves.getCurveSize(params);
-        if (curveSize <= 256) {
-            return new SignatureECDSA(SIGNATURE_ALGORITHM_256);
-        } else if (curveSize <= 384) {
-            return new SignatureECDSA(SIGNATURE_ALGORITHM_384);
-        } else {
-            return new SignatureECDSA(SIGNATURE_ALGORITHM_512);
-        }
-    }
-
     public byte[] sign() throws Exception {
         byte[] sig = signature.sign();
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureRSA.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureRSA.java b/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureRSA.java
index de5349f..5c3558a 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureRSA.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureRSA.java
@@ -29,21 +29,6 @@ import org.apache.sshd.common.Signature;
  */
 public class SignatureRSA extends AbstractSignature {
 
-    /**
-     * A named factory for RSA <code>Signature</code>
-     */
-    public static class Factory implements NamedFactory<Signature> {
-
-        public String getName() {
-            return KeyPairProvider.SSH_RSA;
-        }
-
-        public Signature create() {
-            return new SignatureRSA();
-        }
-
-    }
-
     public SignatureRSA() {
         super("SHA1withRSA");
     }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/main/java/org/apache/sshd/common/util/KeyUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/KeyUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/KeyUtils.java
index a47050d..6c7800a 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/KeyUtils.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/KeyUtils.java
@@ -26,9 +26,10 @@ import java.security.interfaces.ECKey;
 import java.security.interfaces.RSAKey;
 import java.security.spec.ECParameterSpec;
 
+import org.apache.sshd.common.Digest;
 import org.apache.sshd.common.KeyPairProvider;
 import org.apache.sshd.common.cipher.ECCurves;
-import org.apache.sshd.common.digest.MD5;
+import org.apache.sshd.common.digest.BuiltinDigests;
 
 /**
  * Utility class for keys
@@ -47,7 +48,7 @@ public class KeyUtils {
         try {
             Buffer buffer = new Buffer();
             buffer.putRawPublicKey(key);
-            MD5 md5 = new MD5();
+            Digest md5 = BuiltinDigests.md5.create();
             md5.init();
             md5.update(buffer.array(), 0, buffer.wpos());
             byte[] data = md5.digest();

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
index baa0e83..8929896 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
@@ -187,7 +187,7 @@ public class ServerUserAuthService extends CloseableUtils.AbstractCloseable impl
                 Integer maxSessionCount = FactoryManagerUtils.getInteger(manager, ServerFactoryManager.MAX_CONCURRENT_SESSIONS);
                 if (maxSessionCount != null) {
                     int currentSessionCount = session.getActiveSessionCountForUser(username);
-                    if (currentSessionCount >= maxSessionCount.intValue()) {
+                    if (currentSessionCount >= maxSessionCount) {
                         session.disconnect(SshConstants.SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE,
                                 "Too many concurrent connections (" + currentSessionCount + ") - max. allowed: " + maxSessionCount);
                         return;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/test/java/org/apache/sshd/EcdsaTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/EcdsaTest.java b/sshd-core/src/test/java/org/apache/sshd/EcdsaTest.java
index ae60071..98de765 100644
--- a/sshd-core/src/test/java/org/apache/sshd/EcdsaTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/EcdsaTest.java
@@ -18,65 +18,29 @@
  */
 package org.apache.sshd;
 
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.math.BigInteger;
 import java.security.KeyPair;
 import java.security.KeyPairGenerator;
 import java.security.PublicKey;
 import java.security.SecureRandom;
-import java.security.spec.ECFieldFp;
 import java.security.spec.ECGenParameterSpec;
-import java.security.spec.ECParameterSpec;
-import java.security.spec.EllipticCurve;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
 
-import org.apache.sshd.client.SessionFactory;
-import org.apache.sshd.client.channel.ChannelShell;
-import org.apache.sshd.client.future.AuthFuture;
-import org.apache.sshd.client.session.ClientSessionImpl;
-import org.apache.sshd.common.KeyPairProvider;
 import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.RuntimeSshException;
-import org.apache.sshd.common.Session;
-import org.apache.sshd.common.SessionListener;
 import org.apache.sshd.common.Signature;
-import org.apache.sshd.common.SshConstants;
-import org.apache.sshd.common.SshException;
-import org.apache.sshd.common.cipher.ECCurves;
-import org.apache.sshd.common.io.IoSession;
 import org.apache.sshd.common.keyprovider.AbstractKeyPairProvider;
-import org.apache.sshd.common.session.AbstractSession;
-import org.apache.sshd.common.signature.SignatureDSA;
-import org.apache.sshd.common.signature.SignatureECDSA;
-import org.apache.sshd.common.signature.SignatureRSA;
+import org.apache.sshd.common.signature.BuiltinSignatures;
 import org.apache.sshd.common.util.SecurityUtils;
-import org.apache.sshd.server.Command;
 import org.apache.sshd.server.PublickeyAuthenticator;
-import org.apache.sshd.server.command.ScpCommandFactory;
-import org.apache.sshd.server.keyprovider.AbstractGeneratorHostKeyProvider;
 import org.apache.sshd.server.session.ServerSession;
-import org.apache.sshd.server.sftp.SftpSubsystem;
 import org.apache.sshd.util.BaseTest;
 import org.apache.sshd.util.BogusPasswordAuthenticator;
-import org.apache.sshd.util.EchoShellFactory;
 import org.apache.sshd.util.Utils;
-import org.bouncycastle.jce.ECPointUtil;
-import org.bouncycastle.util.encoders.Hex;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
 /**
  * TODO Add javadoc
  *
@@ -128,9 +92,9 @@ public class EcdsaTest extends BaseTest {
 
             client = SshClient.setUpDefaultClient();
             client.setSignatureFactories(Arrays.<NamedFactory<Signature>>asList(
-                    new SignatureECDSA.NISTP256Factory(),
-                    new SignatureECDSA.NISTP384Factory(),
-                    new SignatureECDSA.NISTP521Factory()));
+                    BuiltinSignatures.nistp256,
+                    BuiltinSignatures.nistp384,
+                    BuiltinSignatures.nistp521));
             client.start();
             ClientSession s = client.connect("smx", "localhost", port).await().getSession();
             s.addPasswordIdentity("smx");

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/test/java/org/apache/sshd/LoadTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/LoadTest.java b/sshd-core/src/test/java/org/apache/sshd/LoadTest.java
index 86ce8b4..ca07844 100644
--- a/sshd-core/src/test/java/org/apache/sshd/LoadTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/LoadTest.java
@@ -18,8 +18,6 @@
  */
 package org.apache.sshd;
 
-import static org.junit.Assert.assertArrayEquals;
-
 import java.io.ByteArrayOutputStream;
 import java.io.OutputStream;
 import java.util.ArrayList;
@@ -28,13 +26,11 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 
-import org.apache.sshd.client.kex.DHGClient;
 import org.apache.sshd.common.Cipher;
 import org.apache.sshd.common.FactoryManager;
 import org.apache.sshd.common.FactoryManagerUtils;
 import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.cipher.BuiltinCiphers;
-import org.apache.sshd.common.kex.AbstractDH;
 import org.apache.sshd.common.kex.BuiltinDHFactories;
 import org.apache.sshd.util.BaseTest;
 import org.apache.sshd.util.BogusPasswordAuthenticator;
@@ -44,6 +40,8 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
+import static org.junit.Assert.assertArrayEquals;
+
 public class LoadTest extends BaseTest {
 
     private SshServer sshd;
@@ -118,7 +116,7 @@ public class LoadTest extends BaseTest {
             FactoryManagerUtils.updateProperty(props, FactoryManager.MAX_PACKET_SIZE, 1024 * 16);
             FactoryManagerUtils.updateProperty(props, FactoryManager.WINDOW_SIZE, 1024 * 8);
             client.setKeyExchangeFactories(Arrays.asList(
-                    DHGClient.newFactory(BuiltinDHFactories.dhg1)));
+                    SshBuilder.ClientBuilder.getKeyExchangeFactory(BuiltinDHFactories.dhg1)));
             client.setCipherFactories(Arrays.<NamedFactory<Cipher>>asList(BuiltinCiphers.blowfishcbc));
             client.start();
             try {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/b9e1401c/sshd-core/src/test/java/org/apache/sshd/MacTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/MacTest.java b/sshd-core/src/test/java/org/apache/sshd/MacTest.java
index b0d7092..c8d97d3 100644
--- a/sshd-core/src/test/java/org/apache/sshd/MacTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/MacTest.java
@@ -28,12 +28,7 @@ import org.apache.sshd.common.Mac;
 import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.Random;
 import org.apache.sshd.common.cipher.BuiltinCiphers;
-import org.apache.sshd.common.mac.HMACMD5;
-import org.apache.sshd.common.mac.HMACMD596;
-import org.apache.sshd.common.mac.HMACSHA1;
-import org.apache.sshd.common.mac.HMACSHA196;
-import org.apache.sshd.common.mac.HMACSHA256;
-import org.apache.sshd.common.mac.HMACSHA512;
+import org.apache.sshd.common.mac.BuiltinMacs;
 import org.apache.sshd.common.random.BouncyCastleRandom;
 import org.apache.sshd.util.BaseTest;
 import org.apache.sshd.util.BogusPasswordAuthenticator;
@@ -59,38 +54,38 @@ public class MacTest extends BaseTest {
 
     @Test
     public void testHMACMD5() throws Exception {
-        setUp(new HMACMD5.Factory());
+        setUp(BuiltinMacs.hmacmd5);
         runTest();
     }
 
     @Test
     public void testHMACMD596() throws Exception {
-        setUp(new HMACMD596.Factory());
+        setUp(BuiltinMacs.hmacmd596);
         runTest();
     }
 
     @Test
     public void testHMACSHA1() throws Exception {
-        setUp(new HMACSHA1.Factory());
+        setUp(BuiltinMacs.hmacsha1);
         runTest();
     }
 
     @Test
     public void testHMACSHA196() throws Exception {
-        setUp(new HMACSHA196.Factory());
+        setUp(BuiltinMacs.hmacsha196);
         runTest();
     }
 
     @Test
     public void testHMACSHA256() throws Exception {
-        setUp(new HMACSHA256.Factory());
+        setUp(BuiltinMacs.hmacsha256);
         runTest();
     }
 
     @Test
     @Ignore("Lead to ArrayIndexOutOfBoundsException in JSch")
     public void testHMACSHA512() throws Exception {
-        setUp(new HMACSHA512.Factory());
+        setUp(BuiltinMacs.hmacsha512);
         runTest();
     }