diff --git a/native/compile-native.sh b/native/compile-native.sh
new file mode 100755
index 000000000..99ba41d2b
--- /dev/null
+++ b/native/compile-native.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+gcc -shared -fPIC -O3 -Werror -I/usr/lib/jvm/default-java/include/ src/main/c/NativeCipherImpl.c -o src/main/resources/native-cipher.so -lcrypto
diff --git a/native/nb-configuration.xml b/native/nb-configuration.xml
new file mode 100644
index 000000000..7e4659240
--- /dev/null
+++ b/native/nb-configuration.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+ project
+ NEW_LINE
+ NEW_LINE
+ NEW_LINE
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+
+
diff --git a/native/pom.xml b/native/pom.xml
new file mode 100644
index 000000000..c6ec0fc52
--- /dev/null
+++ b/native/pom.xml
@@ -0,0 +1,29 @@
+
+
+ 4.0.0
+
+
+ net.md-5
+ bungeecord-parent
+ 1.7-SNAPSHOT
+ ../pom.xml
+
+
+ net.md-5
+ bungeecord-native
+ 1.7-SNAPSHOT
+ jar
+
+ BungeeCord-Native
+ Optional native code to speed up and enhance BungeeCord functionality.
+
+
+
+ io.netty
+ netty-transport
+ ${netty.version}
+ compile
+
+
+
diff --git a/native/src/main/c/NativeCipherImpl.c b/native/src/main/c/NativeCipherImpl.c
new file mode 100644
index 000000000..41884025e
--- /dev/null
+++ b/native/src/main/c/NativeCipherImpl.c
@@ -0,0 +1,56 @@
+#include "net_md_5_bungee_NativeCipherImpl.h"
+#include
+#include
+#include
+#include
+#define BYTE unsigned char
+
+jlong Java_net_md_15_bungee_NativeCipherImpl_init
+(JNIEnv* env, jobject obj, jbyteArray key)
+{
+ AES_KEY *aes_key = malloc(sizeof(AES_KEY));
+
+ jboolean isKeyCopy;
+ BYTE *key_bytes = (*env)->GetByteArrayElements(env, key, &isKeyCopy);
+ int key_length = (*env)->GetArrayLength(env, key) * 8; // in bits
+
+ AES_set_encrypt_key(key_bytes, key_length, aes_key);
+
+ if (isKeyCopy) {
+ (*env)->ReleaseByteArrayElements(env, key, (jbyte*)key_bytes, JNI_ABORT);
+ }
+ return (long) aes_key;
+}
+void Java_net_md_15_bungee_NativeCipherImpl_free
+(JNIEnv* env, jobject obj, jlong key)
+{
+ free((AES_KEY*)key);
+}
+void Java_net_md_15_bungee_NativeCipherImpl_cipher
+(JNIEnv* env, jobject obj, jboolean forEncryption, jlong key, jbyteArray iv, jlong in, jlong out, jint length)
+{
+ AES_KEY *aes_key = (AES_KEY*)key;
+
+ size_t buffer_length = (size_t) length;
+
+ BYTE *input = (BYTE*) in;
+ BYTE *output = (BYTE*) out;
+
+ jboolean isCopy;
+ BYTE *iv_bytes = (*env)->GetByteArrayElements(env, iv, &isCopy);
+
+ AES_cfb8_encrypt(
+ input, // input buffer
+ output, // output buffer
+ buffer_length, // readable bytes
+ aes_key, // encryption key
+ iv_bytes, // IV
+ NULL, // not needed
+ forEncryption ? AES_ENCRYPT : AES_DECRYPT // encryption mode
+ );
+
+ // IV has changed, let's copy it back
+ if (isCopy) {
+ (*env)->ReleaseByteArrayElements(env, iv, (jbyte*)iv_bytes, 0);
+ }
+}
diff --git a/native/src/main/c/net_md_5_bungee_NativeCipherImpl.h b/native/src/main/c/net_md_5_bungee_NativeCipherImpl.h
new file mode 100644
index 000000000..87e30b034
--- /dev/null
+++ b/native/src/main/c/net_md_5_bungee_NativeCipherImpl.h
@@ -0,0 +1,37 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include
+/* Header for class net_md_5_bungee_NativeCipherImpl */
+
+#ifndef _Included_net_md_5_bungee_NativeCipherImpl
+#define _Included_net_md_5_bungee_NativeCipherImpl
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: net_md_5_bungee_NativeCipherImpl
+ * Method: init
+ * Signature: ([B)J
+ */
+JNIEXPORT jlong JNICALL Java_net_md_15_bungee_NativeCipherImpl_init
+ (JNIEnv *, jobject, jbyteArray);
+
+/*
+ * Class: net_md_5_bungee_NativeCipherImpl
+ * Method: free
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_net_md_15_bungee_NativeCipherImpl_free
+ (JNIEnv *, jobject, jlong);
+
+/*
+ * Class: net_md_5_bungee_NativeCipherImpl
+ * Method: cipher
+ * Signature: (ZJ[BJJI)V
+ */
+JNIEXPORT void JNICALL Java_net_md_15_bungee_NativeCipherImpl_cipher
+ (JNIEnv *, jobject, jboolean, jlong, jbyteArray, jlong, jlong, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/native/src/main/java/net/md_5/bungee/BungeeCipher.java b/native/src/main/java/net/md_5/bungee/BungeeCipher.java
new file mode 100644
index 000000000..a165d5ad0
--- /dev/null
+++ b/native/src/main/java/net/md_5/bungee/BungeeCipher.java
@@ -0,0 +1,21 @@
+package net.md_5.bungee;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import javax.crypto.SecretKey;
+import java.security.GeneralSecurityException;
+
+/**
+ * Class to expose cipher methods from either native or fallback Java cipher.
+ */
+public interface BungeeCipher
+{
+
+ void init(boolean forEncryption, SecretKey key) throws GeneralSecurityException;
+
+ void free();
+
+ void cipher(ByteBuf in, ByteBuf out) throws GeneralSecurityException;
+
+ ByteBuf cipher(ChannelHandlerContext ctx, ByteBuf in) throws GeneralSecurityException;
+}
diff --git a/proxy/src/main/java/net/md_5/bungee/netty/CipherBase.java b/native/src/main/java/net/md_5/bungee/FallbackCipher.java
similarity index 65%
rename from proxy/src/main/java/net/md_5/bungee/netty/CipherBase.java
rename to native/src/main/java/net/md_5/bungee/FallbackCipher.java
index 5679afea2..3c9ee0786 100644
--- a/proxy/src/main/java/net/md_5/bungee/netty/CipherBase.java
+++ b/native/src/main/java/net/md_5/bungee/FallbackCipher.java
@@ -1,24 +1,17 @@
-package net.md_5.bungee.netty;
+package net.md_5.bungee;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
-import lombok.AccessLevel;
-import lombok.NonNull;
-import lombok.RequiredArgsConstructor;
+import javax.crypto.spec.IvParameterSpec;
+import java.security.GeneralSecurityException;
-/**
- * Class to expose an
- * {@link #cipher(io.netty.buffer.ByteBuf, io.netty.buffer.ByteBuf)} method to
- * aid in the efficient passing of ByteBuffers through a cipher.
- */
-@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
-public class CipherBase
+public class FallbackCipher implements BungeeCipher
{
- @NonNull
- private final Cipher cipher;
+ private Cipher cipher;
private ThreadLocal heapInLocal = new EmptyByteThreadLocal();
private ThreadLocal heapOutLocal = new EmptyByteThreadLocal();
@@ -32,6 +25,51 @@ public class CipherBase
}
}
+ public FallbackCipher() throws GeneralSecurityException
+ {
+ this.cipher = Cipher.getInstance( "AES/CFB8/NoPadding" );
+ }
+
+ @Override
+ public void init(boolean forEncryption, SecretKey key) throws GeneralSecurityException
+ {
+ int mode = forEncryption ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
+ cipher.init( mode, key, new IvParameterSpec( key.getEncoded() ) );
+ }
+
+ @Override
+ public void cipher(ByteBuf in, ByteBuf out) throws ShortBufferException
+ {
+ int readableBytes = in.readableBytes();
+ byte[] heapIn = bufToByte( in );
+
+ byte[] heapOut = heapOutLocal.get();
+ int outputSize = cipher.getOutputSize( readableBytes );
+ if ( heapOut.length < outputSize )
+ {
+ heapOut = new byte[ outputSize ];
+ heapOutLocal.set( heapOut );
+ }
+ out.writeBytes( heapOut, 0, cipher.update( heapIn, 0, readableBytes, heapOut ) );
+ }
+
+ @Override
+ public ByteBuf cipher(ChannelHandlerContext ctx, ByteBuf in) throws ShortBufferException
+ {
+ int readableBytes = in.readableBytes();
+ byte[] heapIn = bufToByte( in );
+
+ ByteBuf heapOut = ctx.alloc().heapBuffer( cipher.getOutputSize( readableBytes ) );
+ heapOut.writerIndex( cipher.update( heapIn, 0, readableBytes, heapOut.array(), heapOut.arrayOffset() ) );
+
+ return heapOut;
+ }
+
+ @Override
+ public void free()
+ {
+ }
+
private byte[] bufToByte(ByteBuf in)
{
byte[] heapIn = heapInLocal.get();
@@ -44,30 +82,4 @@ public class CipherBase
in.readBytes( heapIn, 0, readableBytes );
return heapIn;
}
-
- protected ByteBuf cipher(ChannelHandlerContext ctx, ByteBuf in) throws ShortBufferException
- {
- int readableBytes = in.readableBytes();
- byte[] heapIn = bufToByte( in );
-
- ByteBuf heapOut = ctx.alloc().heapBuffer( cipher.getOutputSize( readableBytes ) );
- heapOut.writerIndex( cipher.update( heapIn, 0, readableBytes, heapOut.array(), heapOut.arrayOffset() ) );
-
- return heapOut;
- }
-
- protected void cipher(ByteBuf in, ByteBuf out) throws ShortBufferException
- {
- int readableBytes = in.readableBytes();
- byte[] heapIn = bufToByte( in );
-
- byte[] heapOut = heapOutLocal.get();
- int outputSize = cipher.getOutputSize( readableBytes );
- if ( heapOut.length < outputSize )
- {
- heapOut = new byte[ outputSize ];
- heapOutLocal.set( heapOut );
- }
- out.writeBytes( heapOut, 0, cipher.update( heapIn, 0, readableBytes, heapOut ) );
- }
}
diff --git a/native/src/main/java/net/md_5/bungee/NativeCipher.java b/native/src/main/java/net/md_5/bungee/NativeCipher.java
new file mode 100644
index 000000000..41d2d03ad
--- /dev/null
+++ b/native/src/main/java/net/md_5/bungee/NativeCipher.java
@@ -0,0 +1,111 @@
+package net.md_5.bungee;
+
+import com.google.common.io.ByteStreams;
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import lombok.Getter;
+import javax.crypto.SecretKey;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.GeneralSecurityException;
+
+public class NativeCipher implements BungeeCipher
+{
+
+ @Getter
+ private final NativeCipherImpl nativeCipher = new NativeCipherImpl();
+ private boolean forEncryption;
+ private byte[] iv;
+ /*============================================================================*/
+ private static boolean loaded;
+
+ private long pointer;
+
+ public static boolean isSupported()
+ {
+ return "Linux".equals( System.getProperty( "os.name" ) ) && "amd64".equals( System.getProperty( "os.arch" ) );
+ }
+
+ public static boolean load()
+ {
+ if ( !loaded && isSupported() )
+ {
+ try ( InputStream lib = BungeeCipher.class.getClassLoader().getResourceAsStream( "native-cipher.so" ) )
+ {
+ // Else we will create and copy it to a temp file
+ File temp = File.createTempFile( "bungeecord-native-cipher", ".so" );
+ try ( OutputStream outputStream = new FileOutputStream( temp ) )
+ {
+ ByteStreams.copy( lib, outputStream );
+ System.load( temp.getPath() );
+ }
+ loaded = true;
+ } catch ( Throwable t )
+ {
+ }
+ }
+
+ return loaded;
+ }
+
+ public static boolean isLoaded()
+ {
+ return loaded;
+ }
+
+ @Override
+ public void init(boolean forEncryption, SecretKey key) throws GeneralSecurityException
+ {
+ if ( pointer != 0 )
+ {
+ nativeCipher.free( pointer );
+ }
+ this.forEncryption = forEncryption;
+ this.iv = key.getEncoded(); // initialize the IV
+ this.pointer = nativeCipher.init( key.getEncoded() );
+ }
+
+ @Override
+ public void free()
+ {
+ if ( pointer != 0 )
+ {
+ nativeCipher.free( pointer );
+ pointer = 0;
+ }
+ }
+
+ @Override
+ public void cipher(ByteBuf in, ByteBuf out) throws GeneralSecurityException
+ {
+ // Smoke tests
+ in.memoryAddress();
+ out.memoryAddress();
+ // Store how many bytes we can cipher
+ int length = in.readableBytes();
+ // It is important to note that in AES CFB-8 mode, the number of read bytes, is the number of outputted bytes
+ if ( out.writableBytes() < length )
+ {
+ out.capacity( length );
+ }
+ // Cipher the bytes
+ nativeCipher.cipher( forEncryption, pointer, iv, in.memoryAddress() + in.readerIndex(), out.memoryAddress() + out.writerIndex(), length );
+
+ // Go to the end of the buffer, all bytes would of been read
+ in.readerIndex( in.writerIndex() );
+ // Add the number of ciphered bytes to our position
+ out.writerIndex( out.writerIndex() + length );
+ }
+
+ @Override
+ public ByteBuf cipher(ChannelHandlerContext ctx, ByteBuf in) throws GeneralSecurityException
+ {
+ int readableBytes = in.readableBytes();
+ ByteBuf heapOut = ctx.alloc().directBuffer( readableBytes ); // CFB8
+ cipher( in, heapOut );
+
+ return heapOut;
+ }
+}
diff --git a/native/src/main/java/net/md_5/bungee/NativeCipherImpl.java b/native/src/main/java/net/md_5/bungee/NativeCipherImpl.java
new file mode 100644
index 000000000..261a84ec4
--- /dev/null
+++ b/native/src/main/java/net/md_5/bungee/NativeCipherImpl.java
@@ -0,0 +1,32 @@
+package net.md_5.bungee;
+
+class NativeCipherImpl
+{
+
+ /**
+ * Initializes the key.
+ *
+ * @param key the key to for encryption
+ * @return the pointer to key
+ */
+ native long init(byte[] key);
+
+ /**
+ * Frees the key.
+ *
+ * @param key the pointer to key
+ */
+ native void free(long key);
+
+ /**
+ * This method will encrypt some data in AES-CFB8 using the specified key.
+ *
+ * @param forEncryption encryption / decryption mode
+ * @param key the pointer to key
+ * @param iv the iv to use
+ * @param in the starting memory address for reading data
+ * @param out the starting memory address for writing data
+ * @param length the length of data to read / write
+ */
+ native void cipher(boolean forEncryption, long key, byte[] iv, long in, long out, int length);
+}
diff --git a/native/src/main/resources/native-cipher.so b/native/src/main/resources/native-cipher.so
new file mode 100755
index 000000000..262be07b1
Binary files /dev/null and b/native/src/main/resources/native-cipher.so differ
diff --git a/native/src/test/java/net/md_5/bungee/NativeCipherTest.java b/native/src/test/java/net/md_5/bungee/NativeCipherTest.java
new file mode 100644
index 000000000..ce820542b
--- /dev/null
+++ b/native/src/test/java/net/md_5/bungee/NativeCipherTest.java
@@ -0,0 +1,74 @@
+package net.md_5.bungee;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import org.junit.Assert;
+import org.junit.Test;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+public class NativeCipherTest
+{
+
+ private final byte[] plainBytes = "This is a test".getBytes();
+ private final byte[] cipheredBytes = new byte[]
+ {
+ 50, -7, 89, 1, -11, -32, -118, -48, -2, -72, 105, 97, -70, -81
+ };
+ private final SecretKey secret = new SecretKeySpec( new byte[ 16 ], "AES" );
+
+ @Test
+ public void testOpenSSL() throws Exception
+ {
+ if ( NativeCipher.isSupported() )
+ {
+ boolean loaded = NativeCipher.load();
+ Assert.assertTrue( "Native cipher failed to load!", loaded );
+
+ NativeCipher cipher = new NativeCipher();
+ System.out.println( "Testing OpenSSL cipher..." );
+ testACipher( cipher );
+ }
+ }
+
+ @Test
+ public void testJDK() throws Exception
+ {
+ // Create JDK cipher
+ BungeeCipher cipher = new FallbackCipher();
+
+ System.out.println( "Testing Java cipher..." );
+ testACipher( cipher );
+ }
+
+ /**
+ * Hackish test which can test both native and fallback ciphers using direct
+ * buffers.
+ */
+ public void testACipher(BungeeCipher cipher) throws Exception
+ {
+ // Create input buf
+ ByteBuf nativePlain = Unpooled.directBuffer( plainBytes.length );
+ nativePlain.writeBytes( plainBytes );
+ // Create expected buf
+ ByteBuf nativeCiphered = Unpooled.directBuffer( cipheredBytes.length );
+ nativeCiphered.writeBytes( cipheredBytes );
+ // Create output buf
+ ByteBuf out = Unpooled.directBuffer( plainBytes.length );
+
+ // Encrypt
+ cipher.init( true, secret );
+ cipher.cipher( nativePlain, out );
+ Assert.assertEquals( nativeCiphered, out );
+
+ out.clear();
+
+ // Decrypt
+ cipher.init( false, secret );
+ cipher.cipher( nativeCiphered, out );
+ nativePlain.resetReaderIndex();
+ Assert.assertEquals( nativePlain, out );
+
+ System.out.println( "This cipher works correctly!" );
+ }
+}
diff --git a/pom.xml b/pom.xml
index f97ca0d4e..1a1012f42 100644
--- a/pom.xml
+++ b/pom.xml
@@ -44,6 +44,7 @@
protocol
proxy
query
+ native
diff --git a/proxy/pom.xml b/proxy/pom.xml
index 1369b8527..39eafecdf 100644
--- a/proxy/pom.xml
+++ b/proxy/pom.xml
@@ -47,6 +47,12 @@
${project.version}
compile
+
+ net.md-5
+ bungeecord-native
+ ${project.version}
+ compile
+
net.md-5
bungeecord-protocol
diff --git a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java
index 11b560c5e..b30fdef18 100644
--- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java
+++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java
@@ -158,6 +158,14 @@ public class BungeeCord extends ProxyServer
logger.info( "Unable to initialize fancy terminal. To fix this on Windows, install the correct Microsoft Visual C++ 2008 Runtime" );
logger.info( "NOTE: This error is non crucial, and BungeeCord will still function correctly! Do not bug the author about it unless you are still unable to get it working" );
}
+
+ if ( !NativeCipher.load() )
+ {
+ logger.warning( "NOTE: Failed to load native code. Falling back to Java cipher." );
+ } else
+ {
+ logger.info( "Native code loaded." );
+ }
}
/**
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 eb7fe4f19..dabff27c1 100644
--- a/proxy/src/main/java/net/md_5/bungee/EncryptionUtil.java
+++ b/proxy/src/main/java/net/md_5/bungee/EncryptionUtil.java
@@ -12,7 +12,6 @@ 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.EncryptionResponse;
@@ -64,11 +63,19 @@ public class EncryptionUtil
return new SecretKeySpec( cipher.doFinal( resp.getSharedSecret() ), "AES" );
}
- public static Cipher getCipher(int opMode, Key shared) throws GeneralSecurityException
+ public static BungeeCipher getCipher(boolean forEncryption, SecretKey shared) throws GeneralSecurityException
{
- Cipher cip = Cipher.getInstance( "AES/CFB8/NoPadding" );
- cip.init( opMode, shared, new IvParameterSpec( shared.getEncoded() ) );
- return cip;
+ BungeeCipher cipher;
+ if ( NativeCipher.isLoaded() )
+ {
+ cipher = new NativeCipher();
+ } else
+ {
+ cipher = new FallbackCipher();
+ }
+
+ cipher.init( forEncryption, shared );
+ return cipher;
}
public static PublicKey getPubkey(EncryptionRequest request) throws GeneralSecurityException
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 c9afc3002..473fc0a5a 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
@@ -8,14 +8,10 @@ import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
-import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
-import net.md_5.bungee.BungeeCord;
-import net.md_5.bungee.EncryptionUtil;
-import net.md_5.bungee.UserConnection;
-import net.md_5.bungee.Util;
+import net.md_5.bungee.*;
import net.md_5.bungee.api.Callback;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.ProxyServer;
@@ -30,10 +26,10 @@ import net.md_5.bungee.api.event.ProxyPingEvent;
import net.md_5.bungee.http.HttpClient;
import net.md_5.bungee.netty.HandlerBoss;
import net.md_5.bungee.netty.ChannelWrapper;
-import net.md_5.bungee.netty.CipherDecoder;
-import net.md_5.bungee.netty.CipherEncoder;
import net.md_5.bungee.netty.PacketHandler;
import net.md_5.bungee.netty.PipelineUtils;
+import net.md_5.bungee.netty.cipher.CipherDecoder;
+import net.md_5.bungee.netty.cipher.CipherEncoder;
import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.packet.Login;
import net.md_5.bungee.protocol.packet.Handshake;
@@ -286,9 +282,9 @@ 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 );
+ BungeeCipher decrypt = EncryptionUtil.getCipher( false, sharedKey );
ch.addBefore( PipelineUtils.FRAME_DECODER, PipelineUtils.DECRYPT_HANDLER, new CipherDecoder( decrypt ) );
- Cipher encrypt = EncryptionUtil.getCipher( Cipher.ENCRYPT_MODE, sharedKey );
+ BungeeCipher encrypt = EncryptionUtil.getCipher( true, sharedKey );
ch.addBefore( PipelineUtils.FRAME_PREPENDER, PipelineUtils.ENCRYPT_HANDLER, new CipherEncoder( encrypt ) );
String encName = URLEncoder.encode( InitialHandler.this.getName(), "UTF-8" );
diff --git a/proxy/src/main/java/net/md_5/bungee/netty/CipherDecoder.java b/proxy/src/main/java/net/md_5/bungee/netty/cipher/CipherDecoder.java
similarity index 59%
rename from proxy/src/main/java/net/md_5/bungee/netty/CipherDecoder.java
rename to proxy/src/main/java/net/md_5/bungee/netty/cipher/CipherDecoder.java
index e6fe7df92..7fcc323a7 100644
--- a/proxy/src/main/java/net/md_5/bungee/netty/CipherDecoder.java
+++ b/proxy/src/main/java/net/md_5/bungee/netty/cipher/CipherDecoder.java
@@ -1,24 +1,27 @@
-package net.md_5.bungee.netty;
+package net.md_5.bungee.netty.cipher;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
+import lombok.RequiredArgsConstructor;
+import net.md_5.bungee.BungeeCipher;
import java.util.List;
-import javax.crypto.Cipher;
+@RequiredArgsConstructor
public class CipherDecoder extends MessageToMessageDecoder
{
- private final CipherBase cipher;
-
- public CipherDecoder(Cipher cipher)
- {
- this.cipher = new CipherBase( cipher );
- }
+ private final BungeeCipher cipher;
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List