package com.lightsocks.socks5.handler; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerAdapter; import io.netty.channel.ChannelHandlerContext; import java.util.Random; import com.lightsocks.socks5.Client; import com.lightsocks.socks5.crpt.Icrptor; import com.lightsocks.socks5.crpt.IcrptorImp; import com.lightsocks.socks5.crpt.KeyUtil; public class CRightHandler extends ChannelHandlerAdapter implements ForwardAdapter { private Icrptor decrpt; private Icrptor encrptor; private ChannelHandlerContext ctx; private ForwardAdapter forwardWriter; private volatile boolean isInitEncrptor = false; private volatile boolean close = false; private boolean isInitDecrptor = false; public CRightHandler(ForwardAdapter write) { this.forwardWriter = write; } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { this.ctx = ctx; // ctx.fireChannelActive(); forwardWriter.attach(this); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { if (!isInitDecrptor) { byte[] iv = recvIV(ctx, msg); if (iv != null) { initDecrptor(iv); isInitDecrptor = true; forwardWriter.forwardReadyNotify(); return; } } if (isInitDecrptor) { ByteBuf m = (ByteBuf) msg; int validate = m.readInt(); // read the validate length int length = m.readInt(); // read the content length byte[] content = new byte[length]; m.readBytes(content); m.release(); ByteBuf buf = Unpooled.wrappedBuffer(decrpt.update(content), 0, validate); forwardWriter.forward(buf); } } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { // ctx.fireChannelInactive(); close = true; if (forwardWriter != null) { forwardWriter.closeNotify(); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } public void forward(ByteBuf m) throws Exception { if (!isInitEncrptor) { initEncrptor(); byte[] iv = encrptor.getIv(); write(iv,iv.length); isInitEncrptor = true; } int total = m.readableBytes(); int left = total % Client.AppConfig.getCrptorParam().getKeyLen(); int first = total - left; if (first != 0) { byte[] firstBulk = new byte[first]; m.readBytes(firstBulk); byte[] dst = encrptor.update(firstBulk); if (dst != null) { write(dst,first); } } if (left != 0) { byte[] LeftBulk = new byte[left]; m.readBytes(LeftBulk); byte[] end = new byte[Client.AppConfig.getCrptorParam().getKeyLen()]; for (int i = 0; i < left; i++) { end[i] = LeftBulk[i]; } byte[] dst = encrptor.update(end); if (dst != null) { write(dst,left); } } m.release(); } public void attach(ForwardAdapter target) { } public void forwardReadyNotify() { } public void closeNotify() { if (!close) { close = true; this.ctx.close(); } } private void initEncrptor() throws Exception { byte[] iv = new byte[Client.AppConfig.getCrptorParam().getIvLen()]; Random random1 = new Random(256); random1.nextBytes(iv); encrptor = new IcrptorImp(KeyUtil.evpBytesToKey(Client.AppConfig .getPassword(), Client.AppConfig.getCrptorParam().getKeyLen()), iv, Client.AppConfig.getCrptorParam().getMode(), Client.AppConfig.getCrptorParam().getType(), 0); encrptor.init(); } private void initDecrptor(byte[] iv) throws Exception { decrpt = new IcrptorImp(KeyUtil.evpBytesToKey(Client.AppConfig .getPassword(), Client.AppConfig.getCrptorParam().getKeyLen()), iv, Client.AppConfig.getCrptorParam().getMode(), Client.AppConfig.getCrptorParam().getType(), 1); decrpt.init(); } private void write(byte[] data,int validate) { ByteBuf buf = ctx.alloc().buffer(8 + data.length); buf.writeInt(validate); buf.writeInt(data.length); buf.writeBytes(data); ctx.writeAndFlush(buf); } private byte[] recvIV(ChannelHandlerContext ctx, Object msg) { ByteBuf buf = (ByteBuf) msg; if (buf.readableBytes() < 8) { return null; } int validate = buf.readInt(); // read the validate length buf.readInt(); // read the content length byte[] iv = new byte[validate]; buf.readBytes(iv); buf.release(); return iv; } }