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 2014/10/15 23:13:01 UTC

[1/2] git commit: [SSHD-357] ARCFOUR 128/256 ciphers initialization incorrect - always fails

Repository: mina-sshd
Updated Branches:
  refs/heads/master b91da7d13 -> 1a1ca8c88


[SSHD-357] ARCFOUR 128/256 ciphers initialization incorrect - always fails

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

Branch: refs/heads/master
Commit: ec2bffdfcdb167076a168e21c842e2d7b4e90ee7
Parents: b91da7d
Author: Guillaume Nodet <gn...@apache.org>
Authored: Wed Oct 15 20:57:01 2014 +0200
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Wed Oct 15 20:57:01 2014 +0200

----------------------------------------------------------------------
 .../apache/sshd/common/cipher/ARCFOUR128.java   | 20 +----
 .../apache/sshd/common/cipher/ARCFOUR256.java   | 17 +---
 .../apache/sshd/common/cipher/BaseCipher.java   |  2 +-
 .../sshd/common/cipher/BaseRC4Cipher.java       | 54 ++++++++++++
 .../sshd/common/cipher/AES256CBCTest.java       | 38 ++++++++
 .../sshd/common/cipher/ARCFOUR128Test.java      | 36 ++++++++
 .../sshd/common/cipher/ARCFOUR256Test.java      | 38 ++++++++
 .../sshd/common/cipher/BaseCipherTest.java      | 92 ++++++++++++++++++++
 8 files changed, 264 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ec2bffdf/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
index b04a1b4..4ff5f1d 100644
--- 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
@@ -26,10 +26,10 @@ import org.apache.sshd.common.NamedFactory;
  *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public class ARCFOUR128 extends BaseCipher {
+public class ARCFOUR128 extends BaseRC4Cipher {
 
     /**
-     * Named factory for AES128CTR Cipher
+     * Named factory for ARCFOUR128 Cipher
      */
     public static class Factory implements NamedFactory<Cipher> {
         public String getName() {
@@ -41,21 +41,7 @@ public class ARCFOUR128 extends BaseCipher {
     }
 
     public ARCFOUR128() {
-        super(8, 16, "ARCFOUR", "RC4");
-    }
-
-    @Override
-    public void init(Mode mode, byte[] key, byte[] iv) throws Exception {
-        super.init(mode, key, iv);
-        try {
-            byte[] foo = new byte[1];
-            for (int i = 0; i < 1536; i++) {
-                cipher.update(foo, 0, 1, foo, 0);
-            }
-        } catch (Exception e) {
-            cipher = null;
-            throw e;
-        }
+        super(8, 16);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ec2bffdf/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
index cc30889..fed8176 100644
--- 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
@@ -26,7 +26,7 @@ import org.apache.sshd.common.NamedFactory;
  *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public class ARCFOUR256 extends BaseCipher {
+public class ARCFOUR256 extends BaseRC4Cipher {
 
     /**
      * Named factory for AES128CTR Cipher
@@ -41,20 +41,7 @@ public class ARCFOUR256 extends BaseCipher {
     }
 
     public ARCFOUR256() {
-        super(8, 32, "ARCFOUR", "RC4");
+        super(8, 32);
     }
 
-    @Override
-    public void init(Mode mode, byte[] key, byte[] iv) throws Exception {
-        super.init(mode, key, iv);
-        try {
-            byte[] foo = new byte[1];
-            for (int i = 0; i < 1536; i++) {
-                cipher.update(foo, 0, 1, foo, 0);
-            }
-        } catch (Exception e) {
-            cipher = null;
-            throw e;
-        }
-    }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ec2bffdf/sshd-core/src/main/java/org/apache/sshd/common/cipher/BaseCipher.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/BaseCipher.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/BaseCipher.java
index 78ffdcd..33c18b2 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/BaseCipher.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/cipher/BaseCipher.java
@@ -71,7 +71,7 @@ public class BaseCipher implements Cipher {
         cipher.update(input, inputOffset, inputLen, input, inputOffset);
     }
 
-    private static final byte[] resize(byte[] data, int size) {
+    protected static byte[] resize(byte[] data, int size) {
         if (data.length > size) {
             byte[] tmp = new byte[size];
             System.arraycopy(data, 0, tmp, 0, size);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ec2bffdf/sshd-core/src/main/java/org/apache/sshd/common/cipher/BaseRC4Cipher.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/BaseRC4Cipher.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/BaseRC4Cipher.java
new file mode 100644
index 0000000..7183ae0
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/cipher/BaseRC4Cipher.java
@@ -0,0 +1,54 @@
+/*
+ * 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.util.SecurityUtils;
+
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class BaseRC4Cipher extends BaseCipher {
+
+    public static final int	SKIP_SIZE = 1536;
+
+    public BaseRC4Cipher(int ivsize, int bsize) {
+        super(ivsize, bsize, "ARCFOUR", "RC4");
+    }
+
+    @Override
+    public void init(Mode mode, byte[] key, byte[] iv) throws Exception {
+        key = resize(key, bsize);
+        try {
+            cipher = SecurityUtils.getCipher(transformation);
+            cipher.init((mode == Mode.Encrypt ? javax.crypto.Cipher.ENCRYPT_MODE : javax.crypto.Cipher.DECRYPT_MODE),
+                    new SecretKeySpec(key, algorithm));
+
+            byte[] foo = new byte[1];
+            for (int i = 0; i < SKIP_SIZE; i++) {
+                cipher.update(foo, 0, 1, foo, 0);
+            }
+        } catch (Exception e) {
+            cipher = null;
+            throw e;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ec2bffdf/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
new file mode 100644
index 0000000..f63b3d8
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/common/cipher/AES256CBCTest.java
@@ -0,0 +1,38 @@
+/*
+ * 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.junit.Test;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class AES256CBCTest extends BaseCipherTest {
+	public AES256CBCTest() {
+		super();
+	}
+
+	@Test
+	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());
+	}
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ec2bffdf/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
new file mode 100644
index 0000000..369e67d
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/common/cipher/ARCFOUR128Test.java
@@ -0,0 +1,36 @@
+/*
+ * 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.junit.Test;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class ARCFOUR128Test extends BaseCipherTest {
+	public ARCFOUR128Test() {
+		super();
+	}
+
+	@Test
+	public void testEncryptDecrypt() throws Exception {
+		testEncryptDecrypt(new ARCFOUR128.Factory());
+	}
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ec2bffdf/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
new file mode 100644
index 0000000..5d4b862
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/common/cipher/ARCFOUR256Test.java
@@ -0,0 +1,38 @@
+/*
+ * 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.junit.Test;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class ARCFOUR256Test extends BaseCipherTest {
+	public ARCFOUR256Test() {
+		super();
+	}
+
+	@Test
+	public void testEncryptDecrypt() throws Exception {
+		// for RC4 256 bits we need the JCE unlimited strength policy
+		ensureKeySizeSupported(32, "ARCFOUR", "RC4");
+		testEncryptDecrypt(new ARCFOUR256.Factory());
+	}
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ec2bffdf/sshd-core/src/test/java/org/apache/sshd/common/cipher/BaseCipherTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/cipher/BaseCipherTest.java b/sshd-core/src/test/java/org/apache/sshd/common/cipher/BaseCipherTest.java
new file mode 100644
index 0000000..9abcbf7
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/common/cipher/BaseCipherTest.java
@@ -0,0 +1,92 @@
+/*
+ * 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 java.security.GeneralSecurityException;
+import java.security.InvalidKeyException;
+
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.sshd.common.Cipher;
+import org.apache.sshd.common.Cipher.Mode;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.util.SecurityUtils;
+import org.apache.sshd.util.BaseTest;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.internal.AssumptionViolatedException;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public abstract class BaseCipherTest extends BaseTest {
+	protected BaseCipherTest() {
+		super();
+	}
+
+	protected void ensureKeySizeSupported(int bsize, String algorithm, String transformation) throws GeneralSecurityException {
+		try {
+	        javax.crypto.Cipher	cipher=SecurityUtils.getCipher(transformation);
+	        byte[]				key=new byte[bsize];
+	        cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, new SecretKeySpec(key, algorithm));
+		} catch(GeneralSecurityException e) {
+			if (e instanceof InvalidKeyException) {	// NOTE: assumption violations are NOT test failures...
+				throw new AssumptionViolatedException(algorithm + "/" + transformation + "[" + bsize + "] N/A");
+			}
+
+			throw e;
+		}
+	}
+
+	protected void ensureKeySizeSupported(int ivsize, int bsize, String algorithm, String transformation) throws GeneralSecurityException {
+		try {
+	        javax.crypto.Cipher	cipher=SecurityUtils.getCipher(transformation);
+	        byte[]				key=new byte[bsize];
+	        byte[]				iv=new byte[ivsize];
+	        cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, new SecretKeySpec(key, algorithm), new IvParameterSpec(iv));
+		} catch(GeneralSecurityException e) {
+			if (e instanceof InvalidKeyException) {
+				Assume.assumeTrue(algorithm + "/" + transformation + "[" + bsize + "/" + ivsize + "]", false /* force exception */);
+			}
+
+			throw e;
+		}
+	}
+
+	protected void testEncryptDecrypt(NamedFactory<Cipher> factory) throws Exception {
+		String	facName=factory.getName();
+		Cipher	enc=factory.create();
+		int		keySize=enc.getBlockSize(), ivSize=enc.getIVSize();
+		byte[]	key=new byte[keySize], iv=new byte[ivSize];
+		enc.init(Mode.Encrypt, key, iv);
+
+		byte[]	expected=facName.getBytes();
+		byte[]	workBuf=expected.clone();	// need to clone since the cipher works in-line
+		enc.update(workBuf, 0, workBuf.length);
+
+		Cipher	dec=factory.create();
+		dec.init(Mode.Decrypt, key, iv);
+		byte[]	actual=workBuf.clone();
+		dec.update(actual, 0, actual.length);
+
+		Assert.assertArrayEquals(facName, expected, actual);
+	}
+}


[2/2] git commit: [SSHD-358] Create Builders for SShServer and SShClient so they can be extended properly

Posted by gn...@apache.org.
[SSHD-358] Create Builders for SShServer and SShClient so they can be extended properly

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

Branch: refs/heads/master
Commit: 1a1ca8c8827c29909c3021dab8c71d16a299ae03
Parents: ec2bffd
Author: Guillaume Nodet <gn...@apache.org>
Authored: Wed Oct 15 21:41:29 2014 +0200
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Wed Oct 15 23:12:47 2014 +0200

----------------------------------------------------------------------
 .../main/java/org/apache/sshd/SshBuilder.java   | 402 +++++++++++++++++++
 .../main/java/org/apache/sshd/SshClient.java    | 142 +------
 .../main/java/org/apache/sshd/SshServer.java    | 162 +-------
 3 files changed, 422 insertions(+), 284 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1a1ca8c8/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
new file mode 100644
index 0000000..fd4fc54
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java
@@ -0,0 +1,402 @@
+/*
+ * 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.security.InvalidKeyException;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.sshd.client.ServerKeyVerifier;
+import org.apache.sshd.client.keyverifier.AcceptAllServerKeyVerifier;
+import org.apache.sshd.common.AbstractFactoryManager;
+import org.apache.sshd.common.Channel;
+import org.apache.sshd.common.Cipher;
+import org.apache.sshd.common.Compression;
+import org.apache.sshd.common.Factory;
+import org.apache.sshd.common.KeyExchange;
+import org.apache.sshd.common.Mac;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.Random;
+import org.apache.sshd.common.RequestHandler;
+import org.apache.sshd.common.Signature;
+import org.apache.sshd.common.TcpipForwarderFactory;
+import org.apache.sshd.common.cipher.AES128CBC;
+import org.apache.sshd.common.cipher.AES128CTR;
+import org.apache.sshd.common.cipher.AES192CBC;
+import org.apache.sshd.common.cipher.AES256CBC;
+import org.apache.sshd.common.cipher.AES256CTR;
+import org.apache.sshd.common.cipher.ARCFOUR128;
+import org.apache.sshd.common.cipher.ARCFOUR256;
+import org.apache.sshd.common.cipher.BlowfishCBC;
+import org.apache.sshd.common.cipher.TripleDESCBC;
+import org.apache.sshd.common.compression.CompressionNone;
+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.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.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.util.SecurityUtils;
+import org.apache.sshd.server.channel.ChannelSession;
+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;
+
+/**
+ * A builder object for creating SshServer instances.
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class SshBuilder {
+
+    public static ClientBuilder client() {
+        return new ClientBuilder();
+    }
+
+    public static ServerBuilder server() {
+        return new ServerBuilder();
+    }
+
+    static class BaseBuilder<T extends AbstractFactoryManager, S extends BaseBuilder<T, S>> {
+
+        protected Factory<T> factory = null;
+
+        protected List<NamedFactory<KeyExchange>> keyExchangeFactories = null;
+        protected List<NamedFactory<Cipher>> cipherFactories = null;
+        protected List<NamedFactory<Compression>> compressionFactories = null;
+        protected List<NamedFactory<Mac>> macFactories = null;
+        protected List<NamedFactory<Signature>> signatureFactories = null;
+        protected Factory<Random> randomFactory = null;
+        protected List<NamedFactory<Channel>> channelFactories = null;
+        protected FileSystemFactory fileSystemFactory = null;
+        protected TcpipForwarderFactory tcpipForwarderFactory = null;
+        protected List<RequestHandler<ConnectionService>> globalRequestHandlers = null;
+
+        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());
+                }
+                if (randomFactory == null) {
+                    randomFactory = new SingletonRandomFactory(new BouncyCastleRandom.Factory());
+                }
+                // 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());
+                }
+                if (randomFactory == null) {
+                    randomFactory = new SingletonRandomFactory(new JceRandom.Factory());
+                }
+            } else {
+                if (signatureFactories == null) {
+                    signatureFactories = Arrays.asList(
+                            new SignatureDSA.Factory(),
+                            new SignatureRSA.Factory());
+                }
+                if (randomFactory == null) {
+                    randomFactory = new SingletonRandomFactory(new JceRandom.Factory());
+                }
+            }
+
+            if (cipherFactories == null) {
+                cipherFactories = setUpDefaultCiphers();
+            }
+
+            // Compression is not enabled by default
+            //if (compressionFactories == null) {
+            //    compressionFactories = Arrays.<NamedFactory<Compression>>asList(
+            //            new CompressionNone.Factory(),
+            //            new CompressionZlib.Factory(),
+            //            new CompressionDelayedZlib.Factory());
+            //}
+            if (compressionFactories == null) {
+                compressionFactories = Arrays.<NamedFactory<Compression>>asList(
+                        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());
+            }
+            if (fileSystemFactory == null) {
+                fileSystemFactory = new NativeFileSystemFactory();
+            }
+            if (tcpipForwarderFactory == null) {
+                tcpipForwarderFactory = new DefaultTcpipForwarderFactory();
+            }
+
+            return me();
+        }
+
+        public S keyExchangeFactories(List<NamedFactory<KeyExchange>> keyExchangeFactories) {
+            this.keyExchangeFactories = keyExchangeFactories;
+            return me();
+        }
+
+        public S signatureFactories(final List<NamedFactory<Signature>> signatureFactories) {
+            this.signatureFactories = signatureFactories;
+            return me();
+        }
+
+        public S randomFactory(final Factory<Random> randomFactory) {
+            this.randomFactory = randomFactory;
+            return me();
+        }
+
+        public S cipherFactories(final List<NamedFactory<Cipher>> cipherFactories) {
+            this.cipherFactories = cipherFactories;
+            return me();
+        }
+
+        public S compressionFactories(final List<NamedFactory<Compression>> compressionFactories) {
+            this.compressionFactories = compressionFactories;
+            return me();
+        }
+
+        public S macFactories(final List<NamedFactory<Mac>> macFactories) {
+            this.macFactories = macFactories;
+            return me();
+        }
+
+        public S channelFactories(final List<NamedFactory<Channel>> channelFactories) {
+            this.channelFactories = channelFactories;
+            return me();
+        }
+
+        public S fileSystemFactory(final FileSystemFactory fileSystemFactory) {
+            this.fileSystemFactory = fileSystemFactory;
+            return me();
+        }
+
+        public S tcpipForwarderFactory(final TcpipForwarderFactory tcpipForwarderFactory) {
+            this.tcpipForwarderFactory = tcpipForwarderFactory;
+            return me();
+        }
+
+        public S globalRequestHandlers(final List<RequestHandler<ConnectionService>> globalRequestHandlers) {
+            this.globalRequestHandlers = globalRequestHandlers;
+            return me();
+        }
+
+        public S factory(final Factory<T> factory) {
+            this.factory = factory;
+            return me();
+        }
+
+        public T build(final boolean isFillWithDefaultValues) {
+            if (isFillWithDefaultValues) {
+                fillWithDefaultValues();
+            }
+
+            T ssh = factory.create();
+
+            ssh.setKeyExchangeFactories(keyExchangeFactories);
+            ssh.setSignatureFactories(signatureFactories);
+            ssh.setRandomFactory(randomFactory);
+            ssh.setCipherFactories(cipherFactories);
+            ssh.setCompressionFactories(compressionFactories);
+            ssh.setMacFactories(macFactories);
+            ssh.setChannelFactories(channelFactories);
+            ssh.setFileSystemFactory(fileSystemFactory);
+            ssh.setTcpipForwarderFactory(tcpipForwarderFactory);
+            ssh.setGlobalRequestHandlers(globalRequestHandlers);
+
+            return ssh;
+        }
+
+        public T build() {
+            return build(true);
+        }
+
+        @SuppressWarnings("unchecked")
+        protected S me() {
+            return (S) this;
+        }
+
+        protected static List<NamedFactory<Cipher>> setUpDefaultCiphers() {
+            List<NamedFactory<Cipher>> avail = new LinkedList<NamedFactory<Cipher>>();
+            avail.add(new AES128CTR.Factory());
+            avail.add(new AES256CTR.Factory());
+            avail.add(new ARCFOUR128.Factory());
+            avail.add(new ARCFOUR256.Factory());
+            avail.add(new AES128CBC.Factory());
+            avail.add(new TripleDESCBC.Factory());
+            avail.add(new BlowfishCBC.Factory());
+            avail.add(new AES192CBC.Factory());
+            avail.add(new AES256CBC.Factory());
+
+            for (Iterator<NamedFactory<Cipher>> i = avail.iterator(); i.hasNext(); ) {
+                final NamedFactory<Cipher> f = i.next();
+                try {
+                    final Cipher c = f.create();
+                    final byte[] key = new byte[c.getBlockSize()];
+                    final byte[] iv = new byte[c.getIVSize()];
+                    c.init(Cipher.Mode.Encrypt, key, iv);
+                } catch (InvalidKeyException e) {
+                    i.remove();
+                } catch (Exception e) {
+                    i.remove();
+                }
+            }
+            return avail;
+        }
+    }
+
+    /**
+     * SshClient builder
+     */
+    static class ClientBuilder extends BaseBuilder<SshClient, ClientBuilder> {
+
+        protected ServerKeyVerifier serverKeyVerifier;
+
+        @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 (channelFactories == null) {
+                channelFactories = Arrays.<NamedFactory<Channel>>asList(
+                        new TcpipServerChannel.ForwardedTcpipFactory());
+            }
+            if (serverKeyVerifier == null) {
+                serverKeyVerifier = AcceptAllServerKeyVerifier.INSTANCE;
+            }
+            return me();
+        }
+
+        @Override
+        public SshClient build(boolean isFillWithDefaultValues) {
+            SshClient client = super.build(isFillWithDefaultValues);
+            client.setServerKeyVerifier(serverKeyVerifier);
+            return client;
+        }
+    }
+
+    /**
+     * SshServer builder
+     */
+    static class ServerBuilder extends BaseBuilder<SshServer, ServerBuilder> {
+
+        @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 (channelFactories == null) {
+                channelFactories = Arrays.asList(
+                        new ChannelSession.Factory(),
+                        new TcpipServerChannel.DirectTcpipFactory());
+            }
+            if (globalRequestHandlers == null) {
+                globalRequestHandlers = Arrays.asList(
+                        new KeepAliveHandler(),
+                        new NoMoreSessionsHandler(),
+                        new TcpipForwardHandler(),
+                        new CancelTcpipForwardHandler());
+            }
+            return me();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1a1ca8c8/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 ce8b335..6b532e2 100644
--- a/sshd-core/src/main/java/org/apache/sshd/SshClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/SshClient.java
@@ -30,15 +30,11 @@ import java.io.StringWriter;
 import java.io.Writer;
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
-import java.security.InvalidKeyException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
-import java.util.Iterator;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.Callable;
-import java.util.concurrent.Executors;
 import java.util.logging.ConsoleHandler;
 import java.util.logging.Formatter;
 import java.util.logging.Handler;
@@ -57,60 +53,22 @@ import org.apache.sshd.client.auth.UserAuthPublicKey;
 import org.apache.sshd.client.channel.ChannelShell;
 import org.apache.sshd.client.future.ConnectFuture;
 import org.apache.sshd.client.future.DefaultConnectFuture;
-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.client.keyverifier.AcceptAllServerKeyVerifier;
 import org.apache.sshd.client.session.ClientConnectionService;
 import org.apache.sshd.client.session.ClientSessionImpl;
 import org.apache.sshd.client.session.ClientUserAuthService;
 import org.apache.sshd.common.AbstractFactoryManager;
 import org.apache.sshd.common.Channel;
-import org.apache.sshd.common.Cipher;
 import org.apache.sshd.common.Closeable;
-import org.apache.sshd.common.Compression;
 import org.apache.sshd.common.Factory;
-import org.apache.sshd.common.KeyExchange;
 import org.apache.sshd.common.KeyPairProvider;
-import org.apache.sshd.common.Mac;
 import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.Signature;
-import org.apache.sshd.common.cipher.AES128CBC;
-import org.apache.sshd.common.cipher.AES128CTR;
-import org.apache.sshd.common.cipher.AES192CBC;
-import org.apache.sshd.common.cipher.AES256CBC;
-import org.apache.sshd.common.cipher.AES256CTR;
-import org.apache.sshd.common.cipher.ARCFOUR128;
-import org.apache.sshd.common.cipher.ARCFOUR256;
-import org.apache.sshd.common.cipher.BlowfishCBC;
-import org.apache.sshd.common.cipher.TripleDESCBC;
-import org.apache.sshd.common.compression.CompressionNone;
-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.future.CloseFuture;
 import org.apache.sshd.common.future.SshFutureListener;
 import org.apache.sshd.common.io.DefaultIoServiceFactoryFactory;
 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.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.random.BouncyCastleRandom;
-import org.apache.sshd.common.random.JceRandom;
-import org.apache.sshd.common.random.SingletonRandomFactory;
 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.util.CloseableUtils;
 import org.apache.sshd.common.util.NoCloseInputStream;
 import org.apache.sshd.common.util.NoCloseOutputStream;
@@ -166,10 +124,15 @@ import org.bouncycastle.openssl.PasswordFinder;
  */
 public class SshClient extends AbstractFactoryManager implements ClientFactoryManager, Closeable {
 
+    public static final Factory<SshClient> DEFAULT_SSH_CLIENT_FACTORY = new Factory<SshClient>() {
+        public SshClient create() {
+            return new SshClient();
+        }
+    };
+
     protected IoConnector connector;
     protected SessionFactory sessionFactory;
     protected UserInteraction userInteraction;
-    protected Factory<IoConnector> connectorFactory;
     protected List<NamedFactory<UserAuth>> userAuthFactories;
 
     private ServerKeyVerifier serverKeyVerifier;
@@ -369,95 +332,10 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
      * @return a newly create SSH client
      */
     public static SshClient setUpDefaultClient() {
-        SshClient client = new SshClient();
-        // DHG14 uses 2048 bits key which are not supported by the default JCE provider
-        if (SecurityUtils.isBouncyCastleRegistered()) {
-            client.setKeyExchangeFactories(Arrays.<NamedFactory<KeyExchange>>asList(
-                    new DHGEX256.Factory(),
-                    new DHGEX.Factory(),
-                    new ECDHP256.Factory(),
-                    new ECDHP384.Factory(),
-                    new ECDHP521.Factory(),
-                    new DHG14.Factory(),
-                    new DHG1.Factory()));
-            client.setSignatureFactories(Arrays.<NamedFactory<Signature>>asList(
-                    new SignatureDSA.Factory(),
-                    new SignatureRSA.Factory(),
-                    new SignatureECDSA.NISTP256Factory(),
-                    new SignatureECDSA.NISTP384Factory(),
-                    new SignatureECDSA.NISTP521Factory()));
-            client.setRandomFactory(new SingletonRandomFactory(new BouncyCastleRandom.Factory()));
-        // EC keys are not supported until OpenJDK 7
-        } else if (SecurityUtils.hasEcc()) {
-            client.setKeyExchangeFactories(Arrays.<NamedFactory<KeyExchange>>asList(
-                    new ECDHP256.Factory(),
-                    new ECDHP384.Factory(),
-                    new ECDHP521.Factory(),
-                    new DHG1.Factory()));
-            client.setSignatureFactories(Arrays.<NamedFactory<Signature>>asList(
-                    new SignatureDSA.Factory(),
-                    new SignatureRSA.Factory(),
-                    new SignatureECDSA.NISTP256Factory(),
-                    new SignatureECDSA.NISTP384Factory(),
-                    new SignatureECDSA.NISTP521Factory()));
-            client.setRandomFactory(new SingletonRandomFactory(new JceRandom.Factory()));
-        } else {
-            client.setKeyExchangeFactories(Arrays.<NamedFactory<KeyExchange>>asList(
-                    new DHG1.Factory()));
-            client.setSignatureFactories(Arrays.<NamedFactory<Signature>>asList(
-                    new SignatureDSA.Factory(),
-                    new SignatureRSA.Factory()));
-            client.setRandomFactory(new SingletonRandomFactory(new JceRandom.Factory()));
-        }
-        setUpDefaultCiphers(client);
-        // Compression is not enabled by default
-        // client.setCompressionFactories(Arrays.<NamedFactory<Compression>>asList(
-        //         new CompressionNone.Factory(),
-        //         new CompressionZlib.Factory(),
-        //         new CompressionDelayedZlib.Factory()));
-        client.setCompressionFactories(Arrays.<NamedFactory<Compression>>asList(
-                new CompressionNone.Factory()));
-        client.setMacFactories(Arrays.<NamedFactory<Mac>>asList(
-                new HMACSHA256.Factory(),
-                new HMACSHA512.Factory(),
-                new HMACSHA1.Factory(),
-                new HMACMD5.Factory(),
-                new HMACSHA196.Factory(),
-                new HMACMD596.Factory()));
-        client.setChannelFactories(Arrays.<NamedFactory<Channel>>asList(
-                new TcpipServerChannel.ForwardedTcpipFactory()));
-        client.setServerKeyVerifier(AcceptAllServerKeyVerifier.INSTANCE);
-        client.setFileSystemFactory(new NativeFileSystemFactory());
-        client.setTcpipForwarderFactory(new DefaultTcpipForwarderFactory());
-        return client;
-    }
-
-    private static void setUpDefaultCiphers(SshClient client) {
-        List<NamedFactory<Cipher>> avail = new LinkedList<NamedFactory<Cipher>>();
-        avail.add(new AES128CTR.Factory());
-        avail.add(new AES256CTR.Factory());
-        avail.add(new ARCFOUR128.Factory());
-        avail.add(new ARCFOUR256.Factory());
-        avail.add(new AES128CBC.Factory());
-        avail.add(new TripleDESCBC.Factory());
-        avail.add(new BlowfishCBC.Factory());
-        avail.add(new AES192CBC.Factory());
-        avail.add(new AES256CBC.Factory());
-
-        for (Iterator<NamedFactory<Cipher>> i = avail.iterator(); i.hasNext();) {
-            final NamedFactory<Cipher> f = i.next();
-            try {
-                final Cipher c = f.create();
-                final byte[] key = new byte[c.getBlockSize()];
-                final byte[] iv = new byte[c.getIVSize()];
-                c.init(Cipher.Mode.Encrypt, key, iv);
-            } catch (InvalidKeyException e) {
-                i.remove();
-            } catch (Exception e) {
-                i.remove();
-            }
-        }
-        client.setCipherFactories(avail);
+        return SshBuilder
+                .client()
+                .factory(DEFAULT_SSH_CLIENT_FACTORY)
+                .build();
     }
 
     /*=================================

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1a1ca8c8/sshd-core/src/main/java/org/apache/sshd/SshServer.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/SshServer.java b/sshd-core/src/main/java/org/apache/sshd/SshServer.java
index 5aa8736..b60fe65 100644
--- a/sshd-core/src/main/java/org/apache/sshd/SshServer.java
+++ b/sshd-core/src/main/java/org/apache/sshd/SshServer.java
@@ -21,70 +21,30 @@ package org.apache.sshd;
 import java.io.IOException;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
-import java.security.InvalidKeyException;
 import java.security.PublicKey;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.EnumSet;
-import java.util.Iterator;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.sshd.common.AbstractFactoryManager;
-import org.apache.sshd.common.Channel;
-import org.apache.sshd.common.Cipher;
 import org.apache.sshd.common.Closeable;
-import org.apache.sshd.common.Compression;
 import org.apache.sshd.common.Factory;
 import org.apache.sshd.common.ForwardingFilter;
-import org.apache.sshd.common.RequestHandler;
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.Mac;
 import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.Session;
-import org.apache.sshd.common.Signature;
 import org.apache.sshd.common.SshdSocketAddress;
-import org.apache.sshd.common.cipher.AES128CBC;
-import org.apache.sshd.common.cipher.AES128CTR;
-import org.apache.sshd.common.cipher.AES192CBC;
-import org.apache.sshd.common.cipher.AES256CBC;
-import org.apache.sshd.common.cipher.AES256CTR;
-import org.apache.sshd.common.cipher.ARCFOUR128;
-import org.apache.sshd.common.cipher.ARCFOUR256;
-import org.apache.sshd.common.cipher.BlowfishCBC;
-import org.apache.sshd.common.cipher.TripleDESCBC;
-import org.apache.sshd.common.compression.CompressionNone;
-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.future.CloseFuture;
-import org.apache.sshd.common.future.SshFuture;
-import org.apache.sshd.common.future.SshFutureListener;
 import org.apache.sshd.common.io.DefaultIoServiceFactoryFactory;
 import org.apache.sshd.common.io.IoAcceptor;
 import org.apache.sshd.common.io.IoServiceFactory;
 import org.apache.sshd.common.io.IoSession;
 import org.apache.sshd.common.io.mina.MinaServiceFactory;
 import org.apache.sshd.common.io.nio2.Nio2ServiceFactory;
-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.random.BouncyCastleRandom;
-import org.apache.sshd.common.random.JceRandom;
-import org.apache.sshd.common.random.SingletonRandomFactory;
 import org.apache.sshd.common.session.AbstractSession;
-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.util.CloseableUtils;
-import org.apache.sshd.common.util.IoUtils;
 import org.apache.sshd.common.util.OsUtils;
 import org.apache.sshd.common.util.SecurityUtils;
 import org.apache.sshd.common.util.ThreadUtils;
@@ -99,19 +59,7 @@ import org.apache.sshd.server.auth.UserAuthPassword;
 import org.apache.sshd.server.auth.UserAuthPublicKey;
 import org.apache.sshd.server.auth.gss.GSSAuthenticator;
 import org.apache.sshd.server.auth.gss.UserAuthGSS;
-import org.apache.sshd.server.channel.ChannelSession;
 import org.apache.sshd.server.command.ScpCommandFactory;
-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.DHG1;
-import org.apache.sshd.server.kex.DHG14;
-import org.apache.sshd.server.kex.DHGEX;
-import org.apache.sshd.server.kex.DHGEX256;
-import org.apache.sshd.server.kex.ECDHP256;
-import org.apache.sshd.server.kex.ECDHP384;
-import org.apache.sshd.server.kex.ECDHP521;
 import org.apache.sshd.server.keyprovider.PEMGeneratorHostKeyProvider;
 import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
 import org.apache.sshd.server.session.ServerConnectionService;
@@ -147,6 +95,12 @@ import org.apache.sshd.server.shell.ProcessShellFactory;
  */
 public class SshServer extends AbstractFactoryManager implements ServerFactoryManager, Closeable {
 
+    public static final Factory<SshServer> DEFAULT_SSH_SERVER_FACTORY = new Factory<SshServer>() {
+        public SshServer create() {
+            return new SshServer();
+        }
+    };
+
     protected IoAcceptor acceptor;
     protected String host;
     protected int port;
@@ -442,106 +396,10 @@ public class SshServer extends AbstractFactoryManager implements ServerFactoryMa
     }
 
     public static SshServer setUpDefaultServer() {
-        SshServer sshd = new SshServer();
-        // DHG14 uses 2048 bits key which are not supported by the default JCE provider
-        // EC keys are not supported until OpenJDK 8
-        if (SecurityUtils.isBouncyCastleRegistered()) {
-            sshd.setKeyExchangeFactories(Arrays.<NamedFactory<KeyExchange>>asList(
-                    new DHGEX256.Factory(),
-                    new DHGEX.Factory(),
-                    new ECDHP256.Factory(),
-                    new ECDHP384.Factory(),
-                    new ECDHP521.Factory(),
-                    new DHG14.Factory(),
-                    new DHG1.Factory()));
-            sshd.setSignatureFactories(Arrays.<NamedFactory<Signature>>asList(
-                    new SignatureECDSA.NISTP256Factory(),
-                    new SignatureECDSA.NISTP384Factory(),
-                    new SignatureECDSA.NISTP521Factory(),
-                    new SignatureDSA.Factory(),
-                    new SignatureRSA.Factory()));
-            sshd.setRandomFactory(new SingletonRandomFactory(new BouncyCastleRandom.Factory()));
-        // EC keys are not supported until OpenJDK 7
-        } else if (SecurityUtils.hasEcc()) {
-            sshd.setKeyExchangeFactories(Arrays.<NamedFactory<KeyExchange>>asList(
-                    new DHGEX256.Factory(),
-                    new DHGEX.Factory(),
-                    new ECDHP256.Factory(),
-                    new ECDHP384.Factory(),
-                    new ECDHP521.Factory(),
-                    new DHG1.Factory()));
-            sshd.setSignatureFactories(Arrays.<NamedFactory<Signature>>asList(
-                    new SignatureECDSA.NISTP256Factory(),
-                    new SignatureECDSA.NISTP384Factory(),
-                    new SignatureECDSA.NISTP521Factory(),
-                    new SignatureDSA.Factory(),
-                    new SignatureRSA.Factory()));
-            sshd.setRandomFactory(new SingletonRandomFactory(new JceRandom.Factory()));
-        } else {
-            sshd.setKeyExchangeFactories(Arrays.<NamedFactory<KeyExchange>>asList(
-                    new DHGEX256.Factory(),
-                    new DHGEX.Factory(),
-                    new DHG1.Factory()));
-            sshd.setSignatureFactories(Arrays.<NamedFactory<Signature>>asList(
-                    new SignatureDSA.Factory(),
-                    new SignatureRSA.Factory()));
-            sshd.setRandomFactory(new SingletonRandomFactory(new JceRandom.Factory()));
-        }
-        setUpDefaultCiphers(sshd);
-        // Compression is not enabled by default
-        // sshd.setCompressionFactories(Arrays.<NamedFactory<Compression>>asList(
-        //         new CompressionNone.Factory(),
-        //         new CompressionZlib.Factory(),
-        //         new CompressionDelayedZlib.Factory()));
-        sshd.setCompressionFactories(Arrays.<NamedFactory<Compression>>asList(
-                new CompressionNone.Factory()));
-        sshd.setMacFactories(Arrays.<NamedFactory<Mac>>asList(
-                new HMACSHA256.Factory(),
-                new HMACSHA512.Factory(),
-                new HMACSHA1.Factory(),
-                new HMACMD5.Factory(),
-                new HMACSHA196.Factory(),
-                new HMACMD596.Factory()));
-        sshd.setChannelFactories(Arrays.<NamedFactory<Channel>>asList(
-                new ChannelSession.Factory(),
-                new TcpipServerChannel.DirectTcpipFactory()));
-        sshd.setFileSystemFactory(new NativeFileSystemFactory());
-        sshd.setTcpipForwarderFactory(new DefaultTcpipForwarderFactory());
-        sshd.setGlobalRequestHandlers(Arrays.<RequestHandler<ConnectionService>>asList(
-                new KeepAliveHandler(),
-                new NoMoreSessionsHandler(),
-                new TcpipForwardHandler(),
-                new CancelTcpipForwardHandler()
-        ));
-        return sshd;
-    }
-
-    private static void setUpDefaultCiphers(SshServer sshd) {
-        List<NamedFactory<Cipher>> avail = new LinkedList<NamedFactory<Cipher>>();
-        avail.add(new AES128CTR.Factory());
-        avail.add(new AES256CTR.Factory());
-        avail.add(new ARCFOUR128.Factory());
-        avail.add(new ARCFOUR256.Factory());
-        avail.add(new AES128CBC.Factory());
-        avail.add(new TripleDESCBC.Factory());
-        avail.add(new BlowfishCBC.Factory());
-        avail.add(new AES192CBC.Factory());
-        avail.add(new AES256CBC.Factory());
-
-        for (Iterator<NamedFactory<Cipher>> i = avail.iterator(); i.hasNext();) {
-            final NamedFactory<Cipher> f = i.next();
-            try {
-                final Cipher c = f.create();
-                final byte[] key = new byte[c.getBlockSize()];
-                final byte[] iv = new byte[c.getIVSize()];
-                c.init(Cipher.Mode.Encrypt, key, iv);
-            } catch (InvalidKeyException e) {
-                i.remove();
-            } catch (Exception e) {
-                i.remove();
-            }
-        }
-        sshd.setCipherFactories(avail);
+        return SshBuilder
+                .server()
+                .factory(DEFAULT_SSH_SERVER_FACTORY)
+                .build();
     }
 
     /*=================================