diff --git a/native/src/main/java/com/velocitypowered/natives/encryption/JavaVelocityCipher.java b/native/src/main/java/com/velocitypowered/natives/encryption/JavaVelocityCipher.java index dd732d036..e74480793 100644 --- a/native/src/main/java/com/velocitypowered/natives/encryption/JavaVelocityCipher.java +++ b/native/src/main/java/com/velocitypowered/natives/encryption/JavaVelocityCipher.java @@ -10,10 +10,22 @@ import javax.crypto.spec.IvParameterSpec; import java.security.GeneralSecurityException; public class JavaVelocityCipher implements VelocityCipher { + public static final VelocityCipherFactory FACTORY = new VelocityCipherFactory() { + @Override + public VelocityCipher forEncryption(SecretKey key) throws GeneralSecurityException { + return new JavaVelocityCipher(true, key); + } + + @Override + public VelocityCipher forDecryption(SecretKey key) throws GeneralSecurityException { + return new JavaVelocityCipher(false, key); + } + }; + private final Cipher cipher; private boolean disposed = false; - public JavaVelocityCipher(boolean encrypt, SecretKey key) throws GeneralSecurityException { + private JavaVelocityCipher(boolean encrypt, SecretKey key) throws GeneralSecurityException { this.cipher = Cipher.getInstance("AES/CFB8/NoPadding"); this.cipher.init(encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, key, new IvParameterSpec(key.getEncoded())); } diff --git a/native/src/main/java/com/velocitypowered/natives/encryption/VelocityCipherFactory.java b/native/src/main/java/com/velocitypowered/natives/encryption/VelocityCipherFactory.java new file mode 100644 index 000000000..ea3d6b536 --- /dev/null +++ b/native/src/main/java/com/velocitypowered/natives/encryption/VelocityCipherFactory.java @@ -0,0 +1,10 @@ +package com.velocitypowered.natives.encryption; + +import javax.crypto.SecretKey; +import java.security.GeneralSecurityException; + +public interface VelocityCipherFactory { + VelocityCipher forEncryption(SecretKey key) throws GeneralSecurityException; + + VelocityCipher forDecryption(SecretKey key) throws GeneralSecurityException; +} diff --git a/native/src/main/java/com/velocitypowered/natives/util/Natives.java b/native/src/main/java/com/velocitypowered/natives/util/Natives.java index af26c300f..2c055bd68 100644 --- a/native/src/main/java/com/velocitypowered/natives/util/Natives.java +++ b/native/src/main/java/com/velocitypowered/natives/util/Natives.java @@ -5,6 +5,8 @@ import com.velocitypowered.natives.compression.JavaVelocityCompressor; import com.velocitypowered.natives.compression.NativeVelocityCompressor; import com.velocitypowered.natives.compression.VelocityCompressor; import com.velocitypowered.natives.compression.VelocityCompressorFactory; +import com.velocitypowered.natives.encryption.JavaVelocityCipher; +import com.velocitypowered.natives.encryption.VelocityCipherFactory; import java.io.IOException; import java.nio.file.Files; @@ -46,4 +48,10 @@ public class Natives { new NativeCodeLoader.Variant<>(NativeCodeLoader.ALWAYS, () -> {}, "Java compression", JavaVelocityCompressor.FACTORY) ) ); + + public static final NativeCodeLoader cipher = new NativeCodeLoader<>( + ImmutableList.of( + new NativeCodeLoader.Variant<>(NativeCodeLoader.ALWAYS, () -> {}, "Java cipher", JavaVelocityCipher.FACTORY) + ) + ); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java b/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java index dfbbc3107..cedf2910e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java @@ -54,6 +54,7 @@ public class VelocityServer { public void start() { logger.info("Using {}", Natives.compressor.getLoadedVariant()); + logger.info("Using {}", Natives.cipher.getLoadedVariant()); // Create a key pair logger.info("Booting up Velocity..."); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java index 050d145d5..a5375bf25 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java @@ -2,6 +2,7 @@ package com.velocitypowered.proxy.connection; import com.google.common.base.Preconditions; import com.velocitypowered.natives.compression.VelocityCompressor; +import com.velocitypowered.natives.encryption.VelocityCipherFactory; import com.velocitypowered.natives.util.Natives; import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.protocol.PacketWrapper; @@ -205,8 +206,9 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter { public void enableEncryption(byte[] secret) throws GeneralSecurityException { SecretKey key = new SecretKeySpec(secret, "AES"); - VelocityCipher decryptionCipher = new JavaVelocityCipher(false, key); - VelocityCipher encryptionCipher = new JavaVelocityCipher(true, key); + VelocityCipherFactory factory = Natives.cipher.get(); + VelocityCipher decryptionCipher = factory.forDecryption(key); + VelocityCipher encryptionCipher = factory.forEncryption(key); channel.pipeline().addBefore(FRAME_DECODER, CIPHER_DECODER, new MinecraftCipherDecoder(decryptionCipher)); channel.pipeline().addBefore(FRAME_ENCODER, CIPHER_ENCODER, new MinecraftCipherEncoder(encryptionCipher)); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java index 658b0a21f..e276a12b7 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java @@ -101,6 +101,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation { } public void handleConnectionException(ServerInfo info, Component disconnectReason) { + connectionInFlight = null; if (connectedServer == null || connectedServer.getServerInfo().equals(info)) { // The player isn't yet connected to a server or they are already connected to the server // they're disconnected from.