package com.ingotpowered.net.codec; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageCodec; import org.bouncycastle.crypto.BufferedBlockCipher; import org.bouncycastle.crypto.engines.AESFastEngine; import org.bouncycastle.crypto.modes.CFBBlockCipher; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.ParametersWithIV; import java.util.List; public class AesCodec extends ByteToMessageCodec<ByteBuf> { private static final int bufferSize = 1024; private BufferedBlockCipher aesCipherDecoder = new BufferedBlockCipher(new CFBBlockCipher(new AESFastEngine(), 8)); private BufferedBlockCipher aesCipherEncoder = new BufferedBlockCipher(new CFBBlockCipher(new AESFastEngine(), 8)); private byte[] decoderIn; private byte[] decoderOut; private byte[] encoderIn; private byte[] encoderOut; public AesCodec(byte[] iv) { this.aesCipherDecoder.init(false, new ParametersWithIV(new KeyParameter(iv), iv, 0, 16)); this.aesCipherEncoder.init(true, new ParametersWithIV(new KeyParameter(iv), iv, 0, 16)); this.decoderIn = new byte[bufferSize]; this.decoderOut = new byte[this.aesCipherDecoder.getOutputSize(bufferSize)]; this.encoderIn = new byte[bufferSize]; this.encoderOut = new byte[this.aesCipherEncoder.getOutputSize(bufferSize)]; } protected void decode(ChannelHandlerContext context, ByteBuf in, List<Object> out) { ByteBuf buffer = context.alloc().buffer(this.aesCipherDecoder.getOutputSize(in.readableBytes())); int read; while (in.isReadable()) { if (in.readableBytes() > bufferSize) { read = bufferSize; } else { read = in.readableBytes(); } in.readBytes(this.decoderIn, 0, read); read = this.aesCipherDecoder.processBytes(this.decoderIn, 0, read, this.decoderOut, 0); buffer.writeBytes(this.decoderOut, 0, read); } out.add(buffer); } protected void encode(ChannelHandlerContext context, ByteBuf in, ByteBuf out) throws Exception { int read; while (in.isReadable()) { if (in.readableBytes() > bufferSize) { read = bufferSize; } else { read = in.readableBytes(); } in.readBytes(this.encoderIn, 0, read); read = this.aesCipherEncoder.processBytes(this.encoderIn, 0, read, this.encoderOut, 0); out.writeBytes(this.encoderOut, 0, read); } } }