diff --git a/pom.xml b/pom.xml
index 2a791b0f..3ba88b13 100644
--- a/pom.xml
+++ b/pom.xml
@@ -76,6 +76,11 @@
mendax
1.4.4-SNAPSHOT
+
+ org.bouncycastle
+ bcprov-ext-jdk15on
+ 1.47
+
org.yaml
snakeyaml
diff --git a/src/main/java/net/md_5/bungee/EncryptionUtil.java b/src/main/java/net/md_5/bungee/EncryptionUtil.java
index 35cf0c68..d4ec2b87 100644
--- a/src/main/java/net/md_5/bungee/EncryptionUtil.java
+++ b/src/main/java/net/md_5/bungee/EncryptionUtil.java
@@ -6,7 +6,6 @@ import java.io.InputStreamReader;
import java.math.BigInteger;
import java.net.URL;
import java.net.URLEncoder;
-import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
@@ -16,6 +15,7 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.SecureRandom;
+import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
@@ -25,10 +25,15 @@ import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
-import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import net.md_5.bungee.packet.PacketFCEncryptionResponse;
import net.md_5.bungee.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.
@@ -40,6 +45,11 @@ public class EncryptionUtil
private static final Random random = new Random();
private static KeyPair keys;
+ static
+ {
+ Security.addProvider(new BouncyCastleProvider());
+ }
+
public static PacketFDEncryptionRequest encryptRequest() throws NoSuchAlgorithmException
{
if (keys == null)
@@ -96,16 +106,16 @@ public class EncryptionUtil
return "YES".equals(reply);
}
- public static Cipher getCipher(int opMode, Key shared) throws InvalidAlgorithmParameterException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException
+ 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;
}
public static SecretKey getSecret()
{
- byte[] rand = new byte[16];
+ byte[] rand = new byte[32];
secure.nextBytes(rand);
return new SecretKeySpec(rand, "AES");
}
diff --git a/src/main/java/net/md_5/bungee/InitialHandler.java b/src/main/java/net/md_5/bungee/InitialHandler.java
index c01304ac..b2f54ace 100644
--- a/src/main/java/net/md_5/bungee/InitialHandler.java
+++ b/src/main/java/net/md_5/bungee/InitialHandler.java
@@ -5,9 +5,6 @@ import java.io.OutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
-import javax.crypto.Cipher;
-import javax.crypto.CipherInputStream;
-import javax.crypto.CipherOutputStream;
import javax.crypto.SecretKey;
import net.md_5.bungee.packet.Packet2Handshake;
import net.md_5.bungee.packet.PacketFCEncryptionResponse;
@@ -15,6 +12,8 @@ import net.md_5.bungee.packet.PacketFDEncryptionRequest;
import net.md_5.bungee.packet.PacketFFKick;
import net.md_5.bungee.packet.PacketInputStream;
import net.md_5.bungee.plugin.LoginEvent;
+import org.bouncycastle.crypto.io.CipherInputStream;
+import org.bouncycastle.crypto.io.CipherOutputStream;
public class InitialHandler implements Runnable
{
@@ -67,8 +66,8 @@ public class InitialHandler implements Runnable
}
out.write(new PacketFCEncryptionResponse().getPacket());
- in = new PacketInputStream(new CipherInputStream(socket.getInputStream(), EncryptionUtil.getCipher(Cipher.DECRYPT_MODE, shared)));
- out = new CipherOutputStream(socket.getOutputStream(), EncryptionUtil.getCipher(Cipher.ENCRYPT_MODE, shared));
+ in = new PacketInputStream(new CipherInputStream(socket.getInputStream(), EncryptionUtil.getCipher(false, shared)));
+ out = new CipherOutputStream(socket.getOutputStream(), EncryptionUtil.getCipher(true, shared));
List customPackets = new ArrayList<>();
byte[] custom;
while (Util.getId((custom = in.readPacket())) != 0xCD)
diff --git a/src/main/java/net/md_5/bungee/ServerConnection.java b/src/main/java/net/md_5/bungee/ServerConnection.java
index 975440e2..5fd3fadf 100644
--- a/src/main/java/net/md_5/bungee/ServerConnection.java
+++ b/src/main/java/net/md_5/bungee/ServerConnection.java
@@ -4,9 +4,6 @@ import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.security.PublicKey;
-import javax.crypto.Cipher;
-import javax.crypto.CipherInputStream;
-import javax.crypto.CipherOutputStream;
import javax.crypto.SecretKey;
import net.md_5.bungee.packet.Packet1Login;
import net.md_5.bungee.packet.Packet2Handshake;
@@ -16,6 +13,8 @@ import net.md_5.bungee.packet.PacketFCEncryptionResponse;
import net.md_5.bungee.packet.PacketFDEncryptionRequest;
import net.md_5.bungee.packet.PacketFFKick;
import net.md_5.bungee.packet.PacketInputStream;
+import org.bouncycastle.crypto.io.CipherInputStream;
+import org.bouncycastle.crypto.io.CipherOutputStream;
/**
* Class representing a connection from the proxy to the server; ie upstream.
@@ -59,8 +58,8 @@ public class ServerConnection extends GenericConnection
throw new RuntimeException("Server did not send encryption enable");
}
- in = new PacketInputStream(new CipherInputStream(socket.getInputStream(), EncryptionUtil.getCipher(Cipher.DECRYPT_MODE, myKey)));
- out = new CipherOutputStream(out, EncryptionUtil.getCipher(Cipher.ENCRYPT_MODE, myKey));
+ in = new PacketInputStream(new CipherInputStream(socket.getInputStream(), EncryptionUtil.getCipher(false, myKey)));
+ out = new CipherOutputStream(out, EncryptionUtil.getCipher(true, myKey));
for (byte[] custom : user.loginPackets)
{