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) {