Netty Diffie-Hellman Key Exchange Server

    From: manish_iitg <excellencetechnologies08@gmail.com>
    Subject: Diffie-Hellman Key Exchange Server
    To: netty-users@lists.jboss.org
    Reply-To: netty-users@lists.jboss.org
    Date: Tue, 9 Dec 2008 22:51:22 +0900 (KST)

     

    Hello,

     

    I am new to netty, and i am working on a big project which uses netty.  I just wanted to share a piece of code that i have written.

     

    This is client server application, in which both client and server agree upon a Secret Key for Encrypting Data.

     

     

    I just wanted to share this code with you, so that you guys can comment on the implementation and help me improve it. I think newbies to netty learn a lot if we share the way we implement netty for various problems.

     

    // Code for Encryption Client
    import java.net.InetSocketAddress;
    import java.util.concurrent.Executors;
    
    import org.jboss.netty.bootstrap.ClientBootstrap;
    import org.jboss.netty.channel.ChannelFactory;
    import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
    
    public class EncryptionClient {
        public static int PORT = 9091;
    
        public void createClient() {
            ChannelFactory factor = new NioClientSocketChannelFactory(
                    Executors.newCachedThreadPool(), Executors.newCachedThreadPool());
            ClientBootstrap client = new ClientBootstrap(factor);
            client.getPipeline().addLast("handler", new EncryptionClientHandler());
            client.setOption("tcpNoDelay", true);
            client.setOption("keepAlive", true);
            client.connect(new InetSocketAddress("127.0.0.1", PORT));
            System.out.println("Encryption Client Created");
        }
    }
    

     

    // Code for client side handler
    import java.security.KeyFactory;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.PublicKey;
    import java.security.spec.X509EncodedKeySpec;
    
    import javax.crypto.KeyAgreement;
    import javax.crypto.SecretKey;
    
    import org.jboss.netty.buffer.ChannelBuffer;
    import org.jboss.netty.buffer.ChannelBuffers;
    import org.jboss.netty.channel.ChannelHandlerContext;
    import org.jboss.netty.channel.ChannelPipelineCoverage;
    import org.jboss.netty.channel.ChannelStateEvent;
    import org.jboss.netty.channel.ExceptionEvent;
    import org.jboss.netty.channel.MessageEvent;
    import org.jboss.netty.channel.SimpleChannelHandler;
    
    import com.excel.encrypt.Skip;
    
    @ChannelPipelineCoverage("one")
    public class EncryptionClientHandler extends SimpleChannelHandler {
    
        private KeyPairGenerator kpg;
        private KeyPair keyPair;
        private KeyFactory kf;
    
        @Override
        public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
                throws Exception {
    
            // When connection is established with server, the client send it's generated public key
            try {
                kpg = KeyPairGenerator.getInstance("DH");
                KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH");
                kpg.initialize(Skip.sDHParameterSpec);
                keyPair = kpg.genKeyPair();
                byte p[] = keyPair.getPublic().getEncoded();
                ChannelBuffer buffer = ChannelBuffers.wrappedBuffer(p);
                e.getChannel().write(buffer);
                System.out.println("Client Sent Key");
            } catch (Exception ee) {
                ee.printStackTrace();
            }
        }
    
        @Override
        public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
                throws Exception {
    
            // When the client receives the server's public key, it calculates the public key
            ChannelBuffer buffer = (ChannelBuffer) e.getMessage();
            if (buffer.capacity() < 1024) {
                System.out.println("return");
                return;
            } else {
                System.out.println("client recieved key");
                kf = KeyFactory.getInstance("DH");
                byte b[] = new byte[buffer.capacity()];
                buffer.getBytes(0, b);
                X509EncodedKeySpec x509Spec = new X509EncodedKeySpec(b);
                PublicKey theirPublicKey = kf.generatePublic(x509Spec);
                byte keyBytes[] = keyPair.getPublic().getEncoded();
                ChannelBuffer buffer2 = ChannelBuffers.wrappedBuffer(keyBytes);
                e.getChannel().write(buffer2);
    
                KeyAgreement ka = KeyAgreement.getInstance("DH");
                ka.init(keyPair.getPrivate());
                ka.doPhase(theirPublicKey, true);
                SecretKey secretKey = ka.generateSecret("Blowfish");
                System.out.println("client key "
                        + new String(secretKey.getEncoded()));
                System.out.println("client key Length"
                        + secretKey.getEncoded().length);
                e.getChannel().close();
    
            }
        }
    
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
                throws Exception {
            System.out.println("client exception");
            e.getCause().printStackTrace();
        }
    }
    

     

    // Code for server
    import java.net.InetSocketAddress;
    import java.util.concurrent.Executors;
    
    import org.jboss.netty.bootstrap.ServerBootstrap;
    import org.jboss.netty.channel.ChannelFactory;
    import org.jboss.netty.channel.ChannelPipelineCoverage;
    import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
    import org.jboss.netty.handler.execution.ExecutionHandler;
    import org.jboss.netty.handler.execution.MemoryAwareThreadPoolExecutor;
    
    @ChannelPipelineCoverage("all")
    public class EncryptionServer {
        public static int PORT = 9091;
    
        public void createServer() {
            ChannelFactory factory = new NioServerSocketChannelFactory(
                    Executors.newCachedThreadPool(), Executors.newCachedThreadPool());
            ServerBootstrap server = new ServerBootstrap(factory);
            server.getPipeline().addLast(
                    "executor",
                    new ExecutionHandler(
                            new MemoryAwareThreadPoolExecutor(16, 0, 0)));
            server.getPipeline().addLast("handler",
                    new EncryptionServerRequestHandler());
            server.setOption("child.tcpNoDelay", true);
            server.setOption("child.keepAlive", true);
            server.bind(new InetSocketAddress(PORT));
            System.out.println("Encryption Server Created");
        }
    }
    

     

    // Code for client side handler
    import java.security.KeyFactory;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.PublicKey;
    import java.security.spec.X509EncodedKeySpec;
    
    import javax.crypto.KeyAgreement;
    import javax.crypto.SecretKey;
    
    import org.jboss.netty.buffer.ChannelBuffer;
    import org.jboss.netty.buffer.ChannelBuffers;
    import org.jboss.netty.channel.ChannelFuture;
    import org.jboss.netty.channel.ChannelFutureListener;
    import org.jboss.netty.channel.ChannelHandlerContext;
    import org.jboss.netty.channel.ChannelPipelineCoverage;
    import org.jboss.netty.channel.ExceptionEvent;
    import org.jboss.netty.channel.MessageEvent;
    import org.jboss.netty.channel.SimpleChannelHandler;
    
    import com.excel.encrypt.Skip;
    
    @ChannelPipelineCoverage("all")
    public class EncryptionServerRequestHandler extends SimpleChannelHandler {
    
        @Override
        public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
                throws Exception {
    
            // The server receives the client's public key and generates it's Secret Key.
            // Also the server sends back it's public as well to the client.
            ChannelBuffer buffer = (ChannelBuffer) e.getMessage();
            if (buffer.capacity() < 1024) {
                System.out.println("Server Returned");
                return;
            } else {
                System.out.println("Server Received Key");
                KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH");
                kpg.initialize(Skip.sDHParameterSpec);
                KeyPair keyPair = kpg.genKeyPair();
                KeyFactory kf = KeyFactory.getInstance("DH");
                byte b[] = new byte[buffer.capacity()];
                buffer.getBytes(0, b);
                X509EncodedKeySpec x509Spec = new X509EncodedKeySpec(b);
                PublicKey theirPublicKey = kf.generatePublic(x509Spec);
                byte keyBytes[] = keyPair.getPublic().getEncoded();
                ChannelBuffer buffer2 = ChannelBuffers.wrappedBuffer(keyBytes);
                ChannelFuture cf = e.getChannel().write(buffer2);
    
                KeyAgreement ka = KeyAgreement.getInstance("DH");
                ka.init(keyPair.getPrivate());
                ka.doPhase(theirPublicKey, true);
                SecretKey secretKey = ka.generateSecret("Blowfish");
                System.out.println("Server key "
                        + new String(secretKey.getEncoded()));
                System.out.println("Server key Length"
                        + secretKey.getEncoded().length);
    
            }
        }
    
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
                throws Exception {
            System.out.println("server");
            e.getCause().printStackTrace();
        }
    }