Refactor encryption to be two step like vanilla. Thanks @LexManos for pointing this out.

This commit is contained in:
md_5 2013-05-03 19:30:54 +10:00
parent 6236cff658
commit 7436621481
4 changed files with 63 additions and 31 deletions

View File

@ -29,9 +29,10 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.LoginEvent; import net.md_5.bungee.api.event.LoginEvent;
import net.md_5.bungee.api.event.PostLoginEvent; import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.event.ProxyPingEvent; import net.md_5.bungee.api.event.ProxyPingEvent;
import net.md_5.bungee.netty.CipherCodec;
import net.md_5.bungee.netty.HandlerBoss; import net.md_5.bungee.netty.HandlerBoss;
import net.md_5.bungee.netty.ChannelWrapper; import net.md_5.bungee.netty.ChannelWrapper;
import net.md_5.bungee.netty.CipherDecoder;
import net.md_5.bungee.netty.CipherEncoder;
import net.md_5.bungee.packet.Packet2Handshake; import net.md_5.bungee.packet.Packet2Handshake;
import net.md_5.bungee.packet.PacketCDClientStatus; import net.md_5.bungee.packet.PacketCDClientStatus;
import net.md_5.bungee.packet.PacketFAPluginMessage; import net.md_5.bungee.packet.PacketFAPluginMessage;
@ -126,6 +127,9 @@ public class InitialHandler extends PacketHandler implements PendingConnection
Preconditions.checkState( thisState == State.ENCRYPT, "Not expecting ENCRYPT" ); Preconditions.checkState( thisState == State.ENCRYPT, "Not expecting ENCRYPT" );
sharedKey = EncryptionUtil.getSecret( encryptResponse, request ); sharedKey = EncryptionUtil.getSecret( encryptResponse, request );
Cipher decrypt = EncryptionUtil.getCipher( Cipher.DECRYPT_MODE, sharedKey );
ch.getHandle().pipeline().addBefore( "decoder", "decrypt", new CipherDecoder( decrypt ) );
if ( BungeeCord.getInstance().config.isOnlineMode() ) if ( BungeeCord.getInstance().config.isOnlineMode() )
{ {
String encName = URLEncoder.encode( InitialHandler.this.getName(), "UTF-8" ); String encName = URLEncoder.encode( InitialHandler.this.getName(), "UTF-8" );
@ -191,12 +195,11 @@ public class InitialHandler extends PacketHandler implements PendingConnection
return; return;
} }
ch.write( new PacketFCEncryptionResponse() );
try try
{ {
Cipher encrypt = EncryptionUtil.getCipher( Cipher.ENCRYPT_MODE, sharedKey ); Cipher encrypt = EncryptionUtil.getCipher( Cipher.ENCRYPT_MODE, sharedKey );
Cipher decrypt = EncryptionUtil.getCipher( Cipher.DECRYPT_MODE, sharedKey ); ch.getHandle().pipeline().addBefore( "decoder", "encrypt", new CipherEncoder( encrypt ) );
ch.write( new PacketFCEncryptionResponse() );
ch.getHandle().pipeline().addBefore( "decoder", "cipher", new CipherCodec( encrypt, decrypt ) );
thisState = InitialHandler.State.LOGIN; thisState = InitialHandler.State.LOGIN;
} catch ( GeneralSecurityException ex ) } catch ( GeneralSecurityException ex )
{ {

View File

@ -1,21 +1,22 @@
package net.md_5.bungee.netty; package net.md_5.bungee.netty;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToByteCodec;
import javax.crypto.Cipher; import javax.crypto.Cipher;
import javax.crypto.ShortBufferException; import javax.crypto.ShortBufferException;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
/** /**
* This class is a complete solution for encrypting and decoding bytes in a * Class to expose an
* Netty stream. It takes two {@link Cipher} instances, used for encryption and * {@link #cipher(io.netty.buffer.ByteBuf, io.netty.buffer.ByteBuf)} method to
* decryption respectively. * aid in the efficient passing of ByteBuffers through a cipher.
*/ */
public class CipherCodec extends ByteToByteCodec @RequiredArgsConstructor
public class CipherBase
{ {
private Cipher encrypt; @NonNull
private Cipher decrypt; private final Cipher cipher;
private ThreadLocal<byte[]> heapInLocal = new EmptyByteThreadLocal(); private ThreadLocal<byte[]> heapInLocal = new EmptyByteThreadLocal();
private ThreadLocal<byte[]> heapOutLocal = new EmptyByteThreadLocal(); private ThreadLocal<byte[]> heapOutLocal = new EmptyByteThreadLocal();
@ -29,25 +30,7 @@ public class CipherCodec extends ByteToByteCodec
} }
} }
public CipherCodec(Cipher encrypt, Cipher decrypt) protected void cipher(ByteBuf in, ByteBuf out) throws ShortBufferException
{
this.encrypt = encrypt;
this.decrypt = decrypt;
}
@Override
public void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception
{
cipher( in, out, encrypt );
}
@Override
public void decode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception
{
cipher( in, out, decrypt );
}
private void cipher(ByteBuf in, ByteBuf out, Cipher cipher) throws ShortBufferException
{ {
byte[] heapIn = heapInLocal.get(); byte[] heapIn = heapInLocal.get();
int readableBytes = in.readableBytes(); int readableBytes = in.readableBytes();

View File

@ -0,0 +1,23 @@
package net.md_5.bungee.netty;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToByteDecoder;
import javax.crypto.Cipher;
public class CipherDecoder extends ByteToByteDecoder
{
private final CipherBase cipher;
public CipherDecoder(Cipher cipher)
{
this.cipher = new CipherBase( cipher );
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception
{
cipher.cipher( in, out );
}
}

View File

@ -0,0 +1,23 @@
package net.md_5.bungee.netty;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToByteEncoder;
import javax.crypto.Cipher;
public class CipherEncoder extends ByteToByteEncoder
{
private final CipherBase cipher;
public CipherEncoder(Cipher cipher)
{
this.cipher = new CipherBase( cipher );
}
@Override
protected void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception
{
cipher.cipher( in, out );
}
}