Quantcast
Channel: Akka Libraries - Discussion Forum for Akka technologies
Viewing all articles
Browse latest Browse all 1367

TLS SSL TCP Actor

$
0
0

Hello there

I am trying to implement ssl encryption with tcp server socket. I could achieve it using streams but I am not sure how to achieve it using Actors. For now I am using sslengine.unwrap on the Received.class object I received. Unfortunately I am unable to figure out how to read the decrypted text. Any help or advice will be appreciated.

import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManagerFactory;

import org.apache.logging.log4j.*;
import akka.actor.*;
import akka.io.Tcp.*;
import akka.stream.TLSRole;
import akka.io.TcpMessage;
import akka.util.ByteString;
import scala.concurrent.duration.Duration;


public class TcpConnectionHandlerActor extends AbstractActor {

	private final static Logger log = LogManager.getLogger(TcpConnectionHandlerActor.class); 
	private final String clientIP;
	private ActorRef sender;
	private final SSLEngine engine;
	
	public TcpConnectionHandlerActor(String clientIP) {
		this.clientIP = clientIP;
		this.engine = createSSLEngine(getSSLContext(), TLSRole.server());
	}

	public static Props props(String clientIP) {
		return Props.create(TcpConnectionHandlerActor.class, clientIP);
	}
	
	@Override
	public void preStart() throws Exception {
	    log.trace("=============================START---OF---LOG================================");
		log.trace(getSelf().path().name()+" starting tcp-handler");
	}

	@Override
	public Receive createReceive() {
		return receiveBuilder()
				.match(Received.class, msg->{
					sender = getSender();
					
					ByteBuffer buff = msg.data().asByteBuffer();
                    ByteBuffer dest = ByteBuffer.allocate(2024);
                    try{
                    	engine.beginHandshake();
                    	ByteBuffer inb  = msg.data().toByteBuffer();
                    	ByteBuffer outb = ByteBuffer.allocate(
                    	            engine.getSession().getPacketBufferSize());
                    	inb.put(msg.data().toArray());
                    	//inb.flip();
                    	SSLEngineResult result = engine.unwrap(inb, outb);
                    	log.trace("Wrapped " + outb.position() + " octets ("
                    	                + result + ").");
                    	outb.flip();
                    	log.trace("Cyphertext: " + outb);
                    }catch(SSLException e) {
                    	log.error(e.getMessage());
                    	log.error(e.getCause());
                    	getContext().stop(getSelf());
                    }
                    String sslmessageX = ByteString.fromByteBuffer(dest).utf8String();
					log.info(getSelf().path().name()+" received-tcp: "+ sslmessageX);

				})
				
				.match(String.class, s->{
					if(s.contains("Error")){
						log.info(getSelf().path().name()+" sending out NACK to "+clientIP.toString()+" : "+s);  //if not ack then kill the ips actor
					
					}
					sender.tell(TcpMessage.write(ByteString.fromString(s)), getSelf());
				})
				.match(ReceiveTimeout.class, r -> {
					
					getContext().setReceiveTimeout(Duration.Undefined());
				})
				.match(ConnectionClosed.class, closed->{
					log.debug(getSelf().path().name()+" Server: Connection Closure "+closed);
					getContext().stop(getSelf());
				})
				.match(CommandFailed.class, conn->{
					log.fatal(getSelf().path().name()+" Server: Connection Failed "+conn);
					getContext().stop(getSelf());
				})
				.match(Terminated.class,s->{
				})
				.build();
	}

	@Override
	public void postStop() throws Exception {
		log.trace(getSelf().path().name()+" stopping tcp-handler");
		log.trace("=============================END---OF---LOG================================");
	}
	
	 private static SSLContext getSSLContext(){
		  SSLContext context;
	    try {
	      // Don't hardcode your password in actual code
	      char[] password = "abcd1234".toCharArray();

	      KeyStore keyStore = KeyStore.getInstance("PKCS12");
	      keyStore.load(new FileInputStream("config/ssl/mykeystore.p12"), password);

	      TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
	      trustManagerFactory.init(keyStore);

	      KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
	      keyManagerFactory.init(keyStore, password);

	      context = SSLContext.getInstance("TLSv1.2");
	      context.init(
	          keyManagerFactory.getKeyManagers(),
	          trustManagerFactory.getTrustManagers(),
	          new SecureRandom());

	    } catch (KeyStoreException
	        | IOException
	        | NoSuchAlgorithmException
	        | CertificateException
	        | UnrecoverableKeyException
	        | KeyManagementException e) {
	      throw new RuntimeException(e);
	    }
	    return context;
	  }

	  private static SSLEngine createSSLEngine(SSLContext context,TLSRole role) {
	    SSLEngine engine = context.createSSLEngine();
	    engine.setUseClientMode(role.equals(akka.stream.TLSRole.client()));
	    engine.setEnabledCipherSuites(new String[] {"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"});
	    engine.setEnabledProtocols(new String[] {"TLSv1.2"});
	    return engine;
	  }
	  
	  
}

7 posts - 3 participants

Read full topic


Viewing all articles
Browse latest Browse all 1367

Trending Articles