Author: gnodet Date: Fri Feb 6 08:39:11 2009 New Revision: 741470 URL: http://svn.apache.org/viewvc?rev=741470&view=rev Log: SSHD-13: Avoid SecureRandom.generateSeed on every SSH connection
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/common/random/SingletonRandomFactory.java mina/sshd/trunk/src/test/java/org/apache/sshd/LoadTest.java Modified: mina/sshd/trunk/src/main/java/org/apache/sshd/SshClient.java mina/sshd/trunk/src/main/java/org/apache/sshd/SshServer.java mina/sshd/trunk/src/test/java/org/apache/sshd/CipherTest.java mina/sshd/trunk/src/test/resources/log4j.properties Modified: mina/sshd/trunk/src/main/java/org/apache/sshd/SshClient.java URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/SshClient.java?rev=741470&r1=741469&r2=741470&view=diff ============================================================================== --- mina/sshd/trunk/src/main/java/org/apache/sshd/SshClient.java (original) +++ mina/sshd/trunk/src/main/java/org/apache/sshd/SshClient.java Fri Feb 6 08:39:11 2009 @@ -56,6 +56,7 @@ import org.apache.sshd.common.mac.HMACSHA196; 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.signature.SignatureDSA; import org.apache.sshd.common.signature.SignatureRSA; import org.apache.sshd.common.util.SecurityUtils; @@ -179,11 +180,11 @@ client.setKeyExchangeFactories(Arrays.<NamedFactory<KeyExchange>>asList( new DHG14.Factory(), new DHG1.Factory())); - client.setRandomFactory(new BouncyCastleRandom.Factory()); + client.setRandomFactory(new SingletonRandomFactory(new BouncyCastleRandom.Factory())); } else { client.setKeyExchangeFactories(Arrays.<NamedFactory<KeyExchange>>asList( new DHG1.Factory())); - client.setRandomFactory(new JceRandom.Factory()); + client.setRandomFactory(new SingletonRandomFactory(new JceRandom.Factory())); } client.setCipherFactories(Arrays.<NamedFactory<Cipher>>asList( new AES128CBC.Factory(), Modified: mina/sshd/trunk/src/main/java/org/apache/sshd/SshServer.java URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/SshServer.java?rev=741470&r1=741469&r2=741470&view=diff ============================================================================== --- mina/sshd/trunk/src/main/java/org/apache/sshd/SshServer.java (original) +++ mina/sshd/trunk/src/main/java/org/apache/sshd/SshServer.java Fri Feb 6 08:39:11 2009 @@ -45,6 +45,7 @@ import org.apache.sshd.common.mac.HMACSHA196; 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.signature.SignatureDSA; import org.apache.sshd.common.signature.SignatureRSA; import org.apache.sshd.common.util.SecurityUtils; @@ -226,11 +227,11 @@ sshd.setKeyExchangeFactories(Arrays.<NamedFactory<KeyExchange>>asList( new DHG14.Factory(), new DHG1.Factory())); - sshd.setRandomFactory(new BouncyCastleRandom.Factory()); + sshd.setRandomFactory(new SingletonRandomFactory(new BouncyCastleRandom.Factory())); } else { sshd.setKeyExchangeFactories(Arrays.<NamedFactory<KeyExchange>>asList( new DHG1.Factory())); - sshd.setRandomFactory(new JceRandom.Factory()); + sshd.setRandomFactory(new SingletonRandomFactory(new JceRandom.Factory())); } sshd.setUserAuthFactories(Arrays.<NamedFactory<UserAuth>>asList( new UserAuthPassword.Factory(), Added: mina/sshd/trunk/src/main/java/org/apache/sshd/common/random/SingletonRandomFactory.java URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/common/random/SingletonRandomFactory.java?rev=741470&view=auto ============================================================================== --- mina/sshd/trunk/src/main/java/org/apache/sshd/common/random/SingletonRandomFactory.java (added) +++ mina/sshd/trunk/src/main/java/org/apache/sshd/common/random/SingletonRandomFactory.java Fri Feb 6 08:39:11 2009 @@ -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.common.random; + +import org.apache.sshd.common.Random; +import org.apache.sshd.common.NamedFactory; + +/** + * A random factory wrapper that uses a single random instance. + * The underlying random instance has to be thread safe. + * + * @author <a href="mailto:d...@mina.apache.org">Apache MINA SSHD Project</a> + * @version $Rev: 728050 $, $Date: 2008-12-19 16:50:58 +0100 (Fri, 19 Dec 2008) $ + */ +public class SingletonRandomFactory implements Random, NamedFactory<Random> { + + private final NamedFactory<Random> factory; + private final Random random; + + public SingletonRandomFactory(NamedFactory<Random> factory) { + this.factory = factory; + this.random = factory.create(); + } + + public void fill(byte[] bytes, int start, int len) { + random.fill(bytes, start, len); + } + + public String getName() { + return factory.getName(); + } + + public Random create() { + return this; + } +} Modified: mina/sshd/trunk/src/test/java/org/apache/sshd/CipherTest.java URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/test/java/org/apache/sshd/CipherTest.java?rev=741470&r1=741469&r2=741470&view=diff ============================================================================== --- mina/sshd/trunk/src/test/java/org/apache/sshd/CipherTest.java (original) +++ mina/sshd/trunk/src/test/java/org/apache/sshd/CipherTest.java Fri Feb 6 08:39:11 2009 @@ -34,6 +34,9 @@ import org.apache.sshd.common.cipher.BlowfishCBC; import org.apache.sshd.common.cipher.TripleDESCBC; import org.apache.sshd.common.*; +import org.apache.sshd.common.Cipher; +import org.apache.sshd.common.Random; +import org.apache.sshd.common.random.BouncyCastleRandom; import org.apache.sshd.SshServer; import org.apache.sshd.util.EchoShellFactory; import org.apache.sshd.util.BogusPasswordAuthenticator; @@ -83,6 +86,32 @@ 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); + } + + protected void loadTest(NamedFactory<Cipher> factory, Random random) throws Exception { + Cipher cipher = factory.create(); + byte[] key = new byte[cipher.getBlockSize()]; + byte[] iv = new byte[cipher.getIVSize()]; + random.fill(key, 0, key.length); + random.fill(iv, 0, iv.length); + cipher.init(Cipher.Mode.Encrypt, key, iv); + + byte[] input = new byte[cipher.getBlockSize()]; + random.fill(input, 0, input.length); + long t0 = System.currentTimeMillis(); + for (int i = 0; i < 100000; i++) { + cipher.update(input, 0, input.length); + } + long t1 = System.currentTimeMillis(); + System.err.println(factory.getName() + ": " + (t1 - t0) + " ms"); + } + protected void setUp(NamedFactory<org.apache.sshd.common.Cipher> cipher) throws Exception { ServerSocket s = new ServerSocket(0); Added: mina/sshd/trunk/src/test/java/org/apache/sshd/LoadTest.java URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/test/java/org/apache/sshd/LoadTest.java?rev=741470&view=auto ============================================================================== --- mina/sshd/trunk/src/test/java/org/apache/sshd/LoadTest.java (added) +++ mina/sshd/trunk/src/test/java/org/apache/sshd/LoadTest.java Fri Feb 6 08:39:11 2009 @@ -0,0 +1,116 @@ +package org.apache.sshd; + +import java.net.ServerSocket; +import java.io.ByteArrayOutputStream; +import java.io.PipedOutputStream; +import java.io.PipedInputStream; +import java.util.concurrent.CountDownLatch; +import java.util.Arrays; + +import org.junit.Before; +import org.junit.After; +import org.junit.Test; +import org.junit.Assert; +import static org.junit.Assert.assertArrayEquals; +import org.apache.sshd.common.keyprovider.FileKeyPairProvider; +import org.apache.sshd.common.KeyExchange; +import org.apache.sshd.common.NamedFactory; +import org.apache.sshd.common.Cipher; +import org.apache.sshd.common.cipher.AES128CBC; +import org.apache.sshd.common.cipher.TripleDESCBC; +import org.apache.sshd.common.cipher.BlowfishCBC; +import org.apache.sshd.common.cipher.AES192CBC; +import org.apache.sshd.common.cipher.AES256CBC; +import org.apache.sshd.util.EchoShellFactory; +import org.apache.sshd.util.BogusPasswordAuthenticator; +import org.apache.sshd.util.TeePipedOutputStream; +import org.apache.sshd.client.kex.DHG1; + +public class LoadTest { + + private SshServer sshd; + private int port; + + @Before + public void setUp() throws Exception { + ServerSocket s = new ServerSocket(0); + port = s.getLocalPort(); + s.close(); + + sshd = SshServer.setUpDefaultServer(); + sshd.setPort(port); + sshd.setKeyPairProvider(new FileKeyPairProvider(new String[] { "src/test/resources/hostkey.pem" })); + sshd.setShellFactory(new EchoShellFactory()); + sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator()); + sshd.start(); + } + + @After + public void tearDown() throws Exception { + sshd.stop(); + } + + @Test + public void testLoad() throws Exception { + final int nbThreads = 4; + final int nbSessionsPerThread = 4; + final CountDownLatch latch = new CountDownLatch(nbThreads); + + for (int i = 0; i < nbThreads; i++) { + Runnable r = new Runnable() { + public void run() { + try { + testClient(nbSessionsPerThread); + } catch (Throwable t) { + t.printStackTrace(); + } finally { + latch.countDown(); + } + } + }; + new Thread(r).start(); + } + + latch.await(); + } + + protected void testClient(int nbSessionsPerThread) throws Exception { + for (int i = 0; i < nbSessionsPerThread; i++) { + runClient(); + } + } + + protected void runClient() throws Exception { + SshClient client = SshClient.setUpDefaultClient(); + client.setKeyExchangeFactories(Arrays.<NamedFactory<KeyExchange>>asList( + new DHG1.Factory())); + client.setCipherFactories(Arrays.<NamedFactory<Cipher>>asList( + new BlowfishCBC.Factory())); + client.start(); + ClientSession session = client.connect("localhost", port).await().getSession(); + session.authPassword("sshd", "sshd").await().isSuccess(); + + ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL); + ByteArrayOutputStream sent = new ByteArrayOutputStream(); + PipedOutputStream pipedIn = new TeePipedOutputStream(sent); + channel.setIn(new PipedInputStream(pipedIn)); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ByteArrayOutputStream err = new ByteArrayOutputStream(); + channel.setOut(out); + channel.setErr(err); + channel.open(); + + pipedIn.write("this is my command\n".getBytes()); + pipedIn.flush(); + + pipedIn.write("exit\n".getBytes()); + pipedIn.flush(); + + channel.waitFor(ClientChannel.CLOSED, 0); + + channel.close(false); + client.stop(); + + assertArrayEquals(sent.toByteArray(), out.toByteArray()); + } +} Modified: mina/sshd/trunk/src/test/resources/log4j.properties URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/test/resources/log4j.properties?rev=741470&r1=741469&r2=741470&view=diff ============================================================================== --- mina/sshd/trunk/src/test/resources/log4j.properties (original) +++ mina/sshd/trunk/src/test/resources/log4j.properties Fri Feb 6 08:39:11 2009 @@ -21,7 +21,7 @@ # # The logging properties used during tests.. # -log4j.rootLogger=DEBUG, stdout +log4j.rootLogger=WARN, stdout #log4j.logger.org.apache.mina=TRACE #log4j.logger.org.apache.sshd.common.channel.Window=DEBUG