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();
    }
}