From acc711c640390f60b24494cd491237a0b8c2b4d9 Mon Sep 17 00:00:00 2001 From: TheMode Date: Wed, 3 Nov 2021 09:17:23 +0100 Subject: [PATCH] Revert "Volatile encryption (#515)" (#516) This reverts commit 0f15d4a2735dff0bb06d89f49e4eb9a09e40e211. --- .../login/EncryptionResponsePacket.java | 12 +++-- .../packet/client/login/LoginStartPacket.java | 3 +- .../player/PlayerSocketConnection.java | 51 +++++++++---------- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/main/java/net/minestom/server/network/packet/client/login/EncryptionResponsePacket.java b/src/main/java/net/minestom/server/network/packet/client/login/EncryptionResponsePacket.java index 5392a4416..e25afa278 100644 --- a/src/main/java/net/minestom/server/network/packet/client/login/EncryptionResponsePacket.java +++ b/src/main/java/net/minestom/server/network/packet/client/login/EncryptionResponsePacket.java @@ -22,7 +22,6 @@ import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.nio.charset.StandardCharsets; -import java.security.KeyPair; import java.util.Arrays; import java.util.UUID; @@ -51,9 +50,8 @@ public class EncryptionResponsePacket implements ClientPreplayPacket { MinecraftServer.LOGGER.error("{} tried to login with an invalid nonce!", loginUsername); return; } - final KeyPair keyPair = MojangAuth.getKeyPair(); - final SecretKey secretKey = MojangCrypt.decryptByteToSecretKey(keyPair.getPrivate(), sharedSecret); - final byte[] digestedData = MojangCrypt.digestData("", keyPair.getPublic(), secretKey); + + final byte[] digestedData = MojangCrypt.digestData("", MojangAuth.getKeyPair().getPublic(), getSecretKey()); if (digestedData == null) { // Incorrect key, probably because of the client MinecraftServer.LOGGER.error("Connection {} failed initializing encryption.", socketConnection.getRemoteAddress()); @@ -80,7 +78,7 @@ public class EncryptionResponsePacket implements ClientPreplayPacket { // Invalid response return; } - socketConnection.setEncryptionKey(secretKey); + socketConnection.setEncryptionKey(getSecretKey()); UUID profileUUID = UUID.fromString(gameProfile.get("id").getAsString() .replaceFirst("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})", "$1-$2-$3-$4-$5")); final String profileName = gameProfile.get("name").getAsString(); @@ -106,6 +104,10 @@ public class EncryptionResponsePacket implements ClientPreplayPacket { ByteArrayData.encodeByteArray(writer, verifyToken); } + private SecretKey getSecretKey() { + return MojangCrypt.decryptByteToSecretKey(MojangAuth.getKeyPair().getPrivate(), sharedSecret); + } + private byte[] getNonce() { return MojangAuth.getKeyPair().getPrivate() == null ? this.verifyToken : MojangCrypt.decryptUsingKey(MojangAuth.getKeyPair().getPrivate(), this.verifyToken); diff --git a/src/main/java/net/minestom/server/network/packet/client/login/LoginStartPacket.java b/src/main/java/net/minestom/server/network/packet/client/login/LoginStartPacket.java index f4269c978..285871e70 100644 --- a/src/main/java/net/minestom/server/network/packet/client/login/LoginStartPacket.java +++ b/src/main/java/net/minestom/server/network/packet/client/login/LoginStartPacket.java @@ -69,7 +69,8 @@ public class LoginStartPacket implements ClientPreplayPacket { } final PlayerSocketConnection socketConnection = (PlayerSocketConnection) connection; socketConnection.setConnectionState(ConnectionState.LOGIN); - socketConnection.sendPacket(new EncryptionRequestPacket(socketConnection)); + EncryptionRequestPacket encryptionRequestPacket = new EncryptionRequestPacket(socketConnection); + socketConnection.sendPacket(encryptionRequestPacket); } else { final boolean bungee = BungeeCordProxy.isEnabled(); // Offline diff --git a/src/main/java/net/minestom/server/network/player/PlayerSocketConnection.java b/src/main/java/net/minestom/server/network/player/PlayerSocketConnection.java index 153e80ff1..203c19eb2 100644 --- a/src/main/java/net/minestom/server/network/player/PlayerSocketConnection.java +++ b/src/main/java/net/minestom/server/network/player/PlayerSocketConnection.java @@ -36,7 +36,6 @@ import java.nio.channels.SocketChannel; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import java.util.zip.DataFormatException; import java.util.zip.Inflater; @@ -48,18 +47,18 @@ import java.util.zip.Inflater; @ApiStatus.Internal public class PlayerSocketConnection extends PlayerConnection { private final static Logger LOGGER = LoggerFactory.getLogger(PlayerSocketConnection.class); - private static final AtomicReferenceFieldUpdater ENCRYPTION_UPDATER = - AtomicReferenceFieldUpdater.newUpdater(PlayerSocketConnection.class, EncryptionInfo.class, "encryptionInfo"); private final Worker worker; private final SocketChannel channel; private SocketAddress remoteAddress; - private volatile EncryptionInfo encryptionInfo; + private boolean encrypted = false; private boolean compressed = false; //Could be null. Only used for Mojang Auth private byte[] nonce = new byte[4]; + private Cipher decryptCipher; + private Cipher encryptCipher; // Data from client packets private String loginUsername; @@ -93,11 +92,11 @@ public class PlayerSocketConnection extends PlayerConnection { public void processPackets(Worker.Context workerContext, PacketProcessor packetProcessor) { final BinaryBuffer readBuffer = workerContext.readBuffer; // Decrypt data - EncryptionInfo encryptionInfo = this.encryptionInfo; - if (encryptionInfo != null) { + if (encrypted) { + final Cipher cipher = decryptCipher; ByteBuffer input = readBuffer.asByteBuffer(0, readBuffer.writerOffset()); try { - encryptionInfo.decryptCipher().update(input, input.duplicate()); + cipher.update(input, input.duplicate()); } catch (ShortBufferException e) { MinecraftServer.getExceptionManager().handleException(e); return; @@ -176,10 +175,12 @@ public class PlayerSocketConnection extends PlayerConnection { * @throws IllegalStateException if encryption is already enabled for this connection */ public void setEncryptionKey(@NotNull SecretKey secretKey) { - final EncryptionInfo prev = ENCRYPTION_UPDATER.getAndSet(this, - new EncryptionInfo(MojangCrypt.getCipher(2, secretKey), MojangCrypt.getCipher(1, secretKey))); - if (prev != null) - throw new IllegalStateException("Encryption was already enabled for this connection"); + Check.stateCondition(encrypted, "Encryption is already enabled!"); + synchronized (bufferLock) { + this.decryptCipher = MojangCrypt.getCipher(2, secretKey); + this.encryptCipher = MojangCrypt.getCipher(1, secretKey); + this.encrypted = true; + } } /** @@ -230,20 +231,19 @@ public class PlayerSocketConnection extends PlayerConnection { @ApiStatus.Internal public void write(@NotNull ByteBuffer buffer, int index, int length) { - EncryptionInfo encryptionInfo = this.encryptionInfo; - if (encryptionInfo != null) { - ByteBuffer output = PacketUtils.localBuffer(); - try { - encryptionInfo.encryptCipher().update(buffer.slice(index, length), output); - buffer = output.flip(); - index = 0; - } catch (ShortBufferException e) { - MinecraftServer.getExceptionManager().handleException(e); - return; - } - } - synchronized (bufferLock) { + if (encrypted) { // Encryption support + ByteBuffer output = PacketUtils.localBuffer(); + try { + this.encryptCipher.update(buffer.slice(index,length), output); + buffer = output.flip(); + index = 0; + } catch (ShortBufferException e) { + MinecraftServer.getExceptionManager().handleException(e); + return; + } + } + BinaryBuffer localBuffer = tickBuffer.getPlain(); final int capacity = localBuffer.capacity(); if (length <= capacity) { @@ -472,7 +472,4 @@ public class PlayerSocketConnection extends PlayerConnection { public void setNonce(byte[] nonce) { this.nonce = nonce; } - - public record EncryptionInfo(Cipher decryptCipher, Cipher encryptCipher) { - } }