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 2009/02/06 09:39:12 UTC

svn commit: r741470 - in /mina/sshd/trunk/src: main/java/org/apache/sshd/ main/java/org/apache/sshd/common/random/ test/java/org/apache/sshd/ test/resources/

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:dev@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