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 );
}