Skip to content

Online (Private Key)

Online (Private Key) forwarding is a type of forwarding player data developed by Void.

As there is no community implementation yet, you need a plugin on both the server and the proxy.

First, obtain the server’s private key that Minecraft uses for authentication and encryption.

Plugin.java
package net.caunt.thevoid;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import java.lang.reflect.InvocationTargetException;
import java.security.KeyPair;
public final class EntryPoint extends JavaPlugin {
@Override
public void onEnable() {
var logger = getLogger();
try {
var server = Bukkit.getServer();
var craftServerClass = server.getClass();
var getDedicatedServerMethod = craftServerClass.getMethod("getServer");
var dedicatedServer = getDedicatedServerMethod.invoke(server);
var dedicatedServerClass = dedicatedServer.getClass();
var getKeyPairMethod = dedicatedServerClass.getMethod("getKeyPair");
var keyPair = (KeyPair)getKeyPairMethod.invoke(dedicatedServer);
var publicKey = keyPair.getPublic();
var privateKey = keyPair.getPrivate();
logger.info("Public Key (Hex): " + bytesToHex(publicKey.getEncoded()));
logger.info("Private Key (Hex): " + bytesToHex(privateKey.getEncoded()));
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
public static String bytesToHex(byte[] bytes) {
StringBuilder hexString = new StringBuilder();
for (byte b : bytes) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
}

Next, send the private key to your proxy plugin over a secure channel.

Finally, provide the key to Void when the player connects so the proxy can decrypt traffic and offer its protocol API.

Void will automatically search for the private key if AuthenticationSide is set to Server.

[Subscribe(PostOrder.Last)]
public void OnAuthenticationStarting(AuthenticationStartingEvent @event)
{
if (@event.Link.Server.Name is not "lobby")
return;
// Ensure Void targets authentication to server side,
// So it allows player to authenticate with server.
@event.Result = AuthenticationSide.Server;
}
[Subscribe]
public async ValueTask OnSearchServerPrivateKey(SearchServerPrivateKeyEvent @event)
{
if (@event.Server.Name is not "lobby")
return;
// Retrieve the private key from your server plugin or mod.
byte[] privateKey = await ValueTask.FromResult(...);
@event.Result = privateKey;
}