From 66de4c95ef36e3cd6d7874347078ae437119511d Mon Sep 17 00:00:00 2001 From: md_5 Date: Thu, 4 Jul 2013 09:57:27 +1000 Subject: [PATCH] Implement BouncyCastle as the cipher engine. --- proxy/pom.xml | 6 ++++++ .../main/java/net/md_5/bungee/EncryptionUtil.java | 15 +++++++++++---- .../java/net/md_5/bungee/ServerConnector.java | 6 +++--- .../md_5/bungee/connection/InitialHandler.java | 14 ++++---------- .../java/net/md_5/bungee/netty/CipherBase.java | 8 ++++---- .../java/net/md_5/bungee/netty/CipherDecoder.java | 4 ++-- .../java/net/md_5/bungee/netty/CipherEncoder.java | 4 ++-- 7 files changed, 32 insertions(+), 25 deletions(-) diff --git a/proxy/pom.xml b/proxy/pom.xml index 4f10347f..b9052432 100644 --- a/proxy/pom.xml +++ b/proxy/pom.xml @@ -67,6 +67,12 @@ 5.1.24 runtime + + org.bouncycastle + bcprov-jdk15on + 1.49 + compile + org.javassist javassist diff --git a/proxy/src/main/java/net/md_5/bungee/EncryptionUtil.java b/proxy/src/main/java/net/md_5/bungee/EncryptionUtil.java index 2331aa87..86c986ca 100644 --- a/proxy/src/main/java/net/md_5/bungee/EncryptionUtil.java +++ b/proxy/src/main/java/net/md_5/bungee/EncryptionUtil.java @@ -7,16 +7,22 @@ import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; +import java.security.Security; import java.security.spec.X509EncodedKeySpec; import java.util.Arrays; import java.util.Random; import javax.crypto.Cipher; import javax.crypto.SecretKey; -import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import lombok.Getter; import net.md_5.bungee.protocol.packet.PacketFCEncryptionResponse; import net.md_5.bungee.protocol.packet.PacketFDEncryptionRequest; +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 org.bouncycastle.jce.provider.BouncyCastleProvider; /** * Class containing all encryption related methods for the proxy. @@ -31,6 +37,7 @@ public class EncryptionUtil static { + Security.addProvider( new BouncyCastleProvider() ); try { keys = KeyPairGenerator.getInstance( "RSA" ).generateKeyPair(); @@ -64,10 +71,10 @@ public class EncryptionUtil return new SecretKeySpec( cipher.doFinal( resp.getSharedSecret() ), "AES" ); } - public static Cipher getCipher(int opMode, Key shared) throws GeneralSecurityException + public static BufferedBlockCipher getCipher(boolean forEncryption, Key shared) { - Cipher cip = Cipher.getInstance( "AES/CFB8/NoPadding" ); - cip.init( opMode, shared, new IvParameterSpec( shared.getEncoded() ) ); + BufferedBlockCipher cip = new BufferedBlockCipher( new CFBBlockCipher( new AESFastEngine(), 8 ) ); + cip.init( forEncryption, new ParametersWithIV( new KeyParameter( shared.getEncoded() ), shared.getEncoded(), 0, 16 ) ); return cip; } diff --git a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java index 863bbf4d..a06cfbfa 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java @@ -7,7 +7,6 @@ import java.io.DataInput; import java.security.PublicKey; import java.util.Objects; import java.util.Queue; -import javax.crypto.Cipher; import javax.crypto.SecretKey; import lombok.RequiredArgsConstructor; import net.md_5.bungee.api.ChatColor; @@ -39,6 +38,7 @@ import net.md_5.bungee.protocol.packet.PacketFCEncryptionResponse; import net.md_5.bungee.protocol.packet.PacketFDEncryptionRequest; import net.md_5.bungee.protocol.packet.PacketFFKick; import net.md_5.bungee.protocol.packet.forge.Forge1Login; +import org.bouncycastle.crypto.BufferedBlockCipher; @RequiredArgsConstructor public class ServerConnector extends PacketHandler @@ -219,7 +219,7 @@ public class ServerConnector extends PacketHandler ch.write( new PacketFCEncryptionResponse( shared, token ) ); - Cipher encrypt = EncryptionUtil.getCipher( Cipher.ENCRYPT_MODE, secretkey ); + BufferedBlockCipher encrypt = EncryptionUtil.getCipher( true, secretkey ); ch.addBefore( PipelineUtils.PACKET_DECODE_HANDLER, PipelineUtils.ENCRYPT_HANDLER, new CipherEncoder( encrypt ) ); thisState = State.ENCRYPT_RESPONSE; @@ -234,7 +234,7 @@ public class ServerConnector extends PacketHandler { Preconditions.checkState( thisState == State.ENCRYPT_RESPONSE, "Not expecting ENCRYPT_RESPONSE" ); - Cipher decrypt = EncryptionUtil.getCipher( Cipher.DECRYPT_MODE, secretkey ); + BufferedBlockCipher decrypt = EncryptionUtil.getCipher( false, secretkey ); ch.addBefore( PipelineUtils.PACKET_DECODE_HANDLER, PipelineUtils.DECRYPT_HANDLER, new CipherDecoder( decrypt ) ); ch.write( user.getPendingConnection().getForgeLogin() ); diff --git a/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java index e06c3a98..a02fb01f 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java @@ -14,7 +14,6 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.logging.Level; -import javax.crypto.Cipher; import javax.crypto.SecretKey; import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -53,6 +52,7 @@ import net.md_5.bungee.protocol.packet.PacketFDEncryptionRequest; import net.md_5.bungee.protocol.packet.PacketFEPing; import net.md_5.bungee.protocol.packet.PacketFFKick; import net.md_5.bungee.reconnect.AbstractReconnectManager; +import org.bouncycastle.crypto.BufferedBlockCipher; @RequiredArgsConstructor public class InitialHandler extends PacketHandler implements PendingConnection @@ -240,7 +240,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection Preconditions.checkState( thisState == State.ENCRYPT, "Not expecting ENCRYPT" ); sharedKey = EncryptionUtil.getSecret( encryptResponse, request ); - Cipher decrypt = EncryptionUtil.getCipher( Cipher.DECRYPT_MODE, sharedKey ); + BufferedBlockCipher decrypt = EncryptionUtil.getCipher( false, sharedKey ); ch.addBefore( PipelineUtils.PACKET_DECODE_HANDLER, PipelineUtils.DECRYPT_HANDLER, new CipherDecoder( decrypt ) ); if ( BungeeCord.getInstance().config.isOnlineMode() ) @@ -316,14 +316,8 @@ public class InitialHandler extends PacketHandler implements PendingConnection public void run() { unsafe().sendPacket( new PacketFCEncryptionResponse( new byte[ 0 ], new byte[ 0 ] ) ); - try - { - Cipher encrypt = EncryptionUtil.getCipher( Cipher.ENCRYPT_MODE, sharedKey ); - ch.addBefore( PipelineUtils.DECRYPT_HANDLER, PipelineUtils.ENCRYPT_HANDLER, new CipherEncoder( encrypt ) ); - } catch ( GeneralSecurityException ex ) - { - disconnect( "Cipher error: " + Util.exception( ex ) ); - } + BufferedBlockCipher encrypt = EncryptionUtil.getCipher( true, sharedKey ); + ch.addBefore( PipelineUtils.DECRYPT_HANDLER, PipelineUtils.ENCRYPT_HANDLER, new CipherEncoder( encrypt ) ); } } ); } diff --git a/proxy/src/main/java/net/md_5/bungee/netty/CipherBase.java b/proxy/src/main/java/net/md_5/bungee/netty/CipherBase.java index 5679afea..02bdaedd 100644 --- a/proxy/src/main/java/net/md_5/bungee/netty/CipherBase.java +++ b/proxy/src/main/java/net/md_5/bungee/netty/CipherBase.java @@ -2,11 +2,11 @@ package net.md_5.bungee.netty; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; -import javax.crypto.Cipher; import javax.crypto.ShortBufferException; import lombok.AccessLevel; import lombok.NonNull; import lombok.RequiredArgsConstructor; +import org.bouncycastle.crypto.BufferedBlockCipher; /** * Class to expose an @@ -18,7 +18,7 @@ public class CipherBase { @NonNull - private final Cipher cipher; + private final BufferedBlockCipher cipher; private ThreadLocal heapInLocal = new EmptyByteThreadLocal(); private ThreadLocal heapOutLocal = new EmptyByteThreadLocal(); @@ -51,7 +51,7 @@ public class CipherBase byte[] heapIn = bufToByte( in ); ByteBuf heapOut = ctx.alloc().heapBuffer( cipher.getOutputSize( readableBytes ) ); - heapOut.writerIndex( cipher.update( heapIn, 0, readableBytes, heapOut.array(), heapOut.arrayOffset() ) ); + heapOut.writerIndex( cipher.processBytes( heapIn, 0, readableBytes, heapOut.array(), heapOut.arrayOffset() ) ); return heapOut; } @@ -68,6 +68,6 @@ public class CipherBase heapOut = new byte[ outputSize ]; heapOutLocal.set( heapOut ); } - out.writeBytes( heapOut, 0, cipher.update( heapIn, 0, readableBytes, heapOut ) ); + out.writeBytes( heapOut, 0, cipher.processBytes( heapIn, 0, readableBytes, heapOut, 0 ) ); } } diff --git a/proxy/src/main/java/net/md_5/bungee/netty/CipherDecoder.java b/proxy/src/main/java/net/md_5/bungee/netty/CipherDecoder.java index 91fba349..855c69ad 100644 --- a/proxy/src/main/java/net/md_5/bungee/netty/CipherDecoder.java +++ b/proxy/src/main/java/net/md_5/bungee/netty/CipherDecoder.java @@ -4,14 +4,14 @@ import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.MessageList; import io.netty.handler.codec.MessageToMessageDecoder; -import javax.crypto.Cipher; +import org.bouncycastle.crypto.BufferedBlockCipher; public class CipherDecoder extends MessageToMessageDecoder { private final CipherBase cipher; - public CipherDecoder(Cipher cipher) + public CipherDecoder(BufferedBlockCipher cipher) { this.cipher = new CipherBase( cipher ); } diff --git a/proxy/src/main/java/net/md_5/bungee/netty/CipherEncoder.java b/proxy/src/main/java/net/md_5/bungee/netty/CipherEncoder.java index 7e5c0ec6..c300a181 100644 --- a/proxy/src/main/java/net/md_5/bungee/netty/CipherEncoder.java +++ b/proxy/src/main/java/net/md_5/bungee/netty/CipherEncoder.java @@ -3,14 +3,14 @@ package net.md_5.bungee.netty; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; -import javax.crypto.Cipher; +import org.bouncycastle.crypto.BufferedBlockCipher; public class CipherEncoder extends MessageToByteEncoder { private final CipherBase cipher; - public CipherEncoder(Cipher cipher) + public CipherEncoder(BufferedBlockCipher cipher) { this.cipher = new CipherBase( cipher ); }